Files
agent/.github/workflows/pr-build.yml
T
Cédric VerstraetenandCopilot App e3acd64a57 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>
2026-11-04 22:03:04 +01:00

98 lines
4.0 KiB
YAML

name: Build pull request
on:
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: read
defaults:
run:
shell: bash
jobs:
build:
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- architecture: amd64
runner: ubuntu-24.04
- architecture: arm64
runner: ubuntu-24.04-arm
env:
ARCH: ${{ matrix.architecture }}
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
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