Skip to content

Commit 773950d

Browse files
CopilotdevakesuCopilot
authored
Optimize Docker build performance with layer caching and conditional multi-arch (#360)
* Fix auto-version workflow: create releases for version branches (#359) * Initial plan * Fix auto-version-and-tag workflow to create releases for version branches Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Initial plan * Fix incomplete Docker pull command by using IMAGE_NAME secret Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Add Docker layer caching and conditional ARM64 builds for performance Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Update docs/BUILD_PERFORMANCE.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Devanarayanan <fusion@devakesu.com> * Update .github/workflows/release.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Devanarayanan <fusion@devakesu.com> * Make platform messaging dynamic based on actual build platforms Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Improve sed command robustness for platform formatting Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Fix gh release create: add GH_TOKEN and remove conflicting --generate-notes Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> * Apply consistent platform formatting in VERIFY.md Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> --------- Signed-off-by: Devanarayanan <fusion@devakesu.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: devakesu <61821107+devakesu@users.noreply.github.com> Co-authored-by: Devanarayanan <fusion@devakesu.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent e16e169 commit 773950d

File tree

3 files changed

+338
-56
lines changed

3 files changed

+338
-56
lines changed

.github/workflows/pipeline.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ jobs:
7373
sentry_token=${{ secrets.SENTRY_AUTH_TOKEN }}
7474
7575
platforms: linux/amd64
76+
77+
# Enable layer caching for faster builds
78+
cache-from: type=gha
79+
cache-to: type=gha,mode=max
7680

7781
build-args: |
7882
APP_COMMIT_SHA=${{ github.sha }}

.github/workflows/release.yml

Lines changed: 110 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ on:
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

Comments
 (0)