Skip to content

fix: source release-config.sh from main in build-docker.yaml #142

fix: source release-config.sh from main in build-docker.yaml

fix: source release-config.sh from main in build-docker.yaml #142

Workflow file for this run

name: Build Docker
on:
pull_request:
types: [labeled, synchronize]
branches:
- main
- release/*
workflow_call:
inputs:
tag:
description: 'Tag to build and publish Docker images for (e.g. v0.6.0)'
required: true
type: string
workflow_dispatch:
inputs:
tag:
description: 'Tag to build and publish Docker images for (e.g. v0.6.0)'
required: true
type: string
concurrency:
group: docker-${{ (github.event_name == 'workflow_call' || github.event_name == 'workflow_dispatch') && inputs.tag || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
REGISTRY: docker.cloudsmith.io
REGISTRY_NAMESPACE: circle/arc-network
jobs:
build:
if: >-
github.event_name == 'workflow_call' ||
github.event_name == 'workflow_dispatch' ||
contains(github.event.pull_request.labels.*.name, 'build-docker')
name: Build ${{ matrix.image }} (${{ matrix.platform }})
permissions:
contents: read
id-token: write
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
image:
- arc-execution
- arc-consensus
platform:
- linux/amd64
- linux/arm64
include:
- platform: linux/amd64
arch: amd64
runner: ubuntu-latest
- platform: linux/arm64
arch: arm64
runner: ubuntu-24.04-arm
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
ref: ${{ (github.event_name == 'workflow_call' || github.event_name == 'workflow_dispatch') && format('refs/tags/{0}', inputs.tag) || github.ref }}
submodules: recursive
fetch-depth: 0
- name: Resolve image metadata
id: vars
env:
EVENT_NAME: ${{ github.event_name }}
INPUT_TAG: ${{ inputs.tag }}
run: |
SHA="$(git rev-parse HEAD)"
if [[ "$EVENT_NAME" == "workflow_call" || "$EVENT_NAME" == "workflow_dispatch" ]]; then
# A release branch's release-config.sh can predate functions this workflow
# (always run from main) expects, so pull main's copy rather than whatever
# is checked out at the tagged commit above.
git show origin/main:scripts/release-config.sh > "${RUNNER_TEMP}/release-config.sh"
# shellcheck source=/dev/null
source "${RUNNER_TEMP}/release-config.sh"
if ! release_docker_image_version_from_tag "$INPUT_TAG" >/dev/null; then
echo "::error::Invalid tag format: '$INPUT_TAG' (expected e.g. v1.2.3 or v1.2.3-rc.1)"
exit 1
fi
fi
{
echo "full_hash=${SHA}"
echo "short_hash=${SHA::8}"
echo "git_version=$(git describe --tags --always --dirty 2>/dev/null || echo 'v0.0.0-unknown')"
} >> "$GITHUB_OUTPUT"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Build image
id: build
uses: docker/bake-action@6614cfa25eff9a0b2b2697efb0b6159e7680d584 # v7.2.0
with:
source: .
files: docker-bake.hcl
targets: ${{ matrix.image }}
set: |
${{ matrix.image }}.platform=${{ matrix.platform }}
${{ matrix.image }}.tags=
${{ matrix.image }}.output=type=oci,tar=false,dest=/tmp/image
env:
BUILDX_NO_DEFAULT_ATTESTATIONS: 1
GITHUB_TOKEN: ${{ github.token }}
GIT_COMMIT_HASH: ${{ steps.vars.outputs.full_hash }}
GIT_VERSION: ${{ steps.vars.outputs.git_version }}
GIT_SHORT_HASH: ${{ steps.vars.outputs.short_hash }}
- name: Trivy vulnerability scan
uses: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1 # v0.35.0
with:
input: /tmp/image
format: sarif
output: trivy-results.sarif
severity: CRITICAL
limit-severities-for-sarif: true
exit-code: '1'
- name: Upload Trivy scan results
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: trivy-${{ matrix.image }}-${{ matrix.arch }}
path: trivy-results.sarif
- name: Login to Cloudsmith
if: ${{ github.event_name == 'workflow_call' || github.event_name == 'workflow_dispatch' }}
uses: ./.github/actions/cloudsmith-login
with:
registry: ${{ env.REGISTRY }}
- name: Push image by digest
if: ${{ github.event_name == 'workflow_call' || github.event_name == 'workflow_dispatch' }}
env:
IMAGE: ${{ env.REGISTRY }}/${{ env.REGISTRY_NAMESPACE }}/${{ matrix.image }}
BAKE_METADATA: ${{ steps.build.outputs.metadata }}
MATRIX_IMAGE: ${{ matrix.image }}
MATRIX_PLATFORM: ${{ matrix.platform }}
run: |
DIGEST=$(echo "${BAKE_METADATA}" | jq -r --arg img "${MATRIX_IMAGE}" '.[$img]."containerimage.digest"')
if [ -z "${DIGEST}" ] || [ "${DIGEST}" = "null" ]; then
echo "::error::Failed to extract digest from build metadata"
exit 1
fi
skopeo copy "oci:/tmp/image" "docker://${IMAGE}@${DIGEST}" --digestfile /tmp/push-digest
rm -rf /tmp/image
REGISTRY_DIGEST=$(cat /tmp/push-digest)
if [ "${DIGEST}" != "${REGISTRY_DIGEST}" ]; then
echo "::warning::Bake metadata digest ${DIGEST} differs from registry digest ${REGISTRY_DIGEST}"
fi
PLATFORM_SLUG=$(echo "${MATRIX_PLATFORM}" | tr '/' '-')
mkdir -p "/tmp/digests/${MATRIX_IMAGE}"
echo "${REGISTRY_DIGEST}" > "/tmp/digests/${MATRIX_IMAGE}/${PLATFORM_SLUG}"
- name: Upload digest
if: ${{ github.event_name == 'workflow_call' || github.event_name == 'workflow_dispatch' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: digest-${{ matrix.image }}-${{ matrix.arch }}
path: /tmp/digests/${{ matrix.image }}/*
if-no-files-found: error
manifest:
if: ${{ github.event_name == 'workflow_call' || github.event_name == 'workflow_dispatch' }}
name: Manifest ${{ matrix.image }}
permissions:
contents: read
id-token: write
attestations: write
needs: [build]
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
image:
- arc-execution
- arc-consensus
steps:
- name: Checkout
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
ref: ${{ format('refs/tags/{0}', inputs.tag) }}
sparse-checkout: |
.github/actions
scripts
fetch-depth: 0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Login to Cloudsmith
uses: ./.github/actions/cloudsmith-login
with:
registry: ${{ env.REGISTRY }}
- name: Download digests
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: digest-${{ matrix.image }}-*
merge-multiple: true
path: /tmp/digests
- name: Create and inspect multi-arch manifest
id: manifest
env:
IMAGE: ${{ env.REGISTRY }}/${{ env.REGISTRY_NAMESPACE }}/${{ matrix.image }}
RELEASE_TAG: ${{ inputs.tag }}
run: |
# A release branch's release-config.sh can predate functions this workflow
# (always run from main) expects, so pull main's copy rather than whatever
# is checked out at the tagged commit above.
git show origin/main:scripts/release-config.sh > "${RUNNER_TEMP}/release-config.sh"
# shellcheck source=/dev/null
source "${RUNNER_TEMP}/release-config.sh"
if ! IMAGE_VERSION="$(release_docker_image_version_from_tag "$RELEASE_TAG")"; then
echo "::error::Invalid tag format: '$RELEASE_TAG' (expected e.g. v1.2.3 or v1.2.3-rc.1)"
exit 1
fi
# Defense in depth: never publish a vX.Y.Z-tagged image, even if the
# sourced parser regresses and stops stripping the leading "v".
IMAGE_VERSION="${IMAGE_VERSION#v}"
SHA="$(git rev-parse HEAD)"
SHORT_HASH="${SHA::8}"
TAG="${IMAGE}:${IMAGE_VERSION}"
SHA_TAG="${IMAGE}:${IMAGE_VERSION}-${SHORT_HASH}"
# Build digest args from all platform artifacts
DIGEST_ARGS=()
for f in /tmp/digests/*; do
DIGEST_ARGS+=("${IMAGE}@$(cat "$f")")
done
if [ ${#DIGEST_ARGS[@]} -eq 0 ]; then
echo "::error::No digest files found"
exit 1
fi
# Create and push the manifest list
docker buildx imagetools create -t "${TAG}" -t "${SHA_TAG}" "${DIGEST_ARGS[@]}"
MANIFEST_DIGEST=$(docker buildx imagetools inspect "${TAG}" --raw | sha256sum | awk '{print "sha256:"$1}')
echo "digest=${MANIFEST_DIGEST}" >> "$GITHUB_OUTPUT"
echo "image-with-digest=${IMAGE}@${MANIFEST_DIGEST}" >> "$GITHUB_OUTPUT"
- name: Generate SBOM
continue-on-error: true
uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
with:
image: ${{ steps.manifest.outputs.image-with-digest }}
artifact-name: sbom-${{ matrix.image }}.spdx.json
output-file: sbom-${{ matrix.image }}.spdx.json
upload-release-assets: false
- name: Attest build provenance
uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
with:
subject-name: ${{ env.REGISTRY }}/${{ env.REGISTRY_NAMESPACE }}/${{ matrix.image }}
subject-digest: ${{ steps.manifest.outputs.digest }}
push-to-registry: true
- name: Attest SBOM
uses: actions/attest-sbom@07e74fc4e78d1aad915e867f9a094073a9f71527 # v4.0.0
with:
subject-name: ${{ env.REGISTRY }}/${{ env.REGISTRY_NAMESPACE }}/${{ matrix.image }}
subject-digest: ${{ steps.manifest.outputs.digest }}
sbom-path: sbom-${{ matrix.image }}.spdx.json
push-to-registry: true