Compare commits

..
Author SHA1 Message Date
Brian DeHamer 71bbf8e91b exeriment with OCI header auth
Signed-off-by: Brian DeHamer <[email protected]>
2025-04-03 17:49:07 -07:00
21 changed files with 6588 additions and 9269 deletions
+10
View File
@@ -0,0 +1,10 @@
rules:
document-end: disable
document-start:
level: warning
present: false
line-length:
level: warning
max: 80
allow-non-breakable-words: true
allow-non-breakable-inline-mappings: true
@@ -7,7 +7,7 @@ export default tseslint.config(
// Ignore non-project files // Ignore non-project files
{ {
name: 'ignore', name: 'ignore',
ignores: ['.github', 'dist', 'coverage', '**/*.json', 'jest.setup.js', 'eslint.config.mjs'] ignores: ['.github', 'dist', 'coverage', '**/*.json', 'jest.setup.js']
}, },
// Use recommended rules from ESLint, TypeScript, and other plugins // Use recommended rules from ESLint, TypeScript, and other plugins
eslint.configs.recommended, eslint.configs.recommended,
@@ -21,7 +21,7 @@ export default tseslint.config(
languageOptions: { languageOptions: {
ecmaVersion: 2023, ecmaVersion: 2023,
parserOptions: { parserOptions: {
project: ['./tsconfig.lint.json'] project: ['./.github/linters/tsconfig.json', './tsconfig.json']
} }
}, },
rules: { rules: {
+9
View File
@@ -0,0 +1,9 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "../../tsconfig.json",
"compilerOptions": {
"noEmit": true
},
"include": ["../../__tests__/**/*", "../../src/**/*"],
"exclude": ["../../dist", "../../node_modules", "../../coverage", "*.json"]
}
+3 -3
View File
@@ -28,11 +28,11 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
id: checkout id: checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 uses: actions/checkout@v4
- name: Setup Node.js - name: Setup Node.js
id: setup-node id: setup-node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 uses: actions/setup-node@v4
with: with:
node-version-file: .node-version node-version-file: .node-version
cache: npm cache: npm
@@ -60,7 +60,7 @@ jobs:
- if: ${{ failure() && steps.diff.outcome == 'failure' }} - if: ${{ failure() && steps.diff.outcome == 'failure' }}
name: Upload Artifact name: Upload Artifact
id: upload id: upload
uses: actions/upload-artifact@v6.0.0 uses: actions/upload-artifact@v4
with: with:
name: dist name: dist
path: dist/ path: dist/
+3 -3
View File
@@ -21,11 +21,11 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
id: checkout id: checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup Node.js - name: Setup Node.js
id: setup-node id: setup-node
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
with: with:
node-version-file: .node-version node-version-file: .node-version
cache: npm cache: npm
@@ -57,7 +57,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
id: checkout id: checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Run attest-provenance - name: Run attest-provenance
id: attest-provenance id: attest-provenance
uses: ./ uses: ./
+4 -4
View File
@@ -32,19 +32,19 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
id: checkout id: checkout
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 uses: actions/checkout@v4
- name: Initialize CodeQL - name: Initialize CodeQL
id: initialize id: initialize
uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 uses: github/codeql-action/init@v3
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
source-root: src source-root: src
- name: Autobuild - name: Autobuild
id: autobuild id: autobuild
uses: github/codeql-action/autobuild@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
id: analyze id: analyze
uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 uses: github/codeql-action/analyze@v3
+51
View File
@@ -0,0 +1,51 @@
name: Lint Codebase
on:
pull_request:
branches:
- main
push:
branches:
- main
permissions:
contents: read
packages: read
statuses: write
jobs:
lint:
name: Lint Codebase
runs-on: ubuntu-latest
steps:
- name: Checkout
id: checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
id: setup-node
uses: actions/setup-node@v4
with:
node-version-file: .node-version
cache: npm
- name: Install Dependencies
id: install
run: npm ci
- name: Lint Codebase
id: super-linter
uses: super-linter/super-linter/[email protected]
env:
DEFAULT_BRANCH: main
FILTER_REGEX_EXCLUDE: dist/**/*
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TYPESCRIPT_DEFAULT_STYLE: prettier
VALIDATE_ALL_CODEBASE: true
VALIDATE_JAVASCRIPT_STANDARD: false
VALIDATE_TYPESCRIPT_STANDARD: false
VALIDATE_JSCPD: false
VALIDATE_YAML_PRETTIER: false
+4 -4
View File
@@ -29,7 +29,7 @@ jobs:
date > artifact date > artifact
- name: Attest build provenance - name: Attest build provenance
uses: actions/attest-build-provenance@v3 uses: actions/attest-build-provenance@v2
env: env:
INPUT_PRIVATE-SIGNING: ${{ inputs.sigstore == 'github' && 'true' || 'false' }} INPUT_PRIVATE-SIGNING: ${{ inputs.sigstore == 'github' && 'true' || 'false' }}
with: with:
@@ -42,13 +42,13 @@ jobs:
gh attestation verify ./artifact --owner "$GITHUB_REPOSITORY_OWNER" gh attestation verify ./artifact --owner "$GITHUB_REPOSITORY_OWNER"
- name: Upload build artifact - name: Upload build artifact
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 uses: actions/upload-artifact@v4
with: with:
path: "artifact" path: "artifact"
- name: Report attestation prober success - name: Report attestation prober success
if: ${{ success() }} if: ${{ success() }}
uses: masci/datadog@a3f481d2ed0f4e1edde2be2f564b94719d6d4bc2 # v1.9.3 uses: masci/datadog@6889e9d060f5368eeee51f8a3f06a52f65d04da3 # v1.9.1
with: with:
api-key: "${{ secrets.DATADOG_API_KEY }}" api-key: "${{ secrets.DATADOG_API_KEY }}"
service-checks: | service-checks: |
@@ -66,7 +66,7 @@ jobs:
- name: Report attestation prober failure - name: Report attestation prober failure
if: ${{ failure() }} if: ${{ failure() }}
uses: masci/datadog@a3f481d2ed0f4e1edde2be2f564b94719d6d4bc2 # v1.9.3 uses: masci/datadog@6889e9d060f5368eeee51f8a3f06a52f65d04da3 # v1.9.1
with: with:
api-key: "${{ secrets.DATADOG_API_KEY }}" api-key: "${{ secrets.DATADOG_API_KEY }}"
service-checks: | service-checks: |
@@ -0,0 +1,22 @@
name: 'Publish Immutable Action Version'
on:
release:
types: [published]
permissions: {}
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
packages: write
steps:
- name: Checking out
uses: actions/checkout@v4
- name: Publish
id: publish
uses: actions/[email protected]
+1 -1
View File
@@ -1 +1 @@
24.5.0 20.6.0
+9 -42
View File
@@ -46,20 +46,16 @@ attest:
permissions: permissions:
id-token: write id-token: write
attestations: write attestations: write
artifact-metadata: write
``` ```
The `id-token` permission gives the action the ability to mint the OIDC token The `id-token` permission gives the action the ability to mint the OIDC token
necessary to request a Sigstore signing certificate. The `attestations` necessary to request a Sigstore signing certificate. The `attestations`
permission is necessary to persist the attestation. permission is necessary to persist the attestation.
The `artifact-metadata` permission is required to generate artifact
metadata storage records. If this permission is not included, the action
will continue without creating the record.
1. Add the following to your workflow after your artifact has been built: 1. Add the following to your workflow after your artifact has been built:
```yaml ```yaml
- uses: actions/attest-build-provenance@v3 - uses: actions/attest-build-provenance@v2
with: with:
subject-path: '<PATH TO ARTIFACT>' subject-path: '<PATH TO ARTIFACT>'
``` ```
@@ -72,7 +68,7 @@ attest:
See [action.yml](action.yml) See [action.yml](action.yml)
```yaml ```yaml
- uses: actions/attest-build-provenance@v3 - uses: actions/attest-build-provenance@v2
with: with:
# Path to the artifact serving as the subject of the attestation. Must # Path to the artifact serving as the subject of the attestation. Must
# specify exactly one of "subject-path", "subject-digest", or # specify exactly one of "subject-path", "subject-digest", or
@@ -99,12 +95,6 @@ See [action.yml](action.yml)
# the "subject-digest" parameter be specified. Defaults to false. # the "subject-digest" parameter be specified. Defaults to false.
push-to-registry: push-to-registry:
# Whether to create a storage record for the artifact.
# Requires that push-to-registry is set to true.
# Requires that the "subject-name" parameter specify the fully-qualified
# image name. Defaults to true.
create-storage-record:
# Whether to attach a list of generated attestations to the workflow run # Whether to attach a list of generated attestations to the workflow run
# summary page. Defaults to true. # summary page. Defaults to true.
show-summary: show-summary:
@@ -131,10 +121,6 @@ Attestations are saved in the JSON-serialized [Sigstore bundle][6] format.
If multiple subjects are being attested at the same time, a single attestation If multiple subjects are being attested at the same time, a single attestation
will be created with references to each of the supplied subjects. will be created with references to each of the supplied subjects.
The absolute path to the generated attestation is appended to the file
`${RUNNER_TEMP}/created_attestation_paths.txt`. This file will accumulate the
paths to all attestations created over the course of a single workflow.
## Attestation Limits ## Attestation Limits
### Subject Limits ### Subject Limits
@@ -169,7 +155,7 @@ jobs:
- name: Build artifact - name: Build artifact
run: make my-app run: make my-app
- name: Attest - name: Attest
uses: actions/attest-build-provenance@v3 uses: actions/attest-build-provenance@v2
with: with:
subject-path: '${{ github.workspace }}/my-app' subject-path: '${{ github.workspace }}/my-app'
``` ```
@@ -180,7 +166,7 @@ If you are generating multiple artifacts, you can attest all of them at the same
time by using a wildcard in the `subject-path` input. time by using a wildcard in the `subject-path` input.
```yaml ```yaml
- uses: actions/attest-build-provenance@v3 - uses: actions/attest-build-provenance@v2
with: with:
subject-path: 'dist/**/my-bin-*' subject-path: 'dist/**/my-bin-*'
``` ```
@@ -192,13 +178,13 @@ Alternatively, you can explicitly list multiple subjects with either a comma or
newline delimited list: newline delimited list:
```yaml ```yaml
- uses: actions/attest-build-provenance@v3 - uses: actions/attest-build-provenance@v2
with: with:
subject-path: 'dist/foo, dist/bar' subject-path: 'dist/foo, dist/bar'
``` ```
```yaml ```yaml
- uses: actions/attest-build-provenance@v3 - uses: actions/attest-build-provenance@v2
with: with:
subject-path: | subject-path: |
dist/foo dist/foo
@@ -219,7 +205,7 @@ attestation.
- name: Calculate artifact digests - name: Calculate artifact digests
run: | run: |
shasum -a 256 foo_0.0.1_* > subject.checksums.txt shasum -a 256 foo_0.0.1_* > subject.checksums.txt
- uses: actions/attest-build-provenance@v3 - uses: actions/attest-build-provenance@v2
with: with:
subject-checksums: subject.checksums.txt subject-checksums: subject.checksums.txt
``` ```
@@ -292,7 +278,7 @@ jobs:
push: true push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
- name: Attest - name: Attest
uses: actions/attest-build-provenance@v3 uses: actions/attest-build-provenance@v2
id: attest id: attest
with: with:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
@@ -300,25 +286,6 @@ jobs:
push-to-registry: true push-to-registry: true
``` ```
#### Artifact Metadata Storage Records
If the `push-to-registry` option is set to true, the Action will also
emit an [Artifact Metadata Storage Record](https://docs.github.com/en/rest/orgs/artifact-metadata?apiVersion=2022-11-28#create-artifact-metadata-storage-record).
Storage records enrich artifact metadata by capturing storage
related details, such as which registry an image is hosted on
and whether it's marked as active.
If you do not want to emit a storage record, set `create-storage-record` to `false`.
> **NOTE**: Storage records can only be created for artifacts
> built from [organization-owned](https://docs.github.com/en/organizations/collaborating-with-groups-in-organizations/about-organizations)
> repositories.
Artifacts associated with a storage record can be viewed by navigating to
the `Linked Artifacts` page in your organization:
`https://github.com/orgs/YOUR_ORG/artifacts`
(replace `YOUR_ORG` with your organization name).
### Integration with `actions/upload-artifact` ### Integration with `actions/upload-artifact`
If you'd like to create an attestation for an archive created with the If you'd like to create an attestation for an archive created with the
@@ -333,7 +300,7 @@ artifact directly into the `subject-digest` input of the attestation action.
path: dist/* path: dist/*
name: artifact.zip name: artifact.zip
- uses: actions/attest-build-provenance@v3 - uses: actions/attest-build-provenance@v2
with: with:
subject-name: artifact.zip subject-name: artifact.zip
subject-digest: sha256:${{ steps.upload.outputs.artifact-digest }} subject-digest: sha256:${{ steps.upload.outputs.artifact-digest }}
+1 -1
View File
@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`main when a non-default OIDC issuer is used successfully run main 1`] = ` exports[`main when a non-default OIDC issuer is used successfully run main 1`] = `
{ {
+2 -11
View File
@@ -36,12 +36,6 @@ inputs:
and that the "subject-digest" parameter be specified. Defaults to false. and that the "subject-digest" parameter be specified. Defaults to false.
default: false default: false
required: false required: false
create-storage-record:
description: >
Whether to create a storage record for the artifact.
Requires that push-to-registry is set to true. Defaults to true.
default: true
required: false
show-summary: show-summary:
description: > description: >
Whether to attach a list of generated attestations to the workflow run Whether to attach a list of generated attestations to the workflow run
@@ -68,12 +62,10 @@ outputs:
runs: runs:
using: 'composite' using: 'composite'
steps: steps:
- uses: actions/attest-build-provenance/predicate@864457a58d4733d7f1574bd8821fa24e02cf7538 # predicate@2.0.0 - uses: actions/attest-build-provenance/predicate@1176ef556905f349f669722abf30bce1a6e16e01 # predicate@1.1.5
id: generate-build-provenance-predicate id: generate-build-provenance-predicate
- uses: actions/attest@e59cbc1ad1ac2d59339667419eb8cdde6eb61e3d # v3.2.0 - uses: actions/attest@experimental/header-auth
id: attest id: attest
env:
NODE_OPTIONS: "--max-http-header-size=32768"
with: with:
subject-path: ${{ inputs.subject-path }} subject-path: ${{ inputs.subject-path }}
subject-digest: ${{ inputs.subject-digest }} subject-digest: ${{ inputs.subject-digest }}
@@ -82,6 +74,5 @@ runs:
predicate-type: ${{ steps.generate-build-provenance-predicate.outputs.predicate-type }} predicate-type: ${{ steps.generate-build-provenance-predicate.outputs.predicate-type }}
predicate: ${{ steps.generate-build-provenance-predicate.outputs.predicate }} predicate: ${{ steps.generate-build-provenance-predicate.outputs.predicate }}
push-to-registry: ${{ inputs.push-to-registry }} push-to-registry: ${{ inputs.push-to-registry }}
create-storage-record: ${{ inputs.create-storage-record }}
show-summary: ${{ inputs.show-summary }} show-summary: ${{ inputs.show-summary }}
github-token: ${{ inputs.github-token }} github-token: ${{ inputs.github-token }}
Generated Vendored
+4 -16
View File
@@ -19,7 +19,7 @@ async function pMap(
signal, signal,
} = {}, } = {},
) { ) {
return new Promise((resolve_, reject_) => { return new Promise((resolve, reject_) => {
if (iterable[Symbol.iterator] === undefined && iterable[Symbol.asyncIterator] === undefined) { if (iterable[Symbol.iterator] === undefined && iterable[Symbol.asyncIterator] === undefined) {
throw new TypeError(`Expected \`input\` to be either an \`Iterable\` or \`AsyncIterable\`, got (${typeof iterable})`); throw new TypeError(`Expected \`input\` to be either an \`Iterable\` or \`AsyncIterable\`, got (${typeof iterable})`);
} }
@@ -42,24 +42,10 @@ async function pMap(
let currentIndex = 0; let currentIndex = 0;
const iterator = iterable[Symbol.iterator] === undefined ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator](); const iterator = iterable[Symbol.iterator] === undefined ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator]();
const signalListener = () => {
reject(signal.reason);
};
const cleanup = () => {
signal?.removeEventListener('abort', signalListener);
};
const resolve = value => {
resolve_(value);
cleanup();
};
const reject = reason => { const reject = reason => {
isRejected = true; isRejected = true;
isResolved = true; isResolved = true;
reject_(reason); reject_(reason);
cleanup();
}; };
if (signal) { if (signal) {
@@ -67,7 +53,9 @@ async function pMap(
reject(signal.reason); reject(signal.reason);
} }
signal.addEventListener('abort', signalListener, {once: true}); signal.addEventListener('abort', () => {
reject(signal.reason);
});
} }
const next = async () => { const next = async () => {
Generated Vendored
+4180 -6709
View File
File diff suppressed because it is too large Load Diff
+2262 -2442
View File
File diff suppressed because it is too large Load Diff
+20 -20
View File
@@ -1,7 +1,7 @@
{ {
"name": "actions/attest-build-provenance", "name": "actions/attest-build-provenance",
"description": "Generate signed build provenance attestations", "description": "Generate signed build provenance attestations",
"version": "2.0.0", "version": "1.1.5",
"author": "", "author": "",
"private": true, "private": true,
"homepage": "https://github.com/actions/attest-build-provenance", "homepage": "https://github.com/actions/attest-build-provenance",
@@ -21,15 +21,15 @@
".": "./dist/index.js" ".": "./dist/index.js"
}, },
"engines": { "engines": {
"node": ">=24" "node": ">=20"
}, },
"scripts": { "scripts": {
"bundle": "npm run format:write && npm run package", "bundle": "npm run format:write && npm run package",
"ci-test": "jest", "ci-test": "jest",
"format:write": "prettier --write **/*.ts", "format:write": "prettier --write **/*.ts",
"format:check": "prettier --check **/*.ts", "format:check": "prettier --check **/*.ts",
"lint:eslint": "npx eslint", "lint:eslint": "npx eslint . -c ./.github/linters/eslint.config.mjs",
"lint:markdown": "npx markdownlint --config .markdown-lint.yml \"*.md\"", "lint:markdown": "npx markdownlint --config .github/linters/.markdown-lint.yml \"*.md\"",
"lint": "npm run lint:eslint && npm run lint:markdown", "lint": "npm run lint:eslint && npm run lint:markdown",
"package": "ncc build src/index.ts --license licenses.txt", "package": "ncc build src/index.ts --license licenses.txt",
"package:watch": "npm run package -- --watch", "package:watch": "npm run package -- --watch",
@@ -70,24 +70,24 @@
] ]
}, },
"dependencies": { "dependencies": {
"@actions/attest": "^2.1.0", "@actions/attest": "^1.6.0",
"@actions/core": "^2.0.1" "@actions/core": "^1.11.1"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.39.2", "@eslint/js": "^9.23.0",
"@types/jest": "^30.0.0", "@types/jest": "^29.5.14",
"@types/node": "^25.0.3", "@types/node": "^22.13.14",
"@vercel/ncc": "^0.38.4", "@vercel/ncc": "^0.38.3",
"eslint": "^9.39.2", "eslint": "^9.23.0",
"eslint-plugin-import": "^2.32.0", "eslint-plugin-import": "^2.31.0",
"eslint-plugin-jest": "^29.12.1", "eslint-plugin-jest": "^28.11.0",
"jest": "^30.2.0", "jest": "^29.7.0",
"jose": "^5.9.6", "jose": "^5.9.6",
"markdownlint-cli": "^0.47.0", "markdownlint-cli": "^0.44.0",
"nock": "^14.0.10", "nock": "^14.0.2",
"prettier": "^3.7.4", "prettier": "^3.5.3",
"ts-jest": "^29.4.6", "ts-jest": "^29.3.0",
"typescript": "^5.9.3", "typescript": "^5.8.2",
"typescript-eslint": "^8.51.0" "typescript-eslint": "^8.28.0"
} }
} }
+1 -1
View File
@@ -10,5 +10,5 @@ outputs:
description: > description: >
URI identifying the type of the predicate. URI identifying the type of the predicate.
runs: runs:
using: node24 using: node20
main: ../dist/index.js main: ../dist/index.js
-1
View File
@@ -5,7 +5,6 @@
"module": "NodeNext", "module": "NodeNext",
"rootDir": "./src", "rootDir": "./src",
"moduleResolution": "NodeNext", "moduleResolution": "NodeNext",
"isolatedModules": true,
"baseUrl": "./", "baseUrl": "./",
"sourceMap": true, "sourceMap": true,
"outDir": "./dist", "outDir": "./dist",
-9
View File
@@ -1,9 +0,0 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": true
},
"include": ["./__tests__/**/*", "./src/**/*"],
"exclude": ["./dist", "./node_modules", "./coverage", "*.json"]
}