diff --git a/.github/workflows/deploy-reader.yml b/.github/workflows/deploy-reader.yml index 217f3e01..de41af5a 100644 --- a/.github/workflows/deploy-reader.yml +++ b/.github/workflows/deploy-reader.yml @@ -157,7 +157,6 @@ jobs: NATIVE_UI_SHA256: ${{ needs.native-inputs.outputs.ui }} NATIVE_PROTOCOL_SHA256: ${{ needs.native-inputs.outputs.protocol }} NATIVE_TRUST_ASSET_SHA256: ${{ needs.native-inputs.outputs.trust }} - MDBASE_EXTENSION_STAGING_PUBLIC_KEY: ${{ needs.native-inputs.outputs.public-key }} WRANGLER_SEND_METRICS: "false" outputs: artifact-id: ${{ steps.artifact.outputs.artifact-id }} @@ -189,6 +188,8 @@ jobs: pnpm check - name: One actual target build, precompiled capture Worker, all final bytes id: build + env: + MDBASE_EXTENSION_STAGING_PUBLIC_KEY: ${{ needs.native-inputs.outputs.public-key }} run: | set -euo pipefail node apps/reader/scripts/native-publisher.mjs guard --target "$TARGET" --sha "$SOURCE_SHA" --installed > "$RUNNER_TEMP/reader-confirmed-plan.json" diff --git a/apps/reader/scripts/native-publisher.mjs b/apps/reader/scripts/native-publisher.mjs index 4d9dca07..09ae3692 100644 --- a/apps/reader/scripts/native-publisher.mjs +++ b/apps/reader/scripts/native-publisher.mjs @@ -189,7 +189,7 @@ export async function captureDeployment({ if (!prefix || !accountId || !apiToken) throw new Error("Refusing: missing unique deployment URL or Cloudflare credentials"); const response = await fetchImpl( - `https://api.cloudflare.com/client/v4/accounts/${encodeURIComponent(accountId)}/pages/projects/mdbase-reader/deployments?per_page=100`, + `https://api.cloudflare.com/client/v4/accounts/${encodeURIComponent(accountId)}/pages/projects/mdbase-reader/deployments?per_page=20`, { headers: { Authorization: `Bearer ${apiToken}` }, redirect: "error", diff --git a/scripts/tests/reader-publisher.test.mjs b/scripts/tests/reader-publisher.test.mjs index 32ba00bc..bdbd6959 100644 --- a/scripts/tests/reader-publisher.test.mjs +++ b/scripts/tests/reader-publisher.test.mjs @@ -3,6 +3,8 @@ import { test } from "node:test"; import { mkdtemp, mkdir, readFile, writeFile, rm, cp } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; +import { parse as parseYaml } from "yaml"; +import { extensionEnvironment } from "../../apps/extension/scripts/extension-manifest.mjs"; import { assertDispatch, assertFullSha, @@ -98,6 +100,25 @@ test("ALL current eaa4 installed SDK/UI/protocol/peers: originals plus separatel JSON.stringify(installerEvidence), ); }); +test("native publisher scopes public staging key to target build, not default-LAB manifest checks", async () => { + const workflow = parseYaml(await readFile(".github/workflows/deploy-reader.yml", "utf8")); + const job = workflow.jobs["native-build"]; + const keyName = "MDBASE_EXTENSION_STAGING_PUBLIC_KEY"; + // Explicit PUBLIC-only presence fixture, NOT an allocated key or GHA identity. + const publicInput = "public-only-unit-fixture"; + const checkEnvironment = Object.fromEntries( + ["MDBASE_ENV", "VITE_MDBASE_ENV", keyName] + .filter((name) => name in job.env) + .map((name) => [name, name === keyName ? publicInput : job.env[name]]), + ); + assert.equal(extensionEnvironment(checkEnvironment).target, "lab"); + assert.throws( + () => extensionEnvironment({ MDBASE_ENV: "lab", [keyName]: publicInput }), + /staging builds only/, + ); + const build = job.steps.find((step) => step.id === "build"); + assert.equal(build.env[keyName], "${{ needs.native-inputs.outputs.public-key }}"); +}); async function intakeCopy() { const root = await mkdtemp(join(tmpdir(), "reader-intake-data-")); const paths = [ @@ -263,8 +284,12 @@ test("artifact API run event/attempt check occurs before ZIP retrieval", async ( } }); test("actual UUID resolves from URL + exact source + Pages channel, never URL-prefix ID", async () => { - const fetchImpl = async () => - Response.json({ + const fetchImpl = async (url) => { + assert.equal( + url, + "https://api.cloudflare.com/client/v4/accounts/fixture/pages/projects/mdbase-reader/deployments?per_page=20", + ); + return Response.json({ success: true, result: [ { @@ -274,6 +299,7 @@ test("actual UUID resolves from URL + exact source + Pages channel, never URL-pr }, ], }); + }; const value = await captureDeployment({ output: "https://12345678.mdbase-reader.pages.dev", target: "staging",