1212 - minor
1313 - major
1414 default : ' patch'
15+ build_arm64 :
16+ description : ' Build ARM64 architecture (slower, ~5min extra)'
17+ required : false
18+ type : boolean
19+ default : false
1520 push :
1621 tags :
1722 - ' v*.*.*'
@@ -108,6 +113,7 @@ jobs:
108113 outputs :
109114 digest : ${{ steps.build-push.outputs.digest }}
110115 image_name : ${{ steps.prep.outputs.image_name }}
116+ platforms : ${{ steps.prep.outputs.platforms }}
111117 steps :
112118 - name : Checkout
113119 uses : actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -125,10 +131,44 @@ jobs:
125131 - name : Prepare derived values
126132 id : prep
127133 run : |
128- # Derive image name from repository (convert to lowercase)
129- IMAGE_NAME=$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]')
134+ # Validate IMAGE_NAME secret is set
135+ if [ -z "${{ secrets.IMAGE_NAME }}" ]; then
136+ echo "❌ ERROR: IMAGE_NAME secret is not configured"
137+ echo "Please add IMAGE_NAME secret in repository settings"
138+ echo "Expected format: lowercase repository name (e.g., 'ghostclass')"
139+ exit 1
140+ fi
141+
142+ # Use IMAGE_NAME from secrets (consistent with pipeline.yml)
143+ IMAGE_NAME="${{ secrets.IMAGE_NAME }}"
130144 echo "image_name=${IMAGE_NAME}" >> $GITHUB_OUTPUT
131145
146+ # Debug output
147+ echo "✓ Using IMAGE_NAME: ${IMAGE_NAME}"
148+ echo " Full image path: ghcr.io/${{ github.repository_owner }}/${IMAGE_NAME}"
149+
150+ # Determine build platforms
151+ # For tag pushes: Build both AMD64 and ARM64 (full release)
152+ # For workflow_dispatch: Respect user's build_arm64 input
153+ if [ "${{ github.event_name }}" == "push" ]; then
154+ # Tag push - always build multi-arch for full releases
155+ PLATFORMS="linux/amd64,linux/arm64"
156+ echo "📦 Tag push detected - building multi-architecture"
157+ elif [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
158+ if [ "${{ github.event.inputs.build_arm64 }}" == "true" ]; then
159+ PLATFORMS="linux/amd64,linux/arm64"
160+ echo "📦 Manual dispatch with ARM64 enabled"
161+ else
162+ PLATFORMS="linux/amd64"
163+ echo "📦 Manual dispatch - AMD64 only (faster build)"
164+ fi
165+ else
166+ # Default fallback
167+ PLATFORMS="linux/amd64"
168+ fi
169+ echo "platforms=${PLATFORMS}" >> $GITHUB_OUTPUT
170+ echo " Build platforms: ${PLATFORMS}"
171+
132172 APP_DOMAIN="${{ secrets.NEXT_PUBLIC_APP_DOMAIN }}"
133173 echo "app_url=https://${APP_DOMAIN}" >> $GITHUB_OUTPUT
134174 echo "sitemap_url=https://${APP_DOMAIN}/sitemap.xml" >> $GITHUB_OUTPUT
@@ -147,7 +187,7 @@ jobs:
147187 fi
148188 echo "created=$TIMESTAMP" >> $GITHUB_OUTPUT
149189
150- - name : Build & push multi-platform image
190+ - name : Build & push Docker image
151191 id : build-push
152192 uses : docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
153193 with :
@@ -159,7 +199,11 @@ jobs:
159199 ${{ github.event_name == 'workflow_dispatch' && format('ghcr.io/{0}/{1}:latest', github.repository_owner, steps.prep.outputs.image_name) || '' }}
160200 secrets : |
161201 sentry_token=${{ secrets.SENTRY_AUTH_TOKEN }}
162- platforms : linux/amd64,linux/arm64
202+ platforms : ${{ steps.prep.outputs.platforms }}
203+
204+ # Enable layer caching for faster builds
205+ cache-from : type=gha
206+ cache-to : type=gha,mode=max
163207 build-args : |
164208 APP_COMMIT_SHA=${{ github.sha }}
165209 SOURCE_DATE_EPOCH=${{ secrets.SOURCE_DATE_EPOCH }}
@@ -349,7 +393,11 @@ jobs:
349393 - name : Generate verification instructions
350394 env :
351395 IMAGE_NAME : ${{ needs.build-and-release.outputs.image_name }}
396+ PLATFORMS : ${{ needs.build-and-release.outputs.platforms }}
352397 run : |
398+ # Convert platforms to readable format (same transformation as release notes)
399+ PLATFORM_LIST=$(echo "${PLATFORMS}" | sed 's/linux\///g; s/,/, /g')
400+
353401 cat > ./artifacts/VERIFY.md << EOF
354402 # Release Verification Instructions
355403
@@ -400,7 +448,7 @@ jobs:
400448
401449 - **Image**: \`ghcr.io/${{ github.repository_owner }}/${IMAGE_NAME}:${{ needs.calculate-version.outputs.version_tag }}\`
402450 - **Digest**: \`${{ needs.build-and-release.outputs.digest }}\`
403- - **Platforms**: \`linux/amd64\`, \`linux/arm64 \`
451+ - **Platforms**: \`${PLATFORM_LIST} \`
404452 - **Version**: \`${{ needs.calculate-version.outputs.version }}\`
405453
406454 ## Additional Tags
@@ -419,54 +467,60 @@ jobs:
419467 - name : Create GitHub Release
420468 env :
421469 IMAGE_NAME : ${{ needs.build-and-release.outputs.image_name }}
422- uses : softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
423- with :
424- tag_name : ${{ needs.calculate-version.outputs.version_tag }}
425- name : Release ${{ needs.calculate-version.outputs.version_tag }}
426- body : |
427- ## Release ${{ needs.calculate-version.outputs.version_tag }}
428-
429- This release includes:
430- - 🐳 Multi-platform Docker images (linux/amd64, linux/arm64)
431- - 🔐 Signed images and artifacts using Sigstore cosign
432- - 📋 Software Bill of Materials (SBOM) in CycloneDX format
433- - ✅ Build provenance attestations
434- - 🔍 SHA256 checksums for all artifacts
435-
436- ### Docker Images
437-
438- ```bash
439- docker pull ghcr.io/${{ github.repository_owner }}/${{ needs.build-and-release.outputs.image_name }}:${{ needs.calculate-version.outputs.version_tag }}
440- ```
441-
442- **Image Digest**: `${{ needs.build-and-release.outputs.digest }}`
443-
444- ### Verification
445-
446- See [VERIFY.md](https://github.com/${{ github.repository }}/releases/download/${{ needs.calculate-version.outputs.version_tag }}/VERIFY.md) for detailed verification instructions.
447-
448- ### Quick Verification
449-
450- ```bash
451- # Verify image signature
452- cosign verify \
453- --certificate-identity-regexp="^https://github.com/${{ github.repository }}" \
454- --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
455- ghcr.io/${{ github.repository_owner }}/${{ needs.build-and-release.outputs.image_name }}:${{ needs.calculate-version.outputs.version_tag }}
456-
457- # Verify attestation
458- gh attestation verify oci://ghcr.io/${{ github.repository_owner }}/${{ needs.build-and-release.outputs.image_name }}:${{ needs.calculate-version.outputs.version_tag }} --owner ${{ github.repository_owner }}
459- ```
460-
461- ---
462-
463- **Full Changelog**: ${{ github.server_url }}/${{ github.repository }}/compare/${{ steps.prev_version.outputs.changelog_text }}
464- files : |
465- ./artifacts/sbom.json
466- ./artifacts/sbom.json.bundle
467- ./artifacts/checksums.txt
468- ./artifacts/VERIFY.md
469- draft : false
470- prerelease : false
471- generate_release_notes : true
472- fail_on_unmatched_files : true
470+ PLATFORMS : ${{ needs.build-and-release.outputs.platforms }}
471+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
472+ run : |
473+ # Convert platforms to readable format for release notes
474+ PLATFORM_LIST=$(echo "${PLATFORMS}" | sed 's/linux\///g; s/,/, /g')
475+
476+ # Determine if multi-platform
477+ if [[ "${PLATFORMS}" == *","* ]]; then
478+ PLATFORM_DESC="Multi-platform Docker images (${PLATFORM_LIST})"
479+ else
480+ PLATFORM_DESC="Docker image (${PLATFORM_LIST})"
481+ fi
482+
483+ gh release create "${{ needs.calculate-version.outputs.version_tag }}" \
484+ --title "Release ${{ needs.calculate-version.outputs.version_tag }}" \
485+ --notes "## Release ${{ needs.calculate-version.outputs.version_tag }}
486+
487+ This release includes:
488+ - 🐳 ${PLATFORM_DESC}
489+ - 🔐 Signed images and artifacts using Sigstore cosign
490+ - 📋 Software Bill of Materials (SBOM) in CycloneDX format
491+ - ✅ Build provenance attestations
492+ - 🔍 SHA256 checksums for all artifacts
493+
494+ ### Docker Images
495+
496+ \`\`\`bash
497+ docker pull ghcr.io/${{ github.repository_owner }}/${IMAGE_NAME}:${{ needs.calculate-version.outputs.version_tag }}
498+ \`\`\`
499+
500+ **Image Digest**: \`${{ needs.build-and-release.outputs.digest }}\`
501+
502+ ### Verification
503+
504+ See [VERIFY.md](https://github.com/${{ github.repository }}/releases/download/${{ needs.calculate-version.outputs.version_tag }}/VERIFY.md) for detailed verification instructions.
505+
506+ ### Quick Verification
507+
508+ \`\`\`bash
509+ # Verify image signature
510+ cosign verify \\
511+ --certificate-identity-regexp=\"^https://github.com/${{ github.repository }}\" \\
512+ --certificate-oidc-issuer=\"https://token.actions.githubusercontent.com\" \\
513+ ghcr.io/${{ github.repository_owner }}/${IMAGE_NAME}:${{ needs.calculate-version.outputs.version_tag }}
514+
515+ # Verify attestation
516+ gh attestation verify oci://ghcr.io/${{ github.repository_owner }}/${IMAGE_NAME}:${{ needs.calculate-version.outputs.version_tag }} --owner ${{ github.repository_owner }}
517+ \`\`\`
518+
519+ ---
520+
521+ **Full Changelog**: ${{ github.server_url }}/${{ github.repository }}/compare/${{ steps.prev_version.outputs.changelog_text }}" \
522+ ./artifacts/sbom.json \
523+ ./artifacts/sbom.json.bundle \
524+ ./artifacts/checksums.txt \
525+ ./artifacts/VERIFY.md \
526+ --draft=false
0 commit comments