Align scratch runtime and releases with image hardening baseline

Move container HTTP to8080, remove capabilities/curl, preserve demo UI without mutating assets, patch vulnerable Go dependencies and document migration/runtime contracts. Gate releases on source/final-image security evidence and unresolved policy exceptions.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Cédric Verstraeten
2026-11-04 22:03:04 +01:00
co-authored by Copilot App
parent 9553b1b4b9
commit e3acd64a57
34 changed files with 1585 additions and 491 deletions
+326
View File
@@ -0,0 +1,326 @@
name: Verified image publication
on:
workflow_call:
inputs:
tag:
type: string
default: ""
source_ref:
type: string
required: true
nightly:
type: boolean
default: false
publish_latest:
type: boolean
default: false
secrets:
DOCKER_USERNAME:
required: true
DOCKER_PASSWORD:
required: true
permissions:
contents: read
# No parallel run can overwrite a customer tag while another run verifies it.
concurrency:
group: image-publication-${{ inputs.nightly && 'nightly' || 'release' }}
cancel-in-progress: false
defaults:
run:
shell: bash
jobs:
resolve:
runs-on: ubuntu-24.04
permissions:
contents: write
outputs:
sha: ${{ steps.source.outputs.sha }}
tag: ${{ steps.source.outputs.tag }}
created: ${{ steps.source.outputs.created }}
matrix: ${{ steps.source.outputs.matrix }}
repository: ${{ steps.source.outputs.repository }}
staging_repository: ${{ steps.source.outputs.staging_repository }}
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- name: Validate requested tag
env:
TAG: ${{ inputs.tag }}
NIGHTLY: ${{ inputs.nightly }}
run: |
if [[ "$NIGHTLY" != true && ! "$TAG" =~ ^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,127}$ ]]; then
echo "Invalid Docker tag" >&2
exit 1
fi
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
ref: ${{ inputs.source_ref }}
path: source
persist-credentials: false
- name: Resolve once for every architecture
id: source
env:
TAG: ${{ inputs.tag }}
NIGHTLY: ${{ inputs.nightly }}
run: |
sha=$(git -C source rev-parse HEAD)
[[ "$sha" =~ ^[a-f0-9]{40}$ ]]
created=$(date -u +%Y-%m-%dT%H:%M:%SZ)
repository=kerberos/agent
staging_repository=kerberos/agent-arch
matrix='{"include":[{"architecture":"amd64","runner":"ubuntu-24.04"},{"architecture":"arm64","runner":"ubuntu-24.04-arm"}]}'
if [[ "$NIGHTLY" == true ]]; then
TAG="${sha:0:7}"
repository=kerberos/agent-nightly
staging_repository="$repository"
# Keep arm/v6: the pinned Go trixie base currently lacks this platform.
# Its build must fail rather than publishing an incomplete nightly index.
matrix='{"include":[{"architecture":"amd64","runner":"ubuntu-24.04"},{"architecture":"arm64","runner":"ubuntu-24.04-arm"},{"architecture":"arm/v7","runner":"ubuntu-24.04"},{"architecture":"arm/v6","runner":"ubuntu-24.04"}]}'
fi
{
echo "sha=$sha"
echo "tag=$TAG"
echo "created=$created"
echo "repository=$repository"
echo "staging_repository=$staging_repository"
echo "matrix=$matrix"
} >> "$GITHUB_OUTPUT"
mkdir -p evidence
printf '%s\n' "$sha" > evidence/source-revision.txt
printf '%s\n' "$created" > evidence/created.txt
printf '%s\n' "$TAG" > evidence/version.txt
cp .github/scripts/image-release-policy.json evidence/runtime-policy.json
- name: Validate fail-closed policy helpers
run: python3 .github/scripts/test-image-policy.py
- name: Keep existing GitHub release unpublished until gates pass
if: ${{ !inputs.nightly }}
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.source.outputs.tag }}
run: |
# A release:created event may refer to an already public release.
# Return it to draft immediately; do not imply this run has verified it.
gh api --paginate "repos/$GITHUB_REPOSITORY/releases" --jq '.[]' | jq -s . > evidence/releases.json
release_id=$(jq -r --arg tag "$TAG" '.[] | select(.tag_name == $tag) | .id' evidence/releases.json)
if [[ -n "$release_id" ]]; then
gh api --method PATCH "repos/$GITHUB_REPOSITORY/releases/$release_id" -F draft=true > evidence/draft-release.json
fi
- name: Install verified scanner release
env:
GH_TOKEN: ${{ github.token }}
run: bash .github/scripts/install-trivy.sh
- name: Source/UI dependency vulnerability, secret and misconfiguration gate with SPDX SBOM
run: python3 .github/scripts/image-policy.py source evidence/source
- name: Retain source policy evidence
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: image-source-evidence
path: evidence/
retention-days: 90
if-no-files-found: error
build:
needs: resolve
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.resolve.outputs.matrix) }}
env:
ARCH: ${{ matrix.architecture }}
VERSION: ${{ needs.resolve.outputs.tag }}
REVISION: ${{ needs.resolve.outputs.sha }}
CREATED: ${{ needs.resolve.outputs.created }}
STAGING_REPOSITORY: ${{ needs.resolve.outputs.staging_repository }}
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
ref: ${{ needs.resolve.outputs.sha }}
path: source
persist-credentials: false
- uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3
if: ${{ startsWith(matrix.architecture, 'arm/') }}
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build immutable staging image with maximal provenance
id: build
run: |
mkdir -p evidence
arch="${ARCH//\//-}"
echo "arch=$arch" >> "$GITHUB_OUTPUT"
staging="$STAGING_REPOSITORY:ci-$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT-$arch"
printf '%s\n' "$REVISION" > evidence/source-revision.txt
docker buildx build --platform "linux/$ARCH" --provenance=mode=max \
--build-arg "VERSION=$VERSION" --build-arg "REVISION=$REVISION" --build-arg "CREATED=$CREATED" \
--label "org.opencontainers.image.version=$VERSION" \
--label "org.opencontainers.image.revision=$REVISION" \
--label "org.opencontainers.image.created=$CREATED" \
--label "org.opencontainers.image.source=https://github.com/$GITHUB_REPOSITORY" \
--metadata-file evidence/build-metadata.json --tag "$staging" --push source
digest=$(jq -er '."containerimage.digest"' evidence/build-metadata.json)
[[ "$digest" =~ ^sha256:[a-f0-9]{64}$ ]]
image="$STAGING_REPOSITORY@$digest"
printf '%s\n' "$image" > evidence/image.txt
docker buildx imagetools inspect "$image" --format '{{json .Provenance}}' > evidence/provenance.json
python3 .github/scripts/image-evidence.py evidence
- name: Extract release payload and smoke test the exact staged image
run: |
image=$(cat evidence/image.txt)
docker pull --platform "linux/$ARCH" "$image"
cid=$(docker create --platform "linux/$ARCH" "$image")
trap 'docker rm -f "$cid" >/dev/null' EXIT
docker cp "$cid:/home/agent" output
# Run the existing smoke interface, including emulated nightly architectures.
DOCKER_DEFAULT_PLATFORM="linux/$ARCH" sh source/deployments/docker/test-image.sh "$image"
arch="${ARCH//\//-}"
tar -cf "agent-$arch.tar" -C output .
rm -rf output
- name: Retain build evidence even on failure
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: image-build-${{ steps.build.outputs.arch || strategy.job-index }}
path: evidence/
retention-days: 90
if-no-files-found: error
- name: Retain existing binary artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: agent-${{ steps.build.outputs.arch }}.tar
path: agent-*.tar
if-no-files-found: error
verify-publish:
needs: [resolve, build]
runs-on: ubuntu-24.04
permissions:
contents: write
id-token: write
env:
REPOSITORY: ${{ needs.resolve.outputs.repository }}
STAGING_REPOSITORY: ${{ needs.resolve.outputs.staging_repository }}
VERSION: ${{ needs.resolve.outputs.tag }}
REVISION: ${{ needs.resolve.outputs.sha }}
PUBLISH_LATEST: ${{ inputs.publish_latest }}
MATRIX: ${{ needs.resolve.outputs.matrix }}
GH_TOKEN: ${{ github.token }}
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
path: artifacts
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Install scanner
run: bash .github/scripts/install-trivy.sh
- uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
with:
cosign-release: v3.1.4
- name: Assemble candidate index without publishing version/latest
run: |
mkdir -p evidence
images=()
while IFS= read -r arch; do
directory="artifacts/image-build-${arch//\//-}"
[[ "$(cat "$directory/source-revision.txt")" == "$REVISION" ]]
image=$(cat "$directory/image.txt")
[[ "$image" =~ ^${STAGING_REPOSITORY}@sha256:[a-f0-9]{64}$ ]]
images+=("$image")
done < <(jq -r '.include[].architecture' <<< "$MATRIX")
candidate="$REPOSITORY:ci-$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT"
docker buildx imagetools create --tag "$candidate" "${images[@]}"
digest=$(docker buildx imagetools inspect "$candidate" --format '{{.Manifest.Digest}}')
[[ "$digest" =~ ^sha256:[a-f0-9]{64}$ ]]
image="$REPOSITORY@$digest"
printf '%s\n' "$image" > evidence/final-image.txt
printf '%s\n' "$REVISION" > evidence/source-revision.txt
docker buildx imagetools inspect "$image" --raw > evidence/index.json
docker buildx imagetools inspect "$image" --format '{{json .Provenance}}' > evidence/provenance.json
python3 .github/scripts/image-evidence.py evidence
# Every requested runnable platform must be present, with no silent omissions.
jq -r '.manifests[] | select(.platform.os == "linux") |
.platform | .architecture + (if .variant and .architecture == "arm" then "/" + .variant else "" end)' \
evidence/index.json | sort > evidence/actual-platforms.txt
jq -r '.include[].architecture' <<< "$MATRIX" | sort > evidence/expected-platforms.txt
diff -u evidence/expected-platforms.txt evidence/actual-platforms.txt
- name: Scan every final-index platform and enforce findings/errors
run: |
image=$(cat evidence/final-image.txt)
failed=0
while IFS= read -r arch; do
# Generation uses exit-code 0 only for findings; the helper explicitly
# blocks HIGH/CRITICAL/UNKNOWN and any scanner/inventory/SBOM error.
if ! python3 .github/scripts/image-policy.py "$image" "evidence/${arch//\//-}" --platform "linux/$arch"; then
failed=1
fi
done < <(jq -r '.include[].architecture' <<< "$MATRIX")
exit "$failed"
- name: Required release policy exception gate
run: |
# The product deliberately retains remote terminal/PTY support.
# No approval exists. Keep this release-only gate separate from scans;
# there is no dispatch input/environment variable that can waive it.
cp .github/scripts/image-release-policy.json evidence/runtime-policy.json
python3 .github/scripts/image-release-policy.py evidence/runtime-policy.json
- name: Sign and verify the FINAL multi-platform digest using GitHub OIDC
run: |
image=$(cat evidence/final-image.txt)
# Fulcio's SAN is job_workflow_ref for this local reusable workflow,
# not the caller's filename. Bind the exact repository and executing ref.
# For example: https://github.com/kerberos-io/agent/.github/workflows/image-release.yml@refs/heads/master
identity="https://github.com/$GITHUB_REPOSITORY/.github/workflows/image-release.yml@$GITHUB_REF"
printf '%s\n' "$identity" > evidence/signing-identity.txt
cosign sign --yes --bundle evidence/signature.sigstore.json "$image"
cosign verify --certificate-identity "$identity" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
"$image" > evidence/signature-verification.json
- name: Publish only the already verified and signed digest
run: |
image=$(cat evidence/final-image.txt)
while IFS= read -r arch; do
arch="${arch//\//-}"
staged=$(cat "artifacts/image-build-$arch/image.txt")
# Preserve the existing architecture tag names, after all gates.
docker buildx imagetools create --tag "$STAGING_REPOSITORY:arch-$arch-$VERSION" "$staged"
done < <(jq -r '.include[].architecture' <<< "$MATRIX")
docker buildx imagetools create --tag "$REPOSITORY:$VERSION" "$image"
[[ "$(docker buildx imagetools inspect "$REPOSITORY:$VERSION" --format '{{.Manifest.Digest}}')" == "${image##*@}" ]]
if [[ "$PUBLISH_LATEST" == true ]]; then
docker buildx imagetools create --tag "$REPOSITORY:latest" "$image"
[[ "$(docker buildx imagetools inspect "$REPOSITORY:latest" --format '{{.Manifest.Digest}}')" == "${image##*@}" ]]
fi
- name: Retain final reports/SBOM/provenance/signature even on failure
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: image-final-evidence
path: evidence/
retention-days: 90
if-no-files-found: error
- name: Attach binaries and all evidence, then publish GitHub release
if: ${{ !inputs.nightly }}
run: |
tar -czf image-security-evidence.tar.gz evidence artifacts/image-*
# Create a draft only if absent. API errors must not masquerade as absence.
gh api --paginate "repos/$GITHUB_REPOSITORY/releases" --jq '.[]' | jq -s . > releases.json
if ! jq -e --arg tag "$VERSION" '.[] | select(.tag_name == $tag)' releases.json >/dev/null; then
gh release create "$VERSION" --target "$REVISION" --title "$VERSION" --notes "" --draft
fi
gh release upload "$VERSION" artifacts/agent-*.tar/agent-*.tar image-security-evidence.tar.gz --clobber
gh release edit "$VERSION" --draft=false --latest --title "$VERSION"
+12 -55
View File
@@ -1,62 +1,19 @@
name: Nightly build
on:
# Triggers the workflow every day at 9PM (CET).
schedule:
- cron: "0 22 * * *"
# Allows manual triggering from the Actions tab.
workflow_dispatch:
permissions:
contents: write
jobs:
nightly-build-amd64:
runs-on: ubuntu-latest
strategy:
matrix:
architecture: [amd64]
steps:
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Checkout
uses: actions/checkout@v4
with:
ref: master
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
- name: Available platforms
run: echo ${{ steps.buildx.outputs.platforms }}
- name: Run Buildx
run: docker buildx build --build-arg VERSION=$(echo $GITHUB_SHA | cut -c1-7) --platform linux/${{matrix.architecture}} -t kerberos/agent-nightly:arch-$(echo ${{matrix.architecture}} | tr / -)-$(echo $GITHUB_SHA | cut -c1-7) --push .
- name: Create new and append to manifest
run: docker buildx imagetools create -t kerberos/agent-nightly:$(echo $GITHUB_SHA | cut -c1-7) kerberos/agent-nightly:arch-$(echo ${{matrix.architecture}} | tr / -)-$(echo $GITHUB_SHA | cut -c1-7)
nightly-build-other:
runs-on: ubuntu-latest
strategy:
matrix:
architecture: [arm64, arm/v7, arm/v6]
steps:
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Checkout
uses: actions/checkout@v4
with:
ref: master
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
- name: Available platforms
run: echo ${{ steps.buildx.outputs.platforms }}
- name: Run Buildx
run: docker buildx build --build-arg VERSION=$(echo $GITHUB_SHA | cut -c1-7) --platform linux/${{matrix.architecture}} -t kerberos/agent-nightly:arch-$(echo ${{matrix.architecture}} | tr / -)-$(echo $GITHUB_SHA | cut -c1-7) --push .
- name: Create new and append to manifest
run: docker buildx imagetools create --append -t kerberos/agent-nightly:$(echo $GITHUB_SHA | cut -c1-7) kerberos/agent-nightly:arch-$(echo ${{matrix.architecture}} | tr / -)-$(echo $GITHUB_SHA | cut -c1-7)
nightly:
permissions:
contents: read
id-token: write
uses: ./.github/workflows/image-release.yml
with:
source_ref: master
nightly: true
secrets: inherit
+80 -21
View File
@@ -1,38 +1,97 @@
name: Build pull request
on:
pull_request:
types: [opened, synchronize]
types: [opened, synchronize, reopened]
env:
REPO: kerberos/agent
permissions:
contents: read
defaults:
run:
shell: bash
jobs:
build:
runs-on: ${{ matrix.runner }}
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include:
- architecture: amd64
runner: ubuntu-24.04
- architecture: arm64
runner: ubuntu-24.04-arm
env:
ARCH: ${{ matrix.architecture }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run Build
run: |
docker build --build-arg VERSION=$(echo "${{ github.event.pull_request.head.sha }}" | cut -c1-7) -t ${{ matrix.architecture }} .
CID=$(docker create ${{matrix.architecture}})
docker cp ${CID}:/home/agent ./output-${{matrix.architecture}}
docker rm ${CID}
- name: Test production image
run: sh deployments/docker/test-image.sh ${{ matrix.architecture }}
- name: Strip binary
run: tar -cf agent-${{matrix.architecture}}.tar -C output-${{matrix.architecture}} . && rm -rf output-${{matrix.architecture}}
- name: Upload artifact
uses: actions/upload-artifact@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
name: agent-${{matrix.architecture}}.tar
path: agent-${{matrix.architecture}}.tar
persist-credentials: false
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
ref: ${{ github.sha }}
path: source
persist-credentials: false
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
- name: Validate fail-closed policy helpers
run: python3 .github/scripts/test-image-policy.py
- name: Install scanner
env:
GH_TOKEN: ${{ github.token }}
run: bash .github/scripts/install-trivy.sh
- name: Build once, populating OCI metadata from CI
env:
BUILDX_METADATA_PROVENANCE: max
run: |
mkdir -p evidence/build .ci-tools
revision=$(git -C source rev-parse HEAD)
version="${revision:0:7}"
created=$(date -u +%Y-%m-%dT%H:%M:%SZ)
printf '%s\n' "$revision" > evidence/build/source-revision.txt
# A local Docker load cannot retain attestations. The second exporter
# retains attestations without registry writes. Never upload the full
# image as scan evidence: it may contain a secret that correctly failed scans.
docker buildx build --platform "linux/$ARCH" --provenance=mode=max \
--build-arg "VERSION=$version" --build-arg "REVISION=$revision" --build-arg "CREATED=$created" \
--label "org.opencontainers.image.version=$version" \
--label "org.opencontainers.image.revision=$revision" \
--label "org.opencontainers.image.created=$created" \
--label "org.opencontainers.image.source=https://github.com/$GITHUB_REPOSITORY" \
--metadata-file evidence/build/build-metadata.json --tag "$ARCH" \
--output type=docker --output type=oci,dest=.ci-tools/pr-image.oci.tar source
jq -e '."buildx.build.provenance" | select(type == "object" and length > 0)' \
evidence/build/build-metadata.json > evidence/build/provenance.json
python3 .github/scripts/image-evidence.py evidence/build
- name: Extract release payload
run: |
cid=$(docker create "$ARCH")
trap 'docker rm -f "$cid" >/dev/null' EXIT
docker cp "$cid:/home/agent" "output-$ARCH"
- name: Test production image
run: sh source/deployments/docker/test-image.sh "$ARCH"
- name: Strip binary
run: tar -cf "agent-$ARCH.tar" -C "output-$ARCH" . && rm -rf "output-$ARCH"
- name: Source/UI dependency and final image gates with SPDX SBOMs
run: |
failed=0
if ! python3 .github/scripts/image-policy.py source evidence/source; then
failed=1
fi
if ! python3 .github/scripts/image-policy.py "$ARCH" "evidence/$ARCH" --platform "linux/$ARCH"; then
failed=1
fi
exit "$failed"
- name: Upload artifact only after secret and vulnerability gates pass
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: agent-${{ matrix.architecture }}.tar
path: agent-${{ matrix.architecture }}.tar
if-no-files-found: error
- name: Retain reports on failure
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: image-pr-evidence-${{ matrix.architecture }}
path: evidence/
retention-days: 90
if-no-files-found: error
+17 -141
View File
@@ -1,160 +1,36 @@
name: Bump release
on:
workflow_dispatch:
inputs:
bump:
description: "Which part of the version to bump"
description: Which part of the version to bump
required: true
default: patch
type: choice
options:
- major
- minor
- patch
options: [major, minor, patch]
permissions:
contents: write
env:
REPO: kerberos/agent
contents: read
jobs:
# Determine the next version, create the GitHub release and expose the tag.
bump-release:
uses: uug-ai/workflows/.github/workflows/release-bump.yml@main
permissions:
contents: write
# Verified revision supports reserving a tag with an unpublished draft.
uses: uug-ai/workflows/.github/workflows/release-bump.yml@f31d4260a833e82228ca0e9b9163231a970feeb8
with:
bump: ${{ github.event.inputs.bump }}
bump: ${{ inputs.bump }}
draft: true
secrets: inherit
# Publish the platform image to the uug-ai GitHub Container Registry
# (ghcr.io/uug-ai/agent-platform).
#release:
# needs: bump-release
# uses: uug-ai/workflows/.github/workflows/release-create.yml@main
# with:
# organization: uug-ai
# project: ${{ github.event.repository.name }}
# tag: ${{ needs.bump-release.outputs.tag }}
# docker_context: "."
# create_gitops_pr: false
# runner_matrix: >-
# [
# {"architecture":"amd64","runner":"ubuntu-24.04"},
# {"architecture":"arm64","runner":"ubuntu-24.04-arm"}
# ]
# secrets: inherit
# Everything below mirrors the agent's own release-create.yml pipeline and
# publishes the multi-arch image to the kerberos/agent Docker Hub repo, driven
# by the freshly bumped tag instead of a `release: created` event.
build-amd64:
release:
needs: bump-release
runs-on: ubuntu-24.04
permissions:
contents: write
strategy:
matrix:
architecture: [amd64]
steps:
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Checkout
uses: actions/checkout@v4
- name: Run Build
run: |
docker build --provenance=false --build-arg VERSION=${{ needs.bump-release.outputs.tag }} -t ${{matrix.architecture}} .
CID=$(docker create ${{matrix.architecture}})
docker cp ${CID}:/home/agent ./output-${{matrix.architecture}}
docker rm ${CID}
- name: Strip binary
run: tar -cf agent-${{matrix.architecture}}.tar -C output-${{matrix.architecture}} . && rm -rf output-${{matrix.architecture}}
- name: Build and push Docker image
run: |
docker tag ${{matrix.architecture}} $REPO-arch:arch-${{matrix.architecture}}-${{ needs.bump-release.outputs.tag }}
docker push $REPO-arch:arch-${{matrix.architecture}}-${{ needs.bump-release.outputs.tag }}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: agent-${{matrix.architecture}}.tar
path: agent-${{matrix.architecture}}.tar
build-arm64:
needs: bump-release
runs-on: ubuntu-24.04-arm
permissions:
contents: write
strategy:
matrix:
architecture: [arm64]
steps:
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Checkout
uses: actions/checkout@v4
- name: Run Build
run: |
docker build --provenance=false --build-arg VERSION=${{ needs.bump-release.outputs.tag }} -t ${{matrix.architecture}} .
CID=$(docker create ${{matrix.architecture}})
docker cp ${CID}:/home/agent ./output-${{matrix.architecture}}
docker rm ${CID}
- name: Strip binary
run: tar -cf agent-${{matrix.architecture}}.tar -C output-${{matrix.architecture}} . && rm -rf output-${{matrix.architecture}}
- name: Build and push Docker image
run: |
docker tag ${{matrix.architecture}} $REPO-arch:arch-${{matrix.architecture}}-${{ needs.bump-release.outputs.tag }}
docker push $REPO-arch:arch-${{matrix.architecture}}-${{ needs.bump-release.outputs.tag }}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: agent-${{matrix.architecture}}.tar
path: agent-${{matrix.architecture}}.tar
create-manifest:
runs-on: ubuntu-24.04
needs: [bump-release, build-amd64, build-arm64]
steps:
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Create and push multi-arch manifest
run: |
docker manifest create $REPO:${{ needs.bump-release.outputs.tag }} \
$REPO-arch:arch-amd64-${{ needs.bump-release.outputs.tag }} \
$REPO-arch:arch-arm64-${{ needs.bump-release.outputs.tag }}
docker manifest push $REPO:${{ needs.bump-release.outputs.tag }}
- name: Create and push latest manifest
run: |
docker manifest create $REPO:latest \
$REPO-arch:arch-amd64-${{ needs.bump-release.outputs.tag }} \
$REPO-arch:arch-arm64-${{ needs.bump-release.outputs.tag }}
docker manifest push $REPO:latest
create-release:
runs-on: ubuntu-24.04
needs: [bump-release, build-amd64, build-arm64]
permissions:
contents: write
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
- name: Create a release
uses: ncipollo/release-action@v1
with:
latest: true
allowUpdates: true
name: ${{ needs.bump-release.outputs.tag }}
tag: ${{ needs.bump-release.outputs.tag }}
generateReleaseNotes: false
omitBodyDuringUpdate: true
artifacts: "agent-*.tar/agent-*.tar"
id-token: write
uses: ./.github/workflows/image-release.yml
with:
tag: ${{ needs.bump-release.outputs.tag }}
source_ref: ${{ format('refs/tags/{0}', needs.bump-release.outputs.tag) }}
publish_latest: true
secrets: inherit
+12 -109
View File
@@ -5,118 +5,21 @@ on:
workflow_dispatch:
inputs:
tag:
description: "Tag for the Docker image"
description: Tag for the Docker image
required: true
default: "test"
default: test
env:
REPO: kerberos/agent
permissions:
contents: read
jobs:
build-amd64:
runs-on: ubuntu-24.04
release:
permissions:
contents: write
strategy:
matrix:
architecture: [amd64]
steps:
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Checkout
uses: actions/checkout@v4
- name: Run Build
run: |
docker build --provenance=false --build-arg VERSION=${{github.event.inputs.tag || github.ref_name}} -t ${{matrix.architecture}} .
CID=$(docker create ${{matrix.architecture}})
docker cp ${CID}:/home/agent ./output-${{matrix.architecture}}
docker rm ${CID}
- name: Strip binary
run: tar -cf agent-${{matrix.architecture}}.tar -C output-${{matrix.architecture}} . && rm -rf output-${{matrix.architecture}}
- name: Build and push Docker image
run: |
docker tag ${{matrix.architecture}} $REPO-arch:arch-${{matrix.architecture}}-${{github.event.inputs.tag || github.ref_name}}
docker push $REPO-arch:arch-${{matrix.architecture}}-${{github.event.inputs.tag || github.ref_name}}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: agent-${{matrix.architecture}}.tar
path: agent-${{matrix.architecture}}.tar
build-arm64:
runs-on: ubuntu-24.04-arm
permissions:
contents: write
strategy:
matrix:
architecture: [arm64]
steps:
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Checkout
uses: actions/checkout@v4
- name: Run Build
run: |
docker build --provenance=false --build-arg VERSION=${{github.event.inputs.tag || github.ref_name}} -t ${{matrix.architecture}} .
CID=$(docker create ${{matrix.architecture}})
docker cp ${CID}:/home/agent ./output-${{matrix.architecture}}
docker rm ${CID}
- name: Strip binary
run: tar -cf agent-${{matrix.architecture}}.tar -C output-${{matrix.architecture}} . && rm -rf output-${{matrix.architecture}}
- name: Build and push Docker image
run: |
docker tag ${{matrix.architecture}} $REPO-arch:arch-${{matrix.architecture}}-${{github.event.inputs.tag || github.ref_name}}
docker push $REPO-arch:arch-${{matrix.architecture}}-${{github.event.inputs.tag || github.ref_name}}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: agent-${{matrix.architecture}}.tar
path: agent-${{matrix.architecture}}.tar
create-manifest:
runs-on: ubuntu-24.04
needs: [build-amd64, build-arm64]
steps:
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Create and push multi-arch manifest
run: |
docker manifest create $REPO:${{ github.event.inputs.tag || github.ref_name }} \
$REPO-arch:arch-amd64-${{github.event.inputs.tag || github.ref_name}} \
$REPO-arch:arch-arm64-${{github.event.inputs.tag || github.ref_name}}
docker manifest push $REPO:${{ github.event.inputs.tag || github.ref_name }}
- name: Create and push latest manifest
run: |
docker manifest create $REPO:latest \
$REPO-arch:arch-amd64-${{github.event.inputs.tag || github.ref_name}} \
$REPO-arch:arch-arm64-${{github.event.inputs.tag || github.ref_name}}
docker manifest push $REPO:latest
if: github.event.inputs.tag == 'test'
create-release:
runs-on: ubuntu-24.04
needs: [build-amd64, build-arm64]
permissions:
contents: write
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
- name: Create a release
uses: ncipollo/release-action@v1
with:
latest: true
allowUpdates: true
name: ${{ github.event.inputs.tag || github.ref_name }}
tag: ${{ github.event.inputs.tag || github.ref_name }}
generateReleaseNotes: false
omitBodyDuringUpdate: true
artifacts: "agent-*.tar/agent-*.tar"
id-token: write
uses: ./.github/workflows/image-release.yml
with:
tag: ${{ inputs.tag || github.event.release.tag_name }}
source_ref: ${{ github.event_name == 'release' && format('refs/tags/{0}', github.event.release.tag_name) || github.sha }}
publish_latest: ${{ github.event_name == 'workflow_dispatch' && inputs.tag == 'test' }}
secrets: inherit