build: allow main branch publishing and add comprehensive OCI metadata for multi-arch images (#65)

* feat(ci): add OCI annotations and metadata to multi-arch images

- Include created, source, revision, ref-name, vendor & license
- Add title and description for Sure Rails app multi-arch image
- Dynamically annotate version when tag builds are triggered

* chore(ci): add nightly tag with weekday pattern to tag config

* fix(ci): allow publish workflow to push images from main branch

- Update conditional checks to include refs/heads/main
- Reflect new condition in workflow comments for clarity

* fix(ci): set image version label only for tag builds in metadata

* fix(ci): avoid quotations being passed as CLI argument

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Himank Dave <93311724+steadyfall@users.noreply.github.com>

* refactor(ci): remove deprecated `::set-output` command

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Himank Dave <93311724+steadyfall@users.noreply.github.com>

---------

Signed-off-by: Himank Dave <93311724+steadyfall@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Himank Dave
2025-08-04 18:41:05 -04:00
committed by GitHub
parent b3af64dce1
commit eba42e2f71

View File

@@ -1,12 +1,13 @@
# Reference: https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners
# Conditions for pushing the image to GHCR:
# - Triggered by push to default branch (`main`)
# - Triggered by push to a version tag (`v*`)
# - Triggered by a scheduled run
# - Triggered manually via `workflow_dispatch` with `push: true`
#
# Conditional expression:
# startsWith(github.ref, 'refs/tags/v') || github.event_name == 'schedule' || github.event.inputs.push
# github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || github.event_name == 'schedule' || github.event.inputs.push
name: Publish Docker image
@@ -84,6 +85,7 @@ jobs:
BASE_CONFIG="type=sha,format=long"
if [[ $GITHUB_EVENT_NAME == "schedule" ]]; then
BASE_CONFIG+=$'\n'"type=schedule,pattern=nightly"
BASE_CONFIG+=$'\n'"type=schedule,pattern=nightly-{{date 'ddd'}}"
elif [[ "$GITHUB_REF" == refs/tags/v* ]]; then
BASE_CONFIG="type=semver,pattern={{version}}"
BASE_CONFIG+=$'\n'"type=raw,value=stable"
@@ -94,6 +96,10 @@ jobs:
echo EOF
} >> $GITHUB_ENV
- name: Get current date (RFC 3339 format)
id: date
run: echo "date=$(date -Iseconds)" >> $GITHUB_OUTPUT
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@v5.6.0
@@ -101,6 +107,13 @@ jobs:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
flavor: latest=false
tags: ${{ env.TAGS_SPEC }}
labels: |
org.opencontainers.image.version=${{ startsWith(github.ref, 'refs/tags/v') && github.ref_name || '' }}
org.opencontainers.image.created=${{ steps.date.outputs.date }}
org.opencontainers.image.ref.name=${{ github.ref_name }}
org.opencontainers.image.vendor=we-promise
org.opencontainers.image.title=Sure
org.opencontainers.image.description=A multi-arch Docker image for the Sure Rails app
- name: Publish 'linux/${{ matrix.platform }}' image by digest
uses: docker/build-push-action@v6.16.0
@@ -119,7 +132,7 @@ jobs:
outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},name-canonical=true,push-by-digest=true,oci-mediatypes=true
- name: Export the Docker image digest
if: ${{ startsWith(github.ref, 'refs/tags/v') || github.event_name == 'schedule' || github.event.inputs.push }}
if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || github.event_name == 'schedule' || github.event.inputs.push }}
run: |
mkdir -p "${RUNNER_TEMP}"/digests
echo "${DIGEST#sha256:}" > "${RUNNER_TEMP}/digests/digest-${PLATFORM}"
@@ -128,7 +141,7 @@ jobs:
PLATFORM: ${{ matrix.platform }}
- name: Upload the Docker image digest
if: ${{ startsWith(github.ref, 'refs/tags/v') || github.event_name == 'schedule' || github.event.inputs.push }}
if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || github.event_name == 'schedule' || github.event.inputs.push }}
uses: actions/upload-artifact@v4.6.2
with:
name: digest-${{ matrix.platform }}
@@ -138,7 +151,7 @@ jobs:
merge:
name: Merge multi-arch manifest & push multi-arch tag
if: ${{ startsWith(github.ref, 'refs/tags/v') || github.event_name == 'schedule' || github.event.inputs.push }}
if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') || github.event_name == 'schedule' || github.event.inputs.push }}
needs: [build]
timeout-minutes: 60
@@ -182,10 +195,29 @@ jobs:
image_args+=("${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:$(<"${DIGESTS_DIR}/digest-${PLATFORM}")")
done
annotations=(
"index:org.opencontainers.image.created=$(date -Iseconds)"
'index:org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}'
'index:org.opencontainers.image.revision=${{ github.sha }}'
'index:org.opencontainers.image.ref.name=${{ github.ref_name }}'
'index:org.opencontainers.image.vendor=we-promise'
'index:org.opencontainers.image.licenses=AGPL-3.0'
'index:org.opencontainers.image.title=Sure'
'index:org.opencontainers.image.description=A multi-arch Docker image for the Sure Rails app'
)
annotation_args=()
for annotation in "${annotations[@]}"; do
annotation_args+=("--annotation=${annotation}")
done
if [[ $GITHUB_REF_TYPE == "tag" ]]; then
annotation_args+=("--annotation=index:org.opencontainers.image.version=$GITHUB_REF_NAME")
fi
attempts=0
until docker buildx imagetools create \
--annotation "index:org.opencontainers.image.description=A multi-arch Docker image for the Sure Rails app" \
"${tag_args[@]}" "${image_args[@]}" \
"${annotation_args[@]}" \
"${tag_args[@]}" \
"${image_args[@]}" \
; do
attempts=$((attempts + 1))
if [[ $attempts -ge 3 ]]; then