|
| 1 | +name: Generate Cover Images |
| 2 | + |
| 3 | +on: |
| 4 | + pull_request: |
| 5 | + types: [opened, synchronize] |
| 6 | + paths: |
| 7 | + - 'src/content/blog/**/index.md' |
| 8 | + |
| 9 | +permissions: |
| 10 | + contents: write |
| 11 | + pull-requests: write |
| 12 | + |
| 13 | +jobs: |
| 14 | + generate-covers: |
| 15 | + name: Generate Missing Cover Images |
| 16 | + runs-on: ubuntu-latest |
| 17 | + steps: |
| 18 | + - name: Checkout PR branch |
| 19 | + uses: actions/checkout@v4 |
| 20 | + with: |
| 21 | + ref: ${{ github.head_ref }} |
| 22 | + fetch-depth: 0 |
| 23 | + token: ${{ secrets.GITHUB_TOKEN }} |
| 24 | + |
| 25 | + - name: Setup Node.js |
| 26 | + uses: actions/setup-node@v4 |
| 27 | + with: |
| 28 | + node-version: '20' |
| 29 | + |
| 30 | + - name: Install dependencies |
| 31 | + run: npm ci |
| 32 | + |
| 33 | + - name: Find blog posts needing covers |
| 34 | + id: find-posts |
| 35 | + run: | |
| 36 | + # Get list of changed files in this PR |
| 37 | + CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD) |
| 38 | +
|
| 39 | + # Find blog post directories with changes but no cover.png |
| 40 | + POSTS_NEEDING_COVERS="" |
| 41 | +
|
| 42 | + for file in $CHANGED_FILES; do |
| 43 | + # Check if it's a blog post index.md |
| 44 | + if [[ "$file" =~ ^src/content/blog/[0-9]+/.+/index\.md$ ]]; then |
| 45 | + POST_DIR=$(dirname "$file") |
| 46 | + COVER_PATH="$POST_DIR/cover.png" |
| 47 | +
|
| 48 | + # Check if cover.png already exists |
| 49 | + if [ ! -f "$COVER_PATH" ]; then |
| 50 | + POSTS_NEEDING_COVERS="$POSTS_NEEDING_COVERS $POST_DIR" |
| 51 | + echo "Post needs cover: $POST_DIR" |
| 52 | + else |
| 53 | + echo "Post already has cover: $POST_DIR" |
| 54 | + fi |
| 55 | + fi |
| 56 | + done |
| 57 | +
|
| 58 | + # Trim leading space and output |
| 59 | + POSTS_NEEDING_COVERS=$(echo "$POSTS_NEEDING_COVERS" | xargs) |
| 60 | + echo "posts=$POSTS_NEEDING_COVERS" >> $GITHUB_OUTPUT |
| 61 | +
|
| 62 | + if [ -z "$POSTS_NEEDING_COVERS" ]; then |
| 63 | + echo "No posts need cover images" |
| 64 | + echo "has_posts=false" >> $GITHUB_OUTPUT |
| 65 | + else |
| 66 | + echo "has_posts=true" >> $GITHUB_OUTPUT |
| 67 | + fi |
| 68 | +
|
| 69 | + - name: Generate cover images |
| 70 | + if: steps.find-posts.outputs.has_posts == 'true' |
| 71 | + run: | |
| 72 | + for post_dir in ${{ steps.find-posts.outputs.posts }}; do |
| 73 | + echo "Generating cover for: $post_dir" |
| 74 | + node scripts/generate-cover.js "$post_dir" |
| 75 | + done |
| 76 | +
|
| 77 | + - name: Commit and push cover images |
| 78 | + if: steps.find-posts.outputs.has_posts == 'true' |
| 79 | + run: | |
| 80 | + git config user.name "github-actions[bot]" |
| 81 | + git config user.email "github-actions[bot]@users.noreply.github.com" |
| 82 | +
|
| 83 | + # Add only the generated cover images |
| 84 | + for post_dir in ${{ steps.find-posts.outputs.posts }}; do |
| 85 | + git add "$post_dir/cover.png" |
| 86 | + done |
| 87 | +
|
| 88 | + # Check if there are changes to commit |
| 89 | + if git diff --staged --quiet; then |
| 90 | + echo "No new cover images to commit" |
| 91 | + echo "committed=false" >> $GITHUB_OUTPUT |
| 92 | + else |
| 93 | + git commit -m "ci(blog): generate cover images for new posts [skip ci]" |
| 94 | + git push |
| 95 | + echo "committed=true" >> $GITHUB_OUTPUT |
| 96 | + fi |
| 97 | +
|
| 98 | + - name: Comment on PR with cover images |
| 99 | + if: steps.find-posts.outputs.has_posts == 'true' |
| 100 | + env: |
| 101 | + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 102 | + run: | |
| 103 | + # Get the commit SHA after push |
| 104 | + COMMIT_SHA=$(git rev-parse HEAD) |
| 105 | +
|
| 106 | + # Build comment body with all generated covers |
| 107 | + COMMENT="## 🖼️ Generated Cover Images\n\n" |
| 108 | +
|
| 109 | + for post_dir in ${{ steps.find-posts.outputs.posts }}; do |
| 110 | + # Extract post title from directory name |
| 111 | + POST_SLUG=$(basename "$post_dir") |
| 112 | + POST_YEAR=$(basename $(dirname "$post_dir")) |
| 113 | +
|
| 114 | + # Build raw GitHub URL for the image |
| 115 | + IMAGE_URL="https://raw.githubusercontent.com/${{ github.repository }}/${COMMIT_SHA}/${post_dir}/cover.png" |
| 116 | +
|
| 117 | + COMMENT="${COMMENT}### ${POST_YEAR}/${POST_SLUG}\n\n" |
| 118 | + COMMENT="${COMMENT}\n\n" |
| 119 | + done |
| 120 | +
|
| 121 | + COMMENT="${COMMENT}---\n*If you'd like a different style, delete the cover image and push again, or generate one locally with \`npm run cover\`.*" |
| 122 | +
|
| 123 | + # Post comment to PR |
| 124 | + echo -e "$COMMENT" | gh pr comment ${{ github.event.pull_request.number }} --body-file - |
0 commit comments