diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 69ab2cb..3381d9a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -21,7 +21,7 @@ concurrency: jobs: publish: name: publish spawnfile to npm - timeout-minutes: 20 + timeout-minutes: 45 runs-on: ubuntu-latest env: RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }} @@ -80,14 +80,41 @@ jobs: repository: noopolis/daimon path: daimon-fixture + # The shipped runtime refuses any Grok executable but the manifest-pinned + # build, so the source build needs the real linux-x86_64 binary. Its URL, + # size, and digest come from the vendored Daimon contract manifest, so a + # re-vendored Daimon bump moves this download with no CI edit. + - name: Fetch the pinned linux-x86_64 Grok CLI + id: grok-cli + shell: bash + run: | + set -euo pipefail + + manifest=src/runtime/daimon/contract-manifest.json + read -r url bytes sha256 < <(node -e ' + const artifact = require("./" + process.argv[1]).grokEngineBroker?.grokCliArtifacts?.x64; + if (typeof artifact?.url !== "string" || !Number.isInteger(artifact.bytes) || !/^[a-f0-9]{64}$/.test(artifact.sha256 ?? "")) { + throw new Error("vendored Daimon contract manifest has no pinned linux-x86_64 Grok CLI artifact"); + } + process.stdout.write(`${artifact.url} ${artifact.bytes} ${artifact.sha256}\n`); + ' "${manifest}") + + file="${RUNNER_TEMP}/grok" + curl --fail --location --silent --show-error --output "${file}" -- "${url}" + test "$(stat -c %s -- "${file}")" -eq "${bytes}" + echo "${sha256} ${file}" | sha256sum --check --strict - + chmod 0755 -- "${file}" + echo "file=${file}" >> "${GITHUB_OUTPUT}" + - name: Verify Git-free offline linux/amd64 source build env: + SPAWNFILE_GROK_CLI_FILE: ${{ steps.grok-cli.outputs.file }} SPAWNFILE_TEST_DAIMON_SOURCE: ${{ github.workspace }}/daimon-fixture run: npm run test:source-provenance-docker - - name: Remove Daimon provenance fixture + - name: Remove Daimon provenance fixture and Grok CLI if: always() - run: rm -rf -- daimon-fixture + run: rm -rf -- daimon-fixture "${RUNNER_TEMP}/grok" - name: Check out Moltnet provenance fixture uses: actions/checkout@v4 diff --git a/scripts/source-provenance-bundle.integration.test.ts b/scripts/source-provenance-bundle.integration.test.ts index 98a2b5d..d670d85 100644 --- a/scripts/source-provenance-bundle.integration.test.ts +++ b/scripts/source-provenance-bundle.integration.test.ts @@ -25,7 +25,10 @@ const pinnedGrokCli = (): string => { }; const sha512 = (file: string): string => `sha512:${createHash("sha512").update(readFileSync(file)).digest("hex")}`; -test("actual Daimon lock produces a real offline linux/amd64 shipped artifact and rejects tampering", { timeout: 360_000 }, () => { +// A full pass — offline closure, shipped artifact, wrapper image, literal org +// container, and four tamper rejections — measured 328 s on a GitHub-hosted +// runner, so the budget leaves room for a slower one rather than 32 s. +test("actual Daimon lock produces a real offline linux/amd64 shipped artifact and rejects tampering", { timeout: 900_000 }, () => { execFileSync("docker", ["version"], { stdio: "ignore" }); const temporary = mkdtempSync(path.join(repository, ".spawnfile-source-docker-")); let registry: string | undefined;