Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:

steps:
- name: Set up exact Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: ${{ env.LFC_NODE_VERSION }}
package-manager-cache: false
Expand Down Expand Up @@ -114,7 +114,7 @@ jobs:
head-ref: ${{ needs.source.outputs.head }}

- name: Set up exact Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: ${{ env.LFC_NODE_VERSION }}
package-manager-cache: false
Expand Down Expand Up @@ -146,7 +146,7 @@ jobs:

- name: Upload browser results and failure diagnostics
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: browser-diagnostics-${{ github.run_id }}
if-no-files-found: ignore
Expand Down Expand Up @@ -183,7 +183,7 @@ jobs:
ref: ${{ github.event.pull_request.head.sha }}

- name: Set up exact Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: ${{ env.LFC_NODE_VERSION }}
package-manager-cache: false
Expand Down Expand Up @@ -219,7 +219,7 @@ jobs:

- name: Upload screenshot candidates and comparison gallery
if: ${{ always() && steps.eligibility.outputs.eligible == 'true' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: screenshot-candidate-${{ github.run_id }}-${{ github.run_attempt }}
path: .cache/screenshots/candidate/
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/deploy-examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ jobs:

- name: Set up exact Node
if: ${{ steps.identity.outputs.eligible == 'true' }}
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: ${{ env.LFC_NODE_VERSION }}
package-manager-cache: false
Expand Down Expand Up @@ -168,7 +168,7 @@ jobs:

- name: Upload the raw verified channel without deployment authority
if: ${{ steps.identity.outputs.eligible == 'true' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: ${{ steps.artifact.outputs.name }}
if-no-files-found: error
Expand Down Expand Up @@ -200,7 +200,7 @@ jobs:
ref: ${{ needs.build.outputs.source-commit }}

- name: Set up exact Node for canonical Pages assembly
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: ${{ env.LFC_NODE_VERSION }}
package-manager-cache: false
Expand All @@ -214,7 +214,7 @@ jobs:
run: npm ci --ignore-scripts

- name: Download the raw verified channel
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: ${{ needs.build.outputs.channel-artifact }}
path: ${{ runner.temp }}/pages-channel
Expand Down
20 changes: 10 additions & 10 deletions .github/workflows/publish-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ jobs:
ref: ${{ github.sha }}

- name: Set up exact Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: ${{ env.LFC_NODE_VERSION }}
package-manager-cache: false
Expand Down Expand Up @@ -257,7 +257,7 @@ jobs:

- name: Upload browser diagnostics on failure
if: failure() && steps.registry-state.outputs.eligible == 'true'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: release-browser-diagnostics-${{ github.run_id }}
if-no-files-found: ignore
Expand Down Expand Up @@ -331,7 +331,7 @@ jobs:

- name: Upload the exact npm release bundle
if: ${{ steps.registry-state.outputs.eligible == 'true' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: ${{ steps.identity.outputs.bundle-artifact }}
if-no-files-found: error
Expand All @@ -341,7 +341,7 @@ jobs:

- name: Upload normalized release notes
if: ${{ steps.registry-state.outputs.eligible == 'true' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: ${{ steps.identity.outputs.notes-artifact }}
if-no-files-found: error
Expand All @@ -365,13 +365,13 @@ jobs:

steps:
- name: Download the verified bundle without checking out source
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: ${{ needs.verify.outputs.bundle-artifact }}
path: ${{ runner.temp }}/release-bundle

- name: Download normalized release notes
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: ${{ needs.verify.outputs.notes-artifact }}
path: ${{ runner.temp }}/release-notes
Expand Down Expand Up @@ -490,7 +490,7 @@ jobs:

steps:
- name: Set up exact Node for npm trusted publishing
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: ${{ env.LFC_NODE_VERSION }}
package-manager-cache: false
Expand Down Expand Up @@ -635,7 +635,7 @@ jobs:
' <<< "${comparison}" > /dev/null

- name: Download the verified bundle without checking out source
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: ${{ needs.verify.outputs.bundle-artifact }}
path: ${{ runner.temp }}/release-bundle
Expand Down Expand Up @@ -847,7 +847,7 @@ jobs:

steps:
- name: Set up exact Node for registry verification
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: ${{ env.LFC_NODE_VERSION }}
package-manager-cache: false
Expand All @@ -857,7 +857,7 @@ jobs:
run: npm install --global "npm@${LFC_NPM_VERSION}" --ignore-scripts

- name: Download the retained bundle for provenance verification
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: ${{ needs.verify.outputs.bundle-artifact }}
path: ${{ runner.temp }}/release-bundle
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/refresh-screenshot-evidence.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ jobs:
LFC_UPSTREAM_RUN_ID: ${{ github.event.workflow_run.id }}
LFC_UPSTREAM_RUN_ATTEMPT: ${{ github.event.workflow_run.run_attempt }}
LFC_UPSTREAM_HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
LFC_CANDIDATE_DIRECTORY: ${{ runner.temp }}/screenshot-candidate

steps:
- name: Check out trusted promotion code without persisted credentials
Expand All @@ -50,7 +49,7 @@ jobs:
ref: ${{ github.sha }}

- name: Set up exact Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: ${{ env.LFC_NODE_VERSION }}
package-manager-cache: false
Expand All @@ -61,7 +60,7 @@ jobs:

- name: Download the validated candidate artifact
if: ${{ steps.context.outputs.eligible == 'true' }}
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
github-token: ${{ github.token }}
repository: ${{ github.repository }}
Expand All @@ -72,4 +71,6 @@ jobs:

- name: Refresh identical evidence and verify the new exact head
if: ${{ steps.context.outputs.eligible == 'true' }}
env:
LFC_CANDIDATE_DIRECTORY: ${{ runner.temp }}/screenshot-candidate
run: node scripts/screenshot-automation.mjs promote
2 changes: 1 addition & 1 deletion .github/workflows/rollback-examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
ref: ${{ github.sha }}

- name: Set up exact Node for canonical Pages assembly
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: ${{ env.LFC_NODE_VERSION }}
package-manager-cache: false
Expand Down
15 changes: 10 additions & 5 deletions scripts/tests/workflow-contracts.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,11 @@ void test("screenshot promotion consumes a validated artifact without executing
assert.match(promote, /LFC_UPSTREAM_RUN_ATTEMPT: \$\{\{ github\.event\.workflow_run\.run_attempt \}\}/u);
assert.match(promote, /LFC_UPSTREAM_HEAD_SHA: \$\{\{ github\.event\.workflow_run\.head_sha \}\}/u);
assert.match(promote, /screenshot-automation\.mjs promotion-context[\s\S]*?steps\.context\.outputs\.eligible == 'true'[\s\S]*?actions\/download-artifact@[0-9a-f]{40}[\s\S]*?run-id: \$\{\{ github\.event\.workflow_run\.id \}\}[\s\S]*?artifact-ids: \$\{\{ steps\.context\.outputs\.artifact-id \}\}[\s\S]*?screenshot-automation\.mjs promote/u);
assert.match(promote, /LFC_CANDIDATE_DIRECTORY: \$\{\{ runner\.temp \}\}\/screenshot-candidate/u);
const stepBoundary = promote.indexOf("\n steps:");
assert.ok(stepBoundary > 0, "Promotion must declare its steps.");
assert.doesNotMatch(promote.slice(0, stepBoundary), /\$\{\{\s*runner\./u,
"The runner context is unavailable in job-level environment variables.");
assert.match(promote, /Refresh identical evidence and verify the new exact head[\s\S]*?\n {8}env:\s*\n {10}LFC_CANDIDATE_DIRECTORY: \$\{\{ runner\.temp \}\}\/screenshot-candidate\s*\n {8}run: node scripts\/screenshot-automation\.mjs promote/u);
});

void test("hosted gates run Chromium and WebKit while local Playwright retains Firefox", async () => {
Expand Down Expand Up @@ -664,24 +668,25 @@ void test("workflow artifacts use bounded purpose-specific retention", async ()
}
});

void test("artifact downloads use the official Node 24 action", async () => {
void test("artifact downloads consistently pin the official v8 action", async () => {
const workflows = [
"deploy-examples.yml",
"publish-nightly.yml",
"refresh-screenshot-evidence.yml",
"rollback-examples.yml"
];
const expected =
"actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1";
const pins = new Set();
let downloads = 0;
for (const name of workflows) {
const source = await workflow(name);
for (const match of source.matchAll(/^\s*uses:\s*(actions\/download-artifact@[^\r\n]+)$/gmu)) {
downloads += 1;
assert.equal(match[1], expected, name);
assert.match(match[1], /^actions\/download-artifact@[0-9a-f]{40} # v8\.\d+\.\d+$/u, name);
pins.add(match[1]);
}
}
assert.equal(downloads, 6);
assert.equal(pins.size, 1, "All artifact downloads must use the same reviewed action pin.");
});

void test("workflow dependency caches stay disabled", async () => {
Expand Down
Loading