Spaces:
Running
Running
| name: Zarf Build and Sign (a11oy) | |
| # Real Zarf package build path for a11oy targeting uds-v0.3.1-rc.1. | |
| # | |
| # Per founder reframe 2026-05-30 ~15:27 EDT, a11oy is the Warhacker focal demo | |
| # target (the governed agentic execution fabric). This workflow is the | |
| # v0.3.1-rc.1 build path: it builds the OCI image from the repo Dockerfile, runs a | |
| # real `zarf package create` against the in-repo deploy/zarf.yaml skeleton, signs the | |
| # resulting .tar.zst with cosign keyless (reusing the pattern proven in | |
| # vessels/.github/workflows/uds-sign-release.yml), and uploads the signed assets to a | |
| # GitHub release named uds-v0.3.1-rc.1. | |
| # | |
| # DELIBERATE SAFETY DESIGN (matches the founder's doctrine): | |
| # * Trigger is workflow_dispatch ONLY — never on tag push, never automatic. | |
| # The founder triggers it manually after reviewing this PR. No tag is moved. | |
| # * The release uds-v0.3.1-rc.1 is created BY this dispatch (a new name), not an | |
| # existing tag. `gh release create … --target main` cuts it at dispatch time. | |
| # * Image is pushed only when this dispatch runs. Opening/merging the PR pushes | |
| # nothing. | |
| # | |
| # Produces the four things the PhD Systems Scope-2 audit found MISSING from the | |
| # v0.2.0 source-archive tarballs: | |
| # zarf.yaml, checksums.txt, images/ (OCI layout), components/ (compressed). | |
| # | |
| # Cosign keyless verification (no stored key; GitHub OIDC + Fulcio + Rekor): | |
| # cosign verify-blob \ | |
| # --certificate-identity-regexp \ | |
| # "https://github.com/szl-holdings/a11oy/.github/workflows/zarf-build-and-sign.yml.*" \ | |
| # --certificate-oidc-issuer https://token.actions.githubusercontent.com \ | |
| # --bundle zarf-package-a11oy-amd64-uds-v0.3.1-rc.1.tar.zst.sigstore.json \ | |
| # zarf-package-a11oy-amd64-uds-v0.3.1-rc.1.tar.zst | |
| # | |
| # References: | |
| # Zarf package create: https://docs.zarf.dev/ref/create/ | |
| # UDS Core docs: https://uds.defenseunicorns.com/core/ | |
| # Cosign keyless: https://docs.sigstore.dev/cosign/signing/signing_with_blobs/ | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| release_name: | |
| description: 'Release name to create and upload to (founder-controlled)' | |
| required: true | |
| default: 'uds-v0.3.1-rc.1' | |
| type: string | |
| push_image: | |
| description: 'Push the OCI image to GHCR (set true only when ready)' | |
| required: true | |
| default: false | |
| type: boolean | |
| permissions: | |
| contents: read | |
| jobs: | |
| build-sign-release: | |
| name: Build image, zarf create, sign, release | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write # create release + upload assets | |
| packages: write # push OCI image to GHCR (only if push_image=true) | |
| id-token: write # cosign keyless OIDC token | |
| env: | |
| IMAGE: ghcr.io/szl-holdings/a11oy | |
| # The image tag a11oy's deploy/zarf.yaml (and deploy/manifests) resolve to. | |
| # NOTE: deploy/zarf.yaml currently pins ghcr.io/szl-holdings/a11oy:v1.0.0-alpha. | |
| # For the rc, we build+tag rc.1 and retag :v1.0.0-alpha so `zarf package create` | |
| # can vendor the layer the skeleton references without editing the skeleton. | |
| IMAGE_TAG: uds-v0.3.1-rc.1 | |
| SKELETON_TAG: v1.0.0-alpha | |
| steps: | |
| - name: Checkout main | |
| uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 | |
| - name: Log in to GHCR | |
| if: ${{ inputs.push_image }} | |
| uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build OCI image from repo Dockerfile | |
| uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 | |
| with: | |
| context: . | |
| file: Dockerfile | |
| # push only when explicitly requested via dispatch input | |
| push: ${{ inputs.push_image }} | |
| load: ${{ inputs.push_image == false }} | |
| tags: | | |
| ${{ env.IMAGE }}:${{ env.IMAGE_TAG }} | |
| ${{ env.IMAGE }}:${{ env.SKELETON_TAG }} | |
| labels: | | |
| org.opencontainers.image.source=https://github.com/szl-holdings/a11oy | |
| org.opencontainers.image.description=A11oy — Brand Orchestration Layer | |
| org.opencontainers.image.revision=${{ github.sha }} | |
| org.opencontainers.image.version=${{ env.IMAGE_TAG }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Install Zarf | |
| # Download Zarf v0.77.0 binary directly from GitHub releases. | |
| # Replaces defenseunicorns/setup-zarf action (not in org allowlist). | |
| # Zarf v0.77.0 adds keyless signing + offline verification. | |
| run: | | |
| ZARF_VERSION=v0.77.0 | |
| curl -fsSL "https://github.com/zarf-dev/zarf/releases/download/${ZARF_VERSION}/zarf_${ZARF_VERSION}_Linux_amd64" \ | |
| -o /usr/local/bin/zarf | |
| chmod +x /usr/local/bin/zarf | |
| zarf version | |
| - name: zarf package create (dry-run inspect of the skeleton) | |
| run: | | |
| echo "Skeleton at deploy/zarf.yaml:" | |
| cat deploy/zarf.yaml | |
| echo "---" | |
| # Confirm the package config is parseable and lists the expected refs. | |
| # `zarf dev lint` validates the schema without building. | |
| zarf dev lint deploy/ || echo "lint reported findings (see above)" | |
| - name: zarf package create (real build from deploy/ skeleton) | |
| run: | | |
| # Build the real Zarf package. With the image present locally | |
| # (load=true) or pushed to GHCR (push_image=true), Zarf vendors the | |
| # image layer into images/ — producing a deployable package, not a | |
| # source archive. | |
| zarf package create deploy/ \ | |
| --confirm \ | |
| --architecture amd64 \ | |
| --output . | |
| echo "=== built artifacts ===" | |
| ls -la zarf-package-*.tar.zst | |
| - name: Inspect package — prove the 4 required parts exist | |
| run: | | |
| PKG=$(ls zarf-package-a11oy-amd64-*.tar.zst | head -1) | |
| echo "Inspecting ${PKG}" | |
| # List the tarball contents and assert the four parts the PhD audit | |
| # said were missing from the v0.2.0 source archives. | |
| tar -I zstd -tf "${PKG}" > /tmp/pkg-listing.txt || zstd -dc "${PKG}" | tar -tf - > /tmp/pkg-listing.txt | |
| echo "--- listing (head) ---"; head -40 /tmp/pkg-listing.txt | |
| for part in "zarf.yaml" "checksums.txt" "images/" "components/"; do | |
| if grep -q "${part}" /tmp/pkg-listing.txt; then | |
| echo "PRESENT: ${part}" | |
| else | |
| echo "MISSING: ${part}"; exit 1 | |
| fi | |
| done | |
| echo "All four required parts present." | |
| - name: Rename package to release-friendly name | |
| id: pkg | |
| run: | | |
| SRC=$(ls zarf-package-a11oy-amd64-*.tar.zst | head -1) | |
| DST="zarf-package-a11oy-amd64-${{ env.IMAGE_TAG }}.tar.zst" | |
| [ "${SRC}" != "${DST}" ] && mv "${SRC}" "${DST}" || true | |
| sha256sum "${DST}" > "${DST}.sha256" | |
| echo "tarball=${DST}" >> "$GITHUB_OUTPUT" | |
| echo "sha256=${DST}.sha256" >> "$GITHUB_OUTPUT" | |
| echo "bundle=${DST}.sigstore.json" >> "$GITHUB_OUTPUT" | |
| - name: Install cosign | |
| uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 | |
| - name: Sign tarball with cosign keyless (GitHub OIDC) | |
| env: | |
| COSIGN_EXPERIMENTAL: "1" | |
| run: | | |
| cosign sign-blob \ | |
| --yes \ | |
| --bundle "${{ steps.pkg.outputs.bundle }}" \ | |
| "${{ steps.pkg.outputs.tarball }}" | |
| echo "Signed -> ${{ steps.pkg.outputs.bundle }}" | |
| - name: Verify signature (self-check) | |
| env: | |
| COSIGN_EXPERIMENTAL: "1" | |
| run: | | |
| cosign verify-blob \ | |
| --certificate-identity-regexp \ | |
| "https://github.com/szl-holdings/a11oy/.github/workflows/zarf-build-and-sign.yml.*" \ | |
| --certificate-oidc-issuer https://token.actions.githubusercontent.com \ | |
| --bundle "${{ steps.pkg.outputs.bundle }}" \ | |
| "${{ steps.pkg.outputs.tarball }}" \ | |
| && echo "Self-verification PASSED" | |
| - name: Create release ${{ inputs.release_name }} and upload signed assets | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| REL="${{ inputs.release_name }}" | |
| # Create the release at the NEW name if it does not exist (no tag move). | |
| if ! gh release view "${REL}" --repo szl-holdings/a11oy >/dev/null 2>&1; then | |
| gh release create "${REL}" \ | |
| --repo szl-holdings/a11oy \ | |
| --target main \ | |
| --title "a11oy ${REL} — real Zarf package (signed)" \ | |
| --notes "Real Zarf package built from deploy/zarf.yaml. Cosign keyless signed. See zarf-build-and-sign.yml." \ | |
| --prerelease | |
| fi | |
| gh release upload "${REL}" \ | |
| "${{ steps.pkg.outputs.tarball }}" \ | |
| "${{ steps.pkg.outputs.sha256 }}" \ | |
| "${{ steps.pkg.outputs.bundle }}" \ | |
| --clobber \ | |
| --repo szl-holdings/a11oy | |
| echo "Uploaded signed Zarf package to release ${REL}." | |
| - name: Verification instructions | |
| run: | | |
| REL="${{ inputs.release_name }}" | |
| echo "BASE=https://github.com/szl-holdings/a11oy/releases/download/${REL}" | |
| echo "cosign verify-blob \\" | |
| echo " --certificate-identity-regexp 'https://github.com/szl-holdings/a11oy/.github/workflows/zarf-build-and-sign.yml.*' \\" | |
| echo " --certificate-oidc-issuer https://token.actions.githubusercontent.com \\" | |
| echo " --bundle ${{ steps.pkg.outputs.bundle }} \\" | |
| echo " ${{ steps.pkg.outputs.tarball }}" | |