Candidate dress rehearsal #7
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Candidate dress rehearsal | |
| on: | |
| workflow_run: | |
| workflows: [CI] | |
| types: [completed] | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: 1helm-private-dress-rehearsal | |
| cancel-in-progress: false | |
| jobs: | |
| build: | |
| name: Build exact trusted-main Linux candidate | |
| if: >- | |
| github.event.workflow_run.conclusion == 'success' && | |
| github.event.workflow_run.event == 'push' && | |
| github.event.workflow_run.head_branch == 'main' && | |
| github.event.workflow_run.head_repository.full_name == github.repository && | |
| github.event.repository.full_name == github.repository && | |
| github.sha == github.event.workflow_run.head_sha && | |
| github.ref == 'refs/heads/main' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 60 | |
| permissions: | |
| contents: read | |
| id-token: write | |
| attestations: write | |
| outputs: | |
| artifact-name: ${{ steps.identity.outputs.artifact_name }} | |
| commit: ${{ steps.identity.outputs.commit }} | |
| version: ${{ steps.identity.outputs.version }} | |
| ci-run-id: ${{ steps.identity.outputs.ci_run_id }} | |
| image-digest: ${{ steps.identity.outputs.image_digest }} | |
| steps: | |
| - name: Check out the exact successful CI commit | |
| uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | |
| with: | |
| ref: ${{ github.event.workflow_run.head_sha }} | |
| fetch-depth: 1 | |
| persist-credentials: false | |
| - name: Re-verify trusted repository, ref, event, and SHA | |
| env: | |
| CI_HEAD_SHA: ${{ github.event.workflow_run.head_sha }} | |
| CI_HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }} | |
| CI_HEAD_REPOSITORY: ${{ github.event.workflow_run.head_repository.full_name }} | |
| CI_EVENT: ${{ github.event.workflow_run.event }} | |
| CI_CONCLUSION: ${{ github.event.workflow_run.conclusion }} | |
| CI_WORKFLOW: ${{ github.event.workflow_run.name }} | |
| run: | | |
| set -euo pipefail | |
| test "$GITHUB_REPOSITORY" = "gitcommit90/1Helm" | |
| test "$CI_HEAD_REPOSITORY" = "$GITHUB_REPOSITORY" | |
| test "$CI_HEAD_BRANCH" = "main" | |
| test "$CI_EVENT" = "push" | |
| test "$CI_CONCLUSION" = "success" | |
| test "$CI_WORKFLOW" = "CI" | |
| test "$GITHUB_REF" = "refs/heads/main" | |
| test "$GITHUB_SHA" = "$CI_HEAD_SHA" | |
| test "$(git rev-parse HEAD)" = "$CI_HEAD_SHA" | |
| test -z "$(git status --porcelain)" | |
| - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: "22" | |
| cache: npm | |
| - name: Install exact dependencies and builder runtime | |
| run: | | |
| set -euo pipefail | |
| PUPPETEER_SKIP_DOWNLOAD=1 npm ci | |
| sudo apt-get update | |
| sudo apt-get install -y podman | |
| - name: Resolve exact OCI and production dependency cache identities | |
| id: packaging-cache | |
| run: | | |
| set -euo pipefail | |
| builder_image=docker.io/library/node:22 | |
| podman pull "$builder_image" | |
| builder_digest="$(podman image inspect "$builder_image" --format '{{.Digest}}' | sed 's/^sha256://')" | |
| node_abi="$(podman run --rm "$builder_image" node -p process.versions.modules)" | |
| case "$(uname -m)" in x86_64|amd64) image_arch=amd64; native_arch=x64 ;; aarch64|arm64) image_arch=arm64; native_arch=arm64 ;; *) exit 1 ;; esac | |
| base_digest="$(sed -n 's/^FROM .*@sha256:\([a-f0-9]\{64\}\)$/\1/p' container/Containerfile.oci)" | |
| containerfile_sha="$(sha256sum container/Containerfile.oci | awk '{print $1}')" | |
| context_sha="$(git ls-files -z container | while IFS= read -r -d '' file; do | |
| case "$file" in container/channel-machine.oci.tar|container/channel-machine.oci.sha256|container/channel-machine.oci.json) continue ;; esac | |
| printf '%s\0' "$file" | |
| sha256sum "$file" | awk '{printf "%s\0", $1}' | |
| done | sha256sum | awk '{print $1}')" | |
| oci_key="$(printf '1helm-channel-image-v1\n%s\n%s\n%s\n%s\n' "$image_arch" "$base_digest" "$containerfile_sha" "$context_sha" | sha256sum | awk '{print $1}')" | |
| dependency_key="$(printf '%s\n%s\n%s\n%s\n%s' "$(sha256sum package-lock.json | awk '{print $1}')" "$(sha256sum config/linux-runtime-package.json | awk '{print $1}')" "$node_abi" "$native_arch" "$builder_digest" | sha256sum | awk '{print $1}')" | |
| [[ "$builder_digest" =~ ^[a-f0-9]{64}$ && "$node_abi" =~ ^[0-9]+$ && "$oci_key" =~ ^[a-f0-9]{64}$ && "$dependency_key" =~ ^[a-f0-9]{64}$ ]] | |
| printf 'oci_key=%s\ndependency_key=%s\n' "$oci_key" "$dependency_key" >> "$GITHUB_OUTPUT" | |
| - name: Restore only the exact sealed OCI cache | |
| uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 | |
| with: | |
| path: dist/cache/channel-images | |
| key: 1helm-phase5-channel-image-${{ steps.packaging-cache.outputs.oci_key }} | |
| - name: Restore only the exact production dependency cache | |
| uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 | |
| with: | |
| path: dist/cache/production-dependencies | |
| key: 1helm-phase5-production-dependencies-${{ steps.packaging-cache.outputs.dependency_key }} | |
| - name: Build sealed OCI image and ready-to-run Linux archive | |
| env: | |
| HELM_CANDIDATE_REPOSITORY: gitcommit90/1Helm | |
| HELM_CANDIDATE_REF: refs/heads/main | |
| HELM_CANDIDATE_COMMIT: ${{ github.event.workflow_run.head_sha }} | |
| HELM_CANDIDATE_SOURCE_STATE: trusted-main | |
| HELM_CANDIDATE_BUILD_ID: candidate-${{ github.event.workflow_run.id }}-${{ github.run_id }}.${{ github.run_attempt }} | |
| HELM_CANDIDATE_CREATED_AT: ${{ github.event.workflow_run.updated_at }} | |
| HELM_CANDIDATE_CI_WORKFLOW: CI | |
| HELM_CANDIDATE_CI_RUN_ID: ${{ github.event.workflow_run.id }} | |
| HELM_CANDIDATE_CI_CONCLUSION: success | |
| run: | | |
| set -euo pipefail | |
| npm run package:channel-image | |
| npm run package:linux | |
| image_name="$(node -p 'require("./container/channel-machine.oci.json").artifact.name')" | |
| cp container/channel-machine.oci.tar "dist/$image_name" | |
| cp container/channel-machine.oci.json "dist/${image_name%.oci.tar}.json" | |
| - name: Measure split artifact composition and enforce regression budgets | |
| run: | | |
| set -euo pipefail | |
| node scripts/artifact-size-report.mjs \ | |
| --json dist/artifact-size-report.json \ | |
| --text dist/artifact-size-report.txt \ | |
| --check | |
| - name: Generate candidate manifest and evidence | |
| id: identity | |
| env: | |
| CI_HEAD_SHA: ${{ github.event.workflow_run.head_sha }} | |
| HELM_CANDIDATE_CI_RUN_ID: ${{ github.event.workflow_run.id }} | |
| run: | | |
| set -euo pipefail | |
| version="$(node -p 'require("./package.json").version')" | |
| archive="dist/1Helm-${version}-linux-node.tgz" | |
| offline="dist/1Helm-${version}-linux-node-offline.tgz" | |
| split="dist/1Helm-${version}-linux-split.json" | |
| evidence="dist/candidate-evidence" | |
| mkdir -p "$evidence" | |
| HELM_CANDIDATE_ARCHIVE="$archive" \ | |
| HELM_CANDIDATE_OFFLINE_ARCHIVE="$offline" \ | |
| HELM_CANDIDATE_SPLIT_MANIFEST="$split" \ | |
| HELM_CANDIDATE_MANIFEST="$evidence/candidate.json" \ | |
| node scripts/candidate-manifest.mjs | |
| cp "$archive.sha256" "$evidence/archive.sha256" | |
| sha256sum "$evidence/candidate.json" > "$evidence/manifest.sha256" | |
| printf 'artifact_name=1helm-candidate-%s\n' "$CI_HEAD_SHA" >> "$GITHUB_OUTPUT" | |
| printf 'commit=%s\n' "$CI_HEAD_SHA" >> "$GITHUB_OUTPUT" | |
| printf 'version=%s\n' "$version" >> "$GITHUB_OUTPUT" | |
| printf 'ci_run_id=%s\n' "$HELM_CANDIDATE_CI_RUN_ID" >> "$GITHUB_OUTPUT" | |
| printf 'image_digest=%s\n' "$(node -p 'require("./container/channel-machine.oci.json").sha256')" >> "$GITHUB_OUTPUT" | |
| - name: Attest archive provenance on the hosted builder | |
| id: attest | |
| uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3 | |
| with: | |
| subject-path: | | |
| dist/1Helm-*-linux-node.tgz | |
| dist/1Helm-*-linux-node-offline.tgz | |
| container/channel-machine.oci.tar | |
| - name: Retain signed provenance bundle | |
| env: | |
| BUNDLE_PATH: ${{ steps.attest.outputs.bundle-path }} | |
| run: | | |
| set -euo pipefail | |
| test -s "$BUNDLE_PATH" | |
| install -m 0644 "$BUNDLE_PATH" dist/candidate-evidence/provenance.bundle.json | |
| - name: Upload exact candidate and evidence | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: ${{ steps.identity.outputs.artifact_name }} | |
| path: | | |
| dist/1Helm-*-linux-node.tgz | |
| dist/1Helm-*-linux-node-offline.tgz | |
| dist/1Helm-*-linux-split.json | |
| dist/artifact-size-report.json | |
| dist/artifact-size-report.txt | |
| container/channel-machine.oci.json | |
| dist/candidate-evidence/candidate.json | |
| dist/candidate-evidence/archive.sha256 | |
| dist/candidate-evidence/manifest.sha256 | |
| dist/candidate-evidence/provenance.bundle.json | |
| if-no-files-found: error | |
| retention-days: 30 | |
| - name: Retain immutable digest-addressed channel image candidate | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: 1helm-channel-image-${{ steps.identity.outputs.image_digest }} | |
| path: | | |
| dist/1Helm-channel-machine-v1-*.oci.tar | |
| dist/1Helm-channel-machine-v1-*.json | |
| container/channel-machine.oci.sha256 | |
| if-no-files-found: error | |
| retention-days: 90 | |
| build-macos: | |
| name: Build signed notarized exact Mac candidate | |
| if: >- | |
| github.event.workflow_run.conclusion == 'success' && | |
| github.event.workflow_run.event == 'push' && | |
| github.event.workflow_run.head_branch == 'main' && | |
| github.event.workflow_run.head_repository.full_name == github.repository && | |
| github.event.repository.full_name == github.repository && | |
| github.sha == github.event.workflow_run.head_sha && | |
| github.ref == 'refs/heads/main' && | |
| vars.HELM_PHASE4_MACOS_ENABLED == '1' | |
| runs-on: [1helm-macos-phase4] | |
| timeout-minutes: 90 | |
| permissions: | |
| contents: read | |
| env: | |
| HELM_PHASE4_RUNNER_LABEL: 1helm-macos-phase4 | |
| outputs: | |
| artifact-name: ${{ steps.identity.outputs.artifact_name }} | |
| steps: | |
| - name: Re-verify trusted event before repository code runs | |
| shell: bash | |
| env: | |
| EXPECTED_SHA: ${{ github.event.workflow_run.head_sha }} | |
| EXPECTED_REPOSITORY: ${{ github.event.workflow_run.head_repository.full_name }} | |
| EXPECTED_EVENT: ${{ github.event.workflow_run.event }} | |
| EXPECTED_BRANCH: ${{ github.event.workflow_run.head_branch }} | |
| EXPECTED_CONCLUSION: ${{ github.event.workflow_run.conclusion }} | |
| run: | | |
| set -euo pipefail | |
| test "$GITHUB_REPOSITORY" = gitcommit90/1Helm | |
| test "$EXPECTED_REPOSITORY" = "$GITHUB_REPOSITORY" | |
| test "$EXPECTED_EVENT" = push | |
| test "$EXPECTED_BRANCH" = main | |
| test "$EXPECTED_CONCLUSION" = success | |
| test "$GITHUB_REF" = refs/heads/main | |
| test "$GITHUB_SHA" = "$EXPECTED_SHA" | |
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | |
| with: | |
| ref: ${{ github.event.workflow_run.head_sha }} | |
| fetch-depth: 1 | |
| persist-credentials: false | |
| - name: Verify checkout and install exact dependencies without privilege | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| test "$(git rev-parse HEAD)" = "${{ github.event.workflow_run.head_sha }}" | |
| test -z "$(git status --porcelain)" | |
| test "$(uname -s)-$(uname -m)" = Darwin-arm64 | |
| PUPPETEER_SKIP_DOWNLOAD=1 npm ci | |
| - name: Build, sign, notarize, staple, and Gatekeeper-check both Mac artifacts | |
| shell: bash | |
| env: | |
| HELM_REQUIRE_NOTARIZATION: "1" | |
| run: npm run package:dmg:release | |
| - name: Bind exact Mac bytes to the candidate and CI identities | |
| id: identity | |
| shell: bash | |
| env: | |
| HELM_CANDIDATE_COMMIT: ${{ github.event.workflow_run.head_sha }} | |
| HELM_CANDIDATE_CI_RUN_ID: ${{ github.event.workflow_run.id }} | |
| run: | | |
| set -euo pipefail | |
| version="$(node -p 'require("./package.json").version')" | |
| mkdir -p dist/candidate-evidence | |
| HELM_CANDIDATE_VERSION="$version" \ | |
| HELM_MAC_DMG="dist/1Helm-$version-arm64.dmg" \ | |
| HELM_MAC_ZIP="dist/1Helm-$version-mac-arm64.zip" \ | |
| HELM_MAC_MANIFEST="dist/candidate-evidence/mac-candidate.json" \ | |
| node scripts/mac-candidate-manifest.mjs | |
| printf 'artifact_name=1helm-macos-candidate-%s\n' "$HELM_CANDIDATE_COMMIT" >> "$GITHUB_OUTPUT" | |
| - name: Upload exact retained signed Mac candidate | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: ${{ steps.identity.outputs.artifact_name }} | |
| path: | | |
| dist/1Helm-*-arm64.dmg | |
| dist/1Helm-*-mac-arm64.zip | |
| dist/candidate-evidence/mac-candidate.json | |
| dist/candidate-evidence/mac_dmg-provenance.json | |
| dist/candidate-evidence/mac_updater_zip-provenance.json | |
| if-no-files-found: error | |
| retention-days: 30 | |
| deploy: | |
| name: Retain private Phase 2 Linux dress rehearsal | |
| needs: build | |
| runs-on: [1helm-dress-rehearsal-phase2] | |
| timeout-minutes: 20 | |
| permissions: | |
| contents: read | |
| actions: read | |
| attestations: read | |
| steps: | |
| - name: Download this workflow's exact candidate | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: | |
| name: ${{ needs.build.outputs.artifact-name }} | |
| path: candidate-download | |
| - name: Submit fixed candidate inputs to the root-owned boundary | |
| env: | |
| EXPECTED_COMMIT: ${{ needs.build.outputs.commit }} | |
| run: | | |
| set -euo pipefail | |
| test "$GITHUB_REPOSITORY" = "gitcommit90/1Helm" | |
| test "$GITHUB_EVENT_NAME" = workflow_run | |
| test "$EXPECTED_COMMIT" = "${{ github.event.workflow_run.head_sha }}" | |
| test "${{ github.event.workflow_run.event }}" = push | |
| test "${{ github.event.workflow_run.head_branch }}" = main | |
| test "${{ github.event.workflow_run.head_repository.full_name }}" = "$GITHUB_REPOSITORY" | |
| test "${{ github.event.workflow_run.conclusion }}" = success | |
| archive="$(find candidate-download -maxdepth 1 -type f -name '1Helm-*-linux-node.tgz' -print -quit)" | |
| test -n "$archive" | |
| install -m 0600 "$archive" /var/lib/1helm-candidate/inbox/candidate.tgz | |
| offline="$(find candidate-download -maxdepth 1 -type f -name '1Helm-*-linux-node-offline.tgz' -print -quit)" | |
| test -n "$offline" | |
| install -m 0600 "$offline" /var/lib/1helm-candidate/inbox/candidate-offline.tgz | |
| install -m 0600 candidate-download/candidate-evidence/candidate.json /var/lib/1helm-candidate/inbox/candidate.json | |
| install -m 0600 candidate-download/candidate-evidence/provenance.bundle.json /var/lib/1helm-candidate/inbox/provenance.bundle.json | |
| sudo -n /usr/local/sbin/1helm-candidate-install | |
| - name: Retain exact private dress-rehearsal evidence | |
| run: | | |
| set -euo pipefail | |
| python3 /usr/local/lib/1helm-candidate/candidate-boundary.py summary /var/lib/1helm-candidate/evidence/status.json | |
| install -d -m 0700 candidate-result | |
| install -m 0600 /var/lib/1helm-candidate/evidence/status.json candidate-result/dress-rehearsal.json | |
| - name: Upload private evidence for hosted promotion assembly | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: 1helm-dress-rehearsal-evidence-${{ needs.build.outputs.commit }} | |
| path: candidate-result/dress-rehearsal.json | |
| if-no-files-found: error | |
| retention-days: 30 | |
| accept-linux: | |
| name: Linux clean, update, state, health, and rollback acceptance | |
| needs: build | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 60 | |
| permissions: | |
| contents: read | |
| actions: read | |
| attestations: read | |
| steps: | |
| - name: Check out the exact candidate verification code | |
| uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | |
| with: | |
| ref: ${{ needs.build.outputs.commit }} | |
| fetch-depth: 1 | |
| persist-credentials: false | |
| - name: Download exact Linux candidate | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: | |
| name: ${{ needs.build.outputs.artifact-name }} | |
| path: candidate-download | |
| - name: Execute real ephemeral systemd acceptance | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| HELM_EXPECTED_COMMIT: ${{ needs.build.outputs.commit }} | |
| HELM_EXPECTED_CI_RUN_ID: ${{ needs.build.outputs.ci-run-id }} | |
| HELM_CANDIDATE_MANIFEST: candidate-download/candidate-evidence/candidate.json | |
| HELM_CANDIDATE_PROVENANCE: candidate-download/candidate-evidence/provenance.bundle.json | |
| HELM_ACCEPTANCE_OUTPUT: linux-acceptance.json | |
| run: | | |
| set -euo pipefail | |
| test "$GITHUB_REPOSITORY" = gitcommit90/1Helm | |
| test "$GITHUB_EVENT_NAME" = workflow_run | |
| test "$GITHUB_REF" = refs/heads/main | |
| test "$GITHUB_SHA" = "$HELM_EXPECTED_COMMIT" | |
| test "${{ github.event.workflow_run.event }}" = push | |
| test "${{ github.event.workflow_run.head_repository.full_name }}" = "$GITHUB_REPOSITORY" | |
| export HELM_CANDIDATE_ARCHIVE="$(find candidate-download -maxdepth 1 -type f -name '1Helm-*-linux-node.tgz' -print -quit)" | |
| export HELM_CANDIDATE_OFFLINE_ARCHIVE="$(find candidate-download -maxdepth 1 -type f -name '1Helm-*-linux-node-offline.tgz' -print -quit)" | |
| test -n "$HELM_CANDIDATE_ARCHIVE" | |
| test -n "$HELM_CANDIDATE_OFFLINE_ARCHIVE" | |
| bash ops/platform-acceptance/linux.sh | |
| - name: Upload exact Linux acceptance evidence | |
| if: always() | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: 1helm-linux-acceptance-${{ needs.build.outputs.commit }} | |
| path: linux-acceptance.json | |
| if-no-files-found: error | |
| retention-days: 30 | |
| accept-macos: | |
| name: macOS signature, clean install, updater, state, and health acceptance | |
| needs: [build, build-macos] | |
| if: needs.build-macos.result == 'success' && vars.HELM_PHASE4_MACOS_ENABLED == '1' | |
| runs-on: [1helm-macos-phase4] | |
| timeout-minutes: 60 | |
| permissions: | |
| contents: read | |
| actions: read | |
| env: | |
| HELM_PHASE4_RUNNER_LABEL: 1helm-macos-phase4 | |
| steps: | |
| - name: Re-verify trusted event before repository code runs | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| test "$GITHUB_REPOSITORY" = gitcommit90/1Helm | |
| test "$GITHUB_EVENT_NAME" = workflow_run | |
| test "$GITHUB_REF" = refs/heads/main | |
| test "$GITHUB_SHA" = "${{ needs.build.outputs.commit }}" | |
| test "${{ github.event.workflow_run.event }}" = push | |
| test "${{ github.event.workflow_run.head_branch }}" = main | |
| test "${{ github.event.workflow_run.head_repository.full_name }}" = "$GITHUB_REPOSITORY" | |
| test "${{ github.event.workflow_run.conclusion }}" = success | |
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | |
| with: | |
| ref: ${{ needs.build.outputs.commit }} | |
| fetch-depth: 1 | |
| persist-credentials: false | |
| - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: | |
| name: ${{ needs.build-macos.outputs.artifact-name }} | |
| path: mac-candidate-download | |
| - name: Execute exact Apple Silicon acceptance | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| HELM_EXPECTED_COMMIT: ${{ needs.build.outputs.commit }} | |
| HELM_EXPECTED_CI_RUN_ID: ${{ needs.build.outputs.ci-run-id }} | |
| HELM_MAC_CANDIDATE_DOWNLOAD: mac-candidate-download | |
| HELM_ACCEPTANCE_OUTPUT: macos-acceptance.json | |
| run: bash ops/platform-acceptance/macos.sh | |
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| if: always() | |
| with: | |
| name: 1helm-macos-acceptance-${{ needs.build.outputs.commit }} | |
| path: macos-acceptance.json | |
| if-no-files-found: error | |
| retention-days: 30 | |
| accept-windows: | |
| name: Windows 11 WSL behavior, reboot, update, keepalive, and uninstall acceptance | |
| needs: build | |
| if: needs.build.result == 'success' && vars.HELM_PHASE4_WINDOWS_ENABLED == '1' | |
| runs-on: [1helm-windows-phase4] | |
| timeout-minutes: 90 | |
| permissions: | |
| contents: read | |
| actions: read | |
| attestations: read | |
| env: | |
| HELM_PHASE4_RUNNER_LABEL: 1helm-windows-phase4 | |
| steps: | |
| - name: Re-verify trusted event before repository code runs | |
| shell: powershell | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| if ($env:GITHUB_REPOSITORY -ne 'gitcommit90/1Helm' -or $env:GITHUB_EVENT_NAME -ne 'workflow_run' -or | |
| $env:GITHUB_REF -ne 'refs/heads/main' -or $env:GITHUB_SHA -ne '${{ needs.build.outputs.commit }}' -or | |
| '${{ github.event.workflow_run.event }}' -ne 'push' -or '${{ github.event.workflow_run.head_branch }}' -ne 'main' -or | |
| '${{ github.event.workflow_run.head_repository.full_name }}' -ne $env:GITHUB_REPOSITORY -or | |
| '${{ github.event.workflow_run.conclusion }}' -ne 'success') { throw 'Windows runner refused untrusted candidate identity.' } | |
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | |
| with: | |
| ref: ${{ needs.build.outputs.commit }} | |
| fetch-depth: 1 | |
| persist-credentials: false | |
| - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: | |
| name: ${{ needs.build.outputs.artifact-name }} | |
| path: candidate-download | |
| - name: Execute exact Windows 11 WSL behavior acceptance | |
| shell: powershell | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| HELM_EXPECTED_COMMIT: ${{ needs.build.outputs.commit }} | |
| HELM_EXPECTED_CI_RUN_ID: ${{ needs.build.outputs.ci-run-id }} | |
| HELM_CANDIDATE_MANIFEST: candidate-download/candidate-evidence/candidate.json | |
| HELM_CANDIDATE_PROVENANCE: candidate-download/candidate-evidence/provenance.bundle.json | |
| HELM_ACCEPTANCE_OUTPUT: windows-acceptance.json | |
| run: | | |
| $archive = Get-ChildItem candidate-download -Filter '1Helm-*-linux-node.tgz' | Select-Object -First 1 -ExpandProperty FullName | |
| if (-not $archive) { throw 'Exact Linux candidate archive is missing.' } | |
| $env:HELM_CANDIDATE_ARCHIVE = $archive | |
| $offline = Get-ChildItem candidate-download -Filter '1Helm-*-linux-node-offline.tgz' | Select-Object -First 1 -ExpandProperty FullName | |
| if (-not $offline) { throw 'Exact Linux offline candidate archive is missing.' } | |
| $env:HELM_CANDIDATE_OFFLINE_ARCHIVE = $offline | |
| & .\ops\platform-acceptance\windows.ps1 | |
| if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } | |
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| if: always() | |
| with: | |
| name: 1helm-windows-acceptance-${{ needs.build.outputs.commit }} | |
| path: windows-acceptance.json | |
| if-no-files-found: error | |
| retention-days: 30 | |
| assemble-promotion: | |
| name: Assemble complete Phase 3 promotion bundle without rebuilding | |
| needs: [build, build-macos, deploy, accept-linux, accept-macos, accept-windows] | |
| if: >- | |
| needs.build.result == 'success' && needs.build-macos.result == 'success' && | |
| needs.deploy.result == 'success' && needs.accept-linux.result == 'success' && | |
| needs.accept-macos.result == 'success' && needs.accept-windows.result == 'success' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| permissions: | |
| contents: read | |
| actions: read | |
| steps: | |
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | |
| with: | |
| ref: ${{ needs.build.outputs.commit }} | |
| fetch-depth: 1 | |
| persist-credentials: false | |
| - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: { name: "${{ needs.build.outputs.artifact-name }}", path: candidate-download } | |
| - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: { name: "1helm-channel-image-${{ needs.build.outputs.image-digest }}", path: channel-image-download } | |
| - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: { name: "${{ needs.build-macos.outputs.artifact-name }}", path: mac-candidate-download } | |
| - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: { name: "1helm-dress-rehearsal-evidence-${{ needs.build.outputs.commit }}", path: rehearsal-download } | |
| - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: { name: "1helm-linux-acceptance-${{ needs.build.outputs.commit }}", path: linux-acceptance-download } | |
| - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: { name: "1helm-macos-acceptance-${{ needs.build.outputs.commit }}", path: macos-acceptance-download } | |
| - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: { name: "1helm-windows-acceptance-${{ needs.build.outputs.commit }}", path: windows-acceptance-download } | |
| - name: Assemble only the retained complete matrix and evidence | |
| env: | |
| HELM_CANDIDATE_DOWNLOAD: candidate-download | |
| HELM_CHANNEL_IMAGE_DOWNLOAD: channel-image-download | |
| HELM_MAC_CANDIDATE_DOWNLOAD: mac-candidate-download | |
| HELM_REHEARSAL_EVIDENCE: rehearsal-download/dress-rehearsal.json | |
| HELM_LINUX_ACCEPTANCE_EVIDENCE: linux-acceptance-download/linux-acceptance.json | |
| HELM_MAC_ACCEPTANCE_EVIDENCE: macos-acceptance-download/macos-acceptance.json | |
| HELM_WINDOWS_ACCEPTANCE_EVIDENCE: windows-acceptance-download/windows-acceptance.json | |
| HELM_ACCEPTANCE_CONTENT: docs/phase4-platform-acceptance.md | |
| HELM_PROMOTION_OUTPUT: promotion-candidate | |
| HELM_PROJECT_ROOT: . | |
| HELM_CANDIDATE_CI_RUN_ID: ${{ needs.build.outputs.ci-run-id }} | |
| run: node scripts/candidate-promotion-skeleton.mjs | |
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: 1helm-promotion-candidate-${{ needs.build.outputs.commit }} | |
| path: promotion-candidate/ | |
| if-no-files-found: error | |
| retention-days: 30 | |
| candidate-status: | |
| name: Report per-platform Phase 3 readiness | |
| needs: [build, build-macos, deploy, accept-linux, accept-macos, accept-windows, assemble-promotion] | |
| if: always() && needs.build.result != 'skipped' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | |
| with: | |
| ref: ${{ github.event.workflow_run.head_sha }} | |
| fetch-depth: 1 | |
| persist-credentials: false | |
| - name: Retain honest pass, failure, and missing-runner blockers | |
| env: | |
| HELM_CANDIDATE_COMMIT: ${{ github.event.workflow_run.head_sha }} | |
| HELM_CANDIDATE_VERSION: ${{ needs.build.outputs.version }} | |
| HELM_LINUX_BUILD_RESULT: ${{ needs.build.result }} | |
| HELM_LINUX_REHEARSAL_RESULT: ${{ needs.deploy.result }} | |
| HELM_MAC_BUILD_RESULT: ${{ needs.build-macos.result }} | |
| HELM_LINUX_ACCEPTANCE_RESULT: ${{ needs.accept-linux.result }} | |
| HELM_MAC_ACCEPTANCE_RESULT: ${{ needs.accept-macos.result }} | |
| HELM_WINDOWS_ACCEPTANCE_RESULT: ${{ needs.accept-windows.result }} | |
| HELM_PROMOTION_BUNDLE_RESULT: ${{ needs.assemble-promotion.result }} | |
| HELM_CANDIDATE_STATUS_OUTPUT: candidate-matrix-status.json | |
| run: node scripts/candidate-matrix-status.mjs | |
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: 1helm-candidate-matrix-status-${{ github.event.workflow_run.head_sha }} | |
| path: candidate-matrix-status.json | |
| if-no-files-found: error | |
| retention-days: 30 |