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
2 changes: 1 addition & 1 deletion .github/workflows/acquisition-readiness-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:

- name: upload acquisition artifacts
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: acquisition-readiness-audit
path: artifacts/acquisition-readiness/**/*
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ jobs:

- name: Upload durable deployment and rollback evidence
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: noema-deployment-evidence-production-${{ steps.release.outputs.tag }}
path: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/central-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ jobs:
sha256sum noema-manifest.json >noema-manifest.sha256

- name: Upload short-lived bounded review manifest
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: noema-manifest-${{ steps.target.outputs.head_sha }}
path: |
Expand Down Expand Up @@ -324,7 +324,7 @@ jobs:
"$RUNNER_TEMP/noema-manifest-attestation.json"

- name: Upload short-lived signed manifest attestation
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: noema-manifest-attestation-${{ needs.collect_evidence.outputs.head_sha }}
path: ${{ runner.temp }}/noema-manifest-attestation.json
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/hourly-commercial-readiness.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ jobs:

- name: upload scheduler activation evidence
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: scheduler-activation-evidence
path: artifacts/operations/hourly-scheduler-activation.json
Expand Down Expand Up @@ -199,7 +199,7 @@ jobs:

- name: upload main governance audit
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: main-governance-audit
path: artifacts/governance/main-governance-audit.json
Expand All @@ -208,7 +208,7 @@ jobs:

- name: upload loop report
if: always() && steps.loop.outcome != 'skipped'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: commercial-readiness-loop-report
path: artifacts/commercial-readiness/hourly-loop-report.json
Expand All @@ -217,7 +217,7 @@ jobs:

- name: upload no-PR commercial-readiness evidence
if: always() && steps.loop.outputs.remaining_open_pull_request_count == '0'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: no-pr-commercial-readiness-evidence
path: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/hourly-product-development.yml
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ jobs:
- name: Upload bounded proposal patch
id: upload_proposal
if: steps.proposal.outputs.has_changes == 'true'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: noema-product-proposal-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ runner.temp }}/noema-product-proposal/proposal.patch
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/maintainer-app-readiness.yml
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ jobs:

- name: upload main governance evidence
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: main-governance-audit
path: ${{ runner.temp }}/noema-maintainer-app-readiness/main-governance-audit.json
Expand All @@ -183,7 +183,7 @@ jobs:

- name: upload Maintainer App readiness evidence
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: maintainer-app-readiness
path: ${{ runner.temp }}/noema-maintainer-app-readiness/maintainer-app-readiness.json
Expand All @@ -192,7 +192,7 @@ jobs:

- name: upload no-write commercial loop evidence
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: commercial-readiness-loop-dry-run
path: ${{ runner.temp }}/noema-maintainer-app-readiness/commercial-readiness-loop-dry-run.json
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/readiness-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ jobs:

- name: upload readiness artifacts
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: saleable-readiness-audit
path: |
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/release-evidence.yml
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ jobs:

- name: Upload bounded sterile release materialization
id: materialization_bundle
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: noema-release-materialization-${{ needs.verify_release.outputs.tag }}
path: |
Expand Down Expand Up @@ -404,7 +404,7 @@ jobs:

- name: Upload bounded release publication bundle
id: release_bundle
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: noema-release-evidence-${{ needs.materialize_release.outputs.tag }}
path: |
Expand Down Expand Up @@ -647,7 +647,7 @@ jobs:

- name: Upload durable publication receipt
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: noema-release-publication-${{ needs.attest_release.outputs.tag }}
path: ${{ runner.temp }}/release-publication/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe("acquisition-readiness workflow supply-chain integrity", () => {
"uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0",
);
expect(workflow).toContain(
"uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2",
"uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1",
);
expect(workflow).not.toMatch(
/uses:\s+actions\/(?:checkout|setup-node|upload-artifact)@v\d+/,
Expand Down
2 changes: 1 addition & 1 deletion test/hourly-product-development-workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ describe("hourly NVIDIA NIM OpenCode product-development workflow", () => {
expect(tokenIndex).toBeLessThan(revalidationIndex);

expect(workflow).toContain(
"actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02",
"actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1",
);
expect(workflow).toContain(
"actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093",
Expand Down
2 changes: 1 addition & 1 deletion test/readiness-scan-toolchain-integrity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe("saleable-readiness workflow supply-chain integrity", () => {
"uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0",
);
expect(workflow).toContain(
"uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2",
"uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1",
);
expect(workflow).not.toMatch(/uses:\s+actions\/(?:checkout|setup-node|upload-artifact)@v\d+/);
});
Expand Down
54 changes: 54 additions & 0 deletions test/upload-artifact-node24-integrity.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { readFileSync, readdirSync } from "node:fs";
import { describe, expect, it } from "vitest";

const uploadArtifactPin =
"actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1";
const deprecatedUploadArtifactPin =
"actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02";
const workflowDirectory = ".github/workflows";
const supportedWorkflowPaths = [
".github/workflows/acquisition-readiness-scan.yml",
".github/workflows/cd.yml",
".github/workflows/central-review.yml",
".github/workflows/hourly-commercial-readiness.yml",
".github/workflows/hourly-product-development.yml",
".github/workflows/maintainer-app-readiness.yml",
".github/workflows/readiness-scan.yml",
".github/workflows/release-evidence.yml",
] as const;

function workflowPathsUsingUploadArtifact(): string[] {
return readdirSync(workflowDirectory, { withFileTypes: true })
.filter(
(entry) =>
entry.isFile() && (entry.name.endsWith(".yml") || entry.name.endsWith(".yaml")),
)
.map((entry) => `${workflowDirectory}/${entry.name}`)
.filter((workflowPath) =>
readFileSync(workflowPath, "utf8").includes("actions/upload-artifact@"),
)
.sort();
}

describe("upload-artifact Node 24 supply-chain contract", () => {
it("keeps the reviewed workflow inventory complete", () => {
expect(workflowPathsUsingUploadArtifact()).toEqual([...supportedWorkflowPaths].sort());
});

for (const workflowPath of supportedWorkflowPaths) {
it(`${workflowPath} pins every upload-artifact use to the reviewed Node 24 action`, () => {
const workflow = readFileSync(workflowPath, "utf8");
const uploadArtifactLines = workflow
.split(/\r?\n/)
.filter((line) => line.includes("actions/upload-artifact@"))
.map((line) => line.trim());

expect(uploadArtifactLines.length).toBeGreaterThan(0);
expect(uploadArtifactLines).toEqual(
uploadArtifactLines.map(() => `uses: ${uploadArtifactPin}`),
);
expect(workflow).not.toContain(deprecatedUploadArtifactPin);
expect(workflow).not.toMatch(/uses:\s+actions\/upload-artifact@v\d+/);
});
}
});
Loading