Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12c083815e | ||
|
|
38ff958ab6 | ||
|
|
60d0be1445 | ||
|
|
32f49af665 | ||
|
|
3f67a24e31 | ||
|
|
e259ee2285 | ||
|
|
58fa41a101 | ||
|
|
b0d8b47eb7 | ||
|
|
9b22bf5c9f | ||
|
|
9cbbc78ff9 |
@@ -175,7 +175,7 @@ fully-qualified image name (e.g. "ghcr.io/user/app" or
|
|||||||
"acme.azurecr.io/user/app"). Do NOT include a tag as part of the image name --
|
"acme.azurecr.io/user/app"). Do NOT include a tag as part of the image name --
|
||||||
the specific image being attested is identified by the supplied digest.
|
the specific image being attested is identified by the supplied digest.
|
||||||
|
|
||||||
> **NOTE**: When pushing to Docker Hub, please use "index.docker.io" as the
|
> **NOTE**: When pushing to Docker Hub, please use "docker.io" as the
|
||||||
> registry portion of the image name.
|
> registry portion of the image name.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
|||||||
@@ -11,6 +11,14 @@ Follow the steps below to tag a new release for the `actions/attest` action.
|
|||||||
gh release create vX.X.X
|
gh release create vX.X.X
|
||||||
```
|
```
|
||||||
|
|
||||||
|
1. Move (or create) the major version tag to point to the same commit tagged
|
||||||
|
above:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
git tag -fa vX -m "vX"
|
||||||
|
git push origin vX --force
|
||||||
|
```
|
||||||
|
|
||||||
1. As appropriate, update any actions like
|
1. As appropriate, update any actions like
|
||||||
[`actions/attest-build-provenance`](https://github.com/actions/attest-build-provenance)
|
[`actions/attest-build-provenance`](https://github.com/actions/attest-build-provenance)
|
||||||
and [`actions/attest-sbom`](https://github.com/actions/attest-sbom) which
|
and [`actions/attest-sbom`](https://github.com/actions/attest-sbom) which
|
||||||
|
|||||||
@@ -116,7 +116,9 @@ describe('action', () => {
|
|||||||
|
|
||||||
expect(runMock).toHaveReturned()
|
expect(runMock).toHaveReturned()
|
||||||
expect(setFailedMock).toHaveBeenCalledWith(
|
expect(setFailedMock).toHaveBeenCalledWith(
|
||||||
expect.stringMatching(/missing "id-token" permission/)
|
new Error(
|
||||||
|
'missing "id-token" permission. Please add "permissions: id-token: write" to your workflow.'
|
||||||
|
)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -131,9 +133,7 @@ describe('action', () => {
|
|||||||
|
|
||||||
expect(runMock).toHaveReturned()
|
expect(runMock).toHaveReturned()
|
||||||
expect(setFailedMock).toHaveBeenCalledWith(
|
expect(setFailedMock).toHaveBeenCalledWith(
|
||||||
expect.stringMatching(
|
new Error('One of subject-path or subject-digest must be provided')
|
||||||
/one of subject-path or subject-digest must be provided/i
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -330,7 +330,9 @@ describe('action', () => {
|
|||||||
|
|
||||||
expect(runMock).toHaveReturned()
|
expect(runMock).toHaveReturned()
|
||||||
expect(setFailedMock).toHaveBeenCalledWith(
|
expect(setFailedMock).toHaveBeenCalledWith(
|
||||||
'Too many subjects specified. The maximum number of subjects is 64.'
|
new Error(
|
||||||
|
'Too many subjects specified. The maximum number of subjects is 64.'
|
||||||
|
)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ import path from 'path'
|
|||||||
import { subjectFromInputs } from '../src/subject'
|
import { subjectFromInputs } from '../src/subject'
|
||||||
|
|
||||||
describe('subjectFromInputs', () => {
|
describe('subjectFromInputs', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
process.env['INPUT_PUSH-TO-REGISTRY'] = 'false'
|
||||||
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
process.env['INPUT_SUBJECT-PATH'] = ''
|
process.env['INPUT_SUBJECT-PATH'] = ''
|
||||||
process.env['INPUT_SUBJECT-DIGEST'] = ''
|
process.env['INPUT_SUBJECT-DIGEST'] = ''
|
||||||
@@ -45,12 +49,12 @@ describe('subjectFromInputs', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('when specifying a subject digest', () => {
|
describe('when specifying a subject digest', () => {
|
||||||
const name = 'subject'
|
const name = 'Subject'
|
||||||
|
|
||||||
describe('when the digest is malformed', () => {
|
describe('when the digest is malformed', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
process.env['INPUT_SUBJECT-DIGEST'] = 'digest'
|
process.env['INPUT_SUBJECT-DIGEST'] = 'digest'
|
||||||
process.env['INPUT_SUBJECT-NAME'] = 'subject'
|
process.env['INPUT_SUBJECT-NAME'] = name
|
||||||
})
|
})
|
||||||
|
|
||||||
it('throws an error', async () => {
|
it('throws an error', async () => {
|
||||||
@@ -63,7 +67,7 @@ describe('subjectFromInputs', () => {
|
|||||||
describe('when the alogrithm is not supported', () => {
|
describe('when the alogrithm is not supported', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
process.env['INPUT_SUBJECT-DIGEST'] = 'md5:deadbeef'
|
process.env['INPUT_SUBJECT-DIGEST'] = 'md5:deadbeef'
|
||||||
process.env['INPUT_SUBJECT-NAME'] = 'subject'
|
process.env['INPUT_SUBJECT-NAME'] = name
|
||||||
})
|
})
|
||||||
|
|
||||||
it('throws an error', async () => {
|
it('throws an error', async () => {
|
||||||
@@ -76,7 +80,7 @@ describe('subjectFromInputs', () => {
|
|||||||
describe('when the sha256 digest is malformed', () => {
|
describe('when the sha256 digest is malformed', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
process.env['INPUT_SUBJECT-DIGEST'] = 'sha256:deadbeef'
|
process.env['INPUT_SUBJECT-DIGEST'] = 'sha256:deadbeef'
|
||||||
process.env['INPUT_SUBJECT-NAME'] = 'subject'
|
process.env['INPUT_SUBJECT-NAME'] = name
|
||||||
})
|
})
|
||||||
|
|
||||||
it('throws an error', async () => {
|
it('throws an error', async () => {
|
||||||
@@ -105,6 +109,28 @@ describe('subjectFromInputs', () => {
|
|||||||
expect(subject[0].digest).toEqual({ [alg]: digest })
|
expect(subject[0].digest).toEqual({ [alg]: digest })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('when the push-to-registry is true', () => {
|
||||||
|
const imageName = 'ghcr.io/FOO/bar'
|
||||||
|
const alg = 'sha256'
|
||||||
|
const digest =
|
||||||
|
'7d070f6b64d9bcc530fe99cc21eaaa4b3c364e0b2d367d7735671fa202a03b32'
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
process.env['INPUT_SUBJECT-DIGEST'] = `${alg}:${digest}`
|
||||||
|
process.env['INPUT_SUBJECT-NAME'] = imageName
|
||||||
|
process.env['INPUT_PUSH-TO-REGISTRY'] = 'true'
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns the subject (with name downcased)', async () => {
|
||||||
|
const subject = await subjectFromInputs()
|
||||||
|
|
||||||
|
expect(subject).toBeDefined()
|
||||||
|
expect(subject).toHaveLength(1)
|
||||||
|
expect(subject[0].name).toEqual(imageName.toLowerCase())
|
||||||
|
expect(subject[0].digest).toEqual({ [alg]: digest })
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('when specifying a subject path', () => {
|
describe('when specifying a subject path', () => {
|
||||||
|
|||||||
643
dist/index.js
generated
vendored
643
dist/index.js
generated
vendored
@@ -11433,7 +11433,7 @@ exports.SignedCertificateTimestamp = SignedCertificateTimestamp;
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
exports.HEADER_OCI_SUBJECT = exports.HEADER_LOCATION = exports.HEADER_IF_MATCH = exports.HEADER_ETAG = exports.HEADER_DIGEST = exports.HEADER_CONTENT_TYPE = exports.HEADER_CONTENT_LENGTH = exports.HEADER_AUTHORIZATION = exports.HEADER_AUTHENTICATE = exports.HEADER_API_VERSION = exports.HEADER_ACCEPT = exports.CONTENT_TYPE_EMPTY_DESCRIPTOR = exports.CONTENT_TYPE_OCTET_STREAM = exports.CONTENT_TYPE_OCI_MANIFEST = exports.CONTENT_TYPE_OCI_INDEX = void 0;
|
exports.HEADER_OCI_SUBJECT = exports.HEADER_LOCATION = exports.HEADER_IF_MATCH = exports.HEADER_ETAG = exports.HEADER_DIGEST = exports.HEADER_CONTENT_TYPE = exports.HEADER_CONTENT_LENGTH = exports.HEADER_AUTHORIZATION = exports.HEADER_AUTHENTICATE = exports.HEADER_API_VERSION = exports.HEADER_ACCEPT = exports.CONTENT_TYPE_EMPTY_DESCRIPTOR = exports.CONTENT_TYPE_OCTET_STREAM = exports.CONTENT_TYPE_DOCKER_MANIFEST_LIST = exports.CONTENT_TYPE_DOCKER_MANIFEST = exports.CONTENT_TYPE_OCI_MANIFEST = exports.CONTENT_TYPE_OCI_INDEX = void 0;
|
||||||
/*
|
/*
|
||||||
Copyright 2023 The Sigstore Authors.
|
Copyright 2023 The Sigstore Authors.
|
||||||
|
|
||||||
@@ -11451,6 +11451,8 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
exports.CONTENT_TYPE_OCI_INDEX = 'application/vnd.oci.image.index.v1+json';
|
exports.CONTENT_TYPE_OCI_INDEX = 'application/vnd.oci.image.index.v1+json';
|
||||||
exports.CONTENT_TYPE_OCI_MANIFEST = 'application/vnd.oci.image.manifest.v1+json';
|
exports.CONTENT_TYPE_OCI_MANIFEST = 'application/vnd.oci.image.manifest.v1+json';
|
||||||
|
exports.CONTENT_TYPE_DOCKER_MANIFEST = 'application/vnd.docker.distribution.manifest.v2+json';
|
||||||
|
exports.CONTENT_TYPE_DOCKER_MANIFEST_LIST = 'application/vnd.docker.distribution.manifest.list.v2+json';
|
||||||
exports.CONTENT_TYPE_OCTET_STREAM = 'application/octet-stream';
|
exports.CONTENT_TYPE_OCTET_STREAM = 'application/octet-stream';
|
||||||
exports.CONTENT_TYPE_EMPTY_DESCRIPTOR = 'application/vnd.oci.empty.v1+json';
|
exports.CONTENT_TYPE_EMPTY_DESCRIPTOR = 'application/vnd.oci.empty.v1+json';
|
||||||
exports.HEADER_ACCEPT = 'Accept';
|
exports.HEADER_ACCEPT = 'Accept';
|
||||||
@@ -11575,6 +11577,96 @@ class OCIError extends Error {
|
|||||||
exports.OCIError = OCIError;
|
exports.OCIError = OCIError;
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 437:
|
||||||
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
/*
|
||||||
|
Copyright 2024 The Sigstore Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
const http2_1 = __nccwpck_require__(85158);
|
||||||
|
const make_fetch_happen_1 = __importDefault(__nccwpck_require__(9525));
|
||||||
|
const proc_log_1 = __nccwpck_require__(56528);
|
||||||
|
const promise_retry_1 = __importDefault(__nccwpck_require__(54742));
|
||||||
|
const { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_TOO_MANY_REQUESTS, HTTP_STATUS_REQUEST_TIMEOUT, } = http2_1.constants;
|
||||||
|
const fetchWithRetry = async (url, options = {}) => {
|
||||||
|
return (0, promise_retry_1.default)(async (retry, attemptNum) => {
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
const logRetry = (reason) => {
|
||||||
|
proc_log_1.log.http('fetch', `${options.method} ${url} attempt ${attemptNum} failed with ${reason}`);
|
||||||
|
};
|
||||||
|
const response = await (0, make_fetch_happen_1.default)(url, {
|
||||||
|
...options,
|
||||||
|
retry: false, // We're handling retries ourselves
|
||||||
|
}).catch((reason) => {
|
||||||
|
logRetry(reason);
|
||||||
|
return retry(reason);
|
||||||
|
});
|
||||||
|
if (retryable(response.status)) {
|
||||||
|
logRetry(response.status);
|
||||||
|
return retry(response);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}, retryOpts(options.retry)).catch((err) => {
|
||||||
|
// If we got an actual error, throw it
|
||||||
|
if (err instanceof Error) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
// Otherwise, return the response (this is simply a retry-able response for
|
||||||
|
// which we exceeded the retry limit)
|
||||||
|
return err;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// Returns a wrapped fetch function with default options
|
||||||
|
fetchWithRetry.defaults = (defaultOptions = {}, wrappedFetch = fetchWithRetry) => {
|
||||||
|
const defaultedFetch = (url, options = {}) => {
|
||||||
|
const finalOptions = {
|
||||||
|
...defaultOptions,
|
||||||
|
...options,
|
||||||
|
headers: { ...defaultOptions.headers, ...options.headers },
|
||||||
|
};
|
||||||
|
return wrappedFetch(url, finalOptions);
|
||||||
|
};
|
||||||
|
defaultedFetch.defaults = (newDefaults = {}) => fetchWithRetry.defaults(newDefaults, defaultedFetch);
|
||||||
|
return defaultedFetch;
|
||||||
|
};
|
||||||
|
// Determine if a status code is retryable. This includes 5xx errors, 408, and
|
||||||
|
// 429.
|
||||||
|
const retryable = (status) => [HTTP_STATUS_REQUEST_TIMEOUT, HTTP_STATUS_TOO_MANY_REQUESTS].includes(status) || status >= HTTP_STATUS_INTERNAL_SERVER_ERROR;
|
||||||
|
// Normalize the retry options to the format expected by promise-retry
|
||||||
|
const retryOpts = (retry) => {
|
||||||
|
if (typeof retry === 'boolean') {
|
||||||
|
return { retries: retry ? 1 : 0 };
|
||||||
|
}
|
||||||
|
else if (typeof retry === 'number') {
|
||||||
|
return { retries: retry };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { retries: 0, ...retry };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports["default"] = fetchWithRetry;
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 79539:
|
/***/ 79539:
|
||||||
@@ -11614,13 +11706,14 @@ limitations under the License.
|
|||||||
const constants_1 = __nccwpck_require__(61319);
|
const constants_1 = __nccwpck_require__(61319);
|
||||||
const error_1 = __nccwpck_require__(60064);
|
const error_1 = __nccwpck_require__(60064);
|
||||||
const registry_1 = __nccwpck_require__(27464);
|
const registry_1 = __nccwpck_require__(27464);
|
||||||
|
const DOCKER_DEFAULT_REGISTRY = 'registry-1.docker.io';
|
||||||
const EMPTY_BLOB = Buffer.from('{}');
|
const EMPTY_BLOB = Buffer.from('{}');
|
||||||
class OCIImage {
|
class OCIImage {
|
||||||
constructor(image, creds, opts) {
|
constructor(image, creds, opts) {
|
||||||
_OCIImage_instances.add(this);
|
_OCIImage_instances.add(this);
|
||||||
_OCIImage_client.set(this, void 0);
|
_OCIImage_client.set(this, void 0);
|
||||||
_OCIImage_credentials.set(this, void 0);
|
_OCIImage_credentials.set(this, void 0);
|
||||||
__classPrivateFieldSet(this, _OCIImage_client, new registry_1.RegistryClient(image.registry, image.path, opts), "f");
|
__classPrivateFieldSet(this, _OCIImage_client, new registry_1.RegistryClient(canonicalizeRegistryName(image.registry), image.path, opts), "f");
|
||||||
__classPrivateFieldSet(this, _OCIImage_credentials, creds, "f");
|
__classPrivateFieldSet(this, _OCIImage_credentials, creds, "f");
|
||||||
}
|
}
|
||||||
async addArtifact(opts) {
|
async addArtifact(opts) {
|
||||||
@@ -11750,6 +11843,13 @@ const newIndex = () => ({
|
|||||||
const digestToTag = (digest) => {
|
const digestToTag = (digest) => {
|
||||||
return digest.replace(':', '-');
|
return digest.replace(':', '-');
|
||||||
};
|
};
|
||||||
|
// Canonicalize the registry name to match the format used by the registry
|
||||||
|
// client. This is used primarily to handle the special case of the Docker Hub
|
||||||
|
// registry.
|
||||||
|
// https://github.com/moby/moby/blob/v24.0.2/registry/config.go#L25-L48
|
||||||
|
const canonicalizeRegistryName = (registry) => {
|
||||||
|
return registry.endsWith('docker.io') ? DOCKER_DEFAULT_REGISTRY : registry;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
@@ -11869,11 +11969,17 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
const make_fetch_happen_1 = __importDefault(__nccwpck_require__(9525));
|
|
||||||
const node_crypto_1 = __importDefault(__nccwpck_require__(6005));
|
const node_crypto_1 = __importDefault(__nccwpck_require__(6005));
|
||||||
const constants_1 = __nccwpck_require__(61319);
|
const constants_1 = __nccwpck_require__(61319);
|
||||||
const credentials_1 = __nccwpck_require__(95475);
|
const credentials_1 = __nccwpck_require__(95475);
|
||||||
const error_1 = __nccwpck_require__(60064);
|
const error_1 = __nccwpck_require__(60064);
|
||||||
|
const fetch_1 = __importDefault(__nccwpck_require__(437));
|
||||||
|
const ALL_MANIFEST_MEDIA_TYPES = [
|
||||||
|
constants_1.CONTENT_TYPE_OCI_INDEX,
|
||||||
|
constants_1.CONTENT_TYPE_OCI_MANIFEST,
|
||||||
|
constants_1.CONTENT_TYPE_DOCKER_MANIFEST,
|
||||||
|
constants_1.CONTENT_TYPE_DOCKER_MANIFEST_LIST,
|
||||||
|
].join(',');
|
||||||
class RegistryClient {
|
class RegistryClient {
|
||||||
constructor(registry, repository, opts) {
|
constructor(registry, repository, opts) {
|
||||||
_RegistryClient_instances.add(this);
|
_RegistryClient_instances.add(this);
|
||||||
@@ -11881,7 +11987,7 @@ class RegistryClient {
|
|||||||
_RegistryClient_repository.set(this, void 0);
|
_RegistryClient_repository.set(this, void 0);
|
||||||
_RegistryClient_fetch.set(this, void 0);
|
_RegistryClient_fetch.set(this, void 0);
|
||||||
__classPrivateFieldSet(this, _RegistryClient_repository, repository, "f");
|
__classPrivateFieldSet(this, _RegistryClient_repository, repository, "f");
|
||||||
__classPrivateFieldSet(this, _RegistryClient_fetch, make_fetch_happen_1.default.defaults(opts), "f");
|
__classPrivateFieldSet(this, _RegistryClient_fetch, fetch_1.default.defaults(opts), "f");
|
||||||
// Use http for localhost registries, https otherwise
|
// Use http for localhost registries, https otherwise
|
||||||
const hostname = new URL(`http://${registry}`).hostname;
|
const hostname = new URL(`http://${registry}`).hostname;
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
@@ -11968,9 +12074,7 @@ class RegistryClient {
|
|||||||
async checkManifest(reference) {
|
async checkManifest(reference) {
|
||||||
const response = await __classPrivateFieldGet(this, _RegistryClient_fetch, "f").call(this, `${__classPrivateFieldGet(this, _RegistryClient_baseURL, "f")}/v2/${__classPrivateFieldGet(this, _RegistryClient_repository, "f")}/manifests/${reference}`, {
|
const response = await __classPrivateFieldGet(this, _RegistryClient_fetch, "f").call(this, `${__classPrivateFieldGet(this, _RegistryClient_baseURL, "f")}/v2/${__classPrivateFieldGet(this, _RegistryClient_repository, "f")}/manifests/${reference}`, {
|
||||||
method: 'HEAD',
|
method: 'HEAD',
|
||||||
headers: {
|
headers: { [constants_1.HEADER_ACCEPT]: ALL_MANIFEST_MEDIA_TYPES },
|
||||||
[constants_1.HEADER_ACCEPT]: `${constants_1.CONTENT_TYPE_OCI_MANIFEST},${constants_1.CONTENT_TYPE_OCI_INDEX}`,
|
|
||||||
},
|
|
||||||
}).then((0, error_1.ensureStatus)(200));
|
}).then((0, error_1.ensureStatus)(200));
|
||||||
const mediaType = response.headers.get(constants_1.HEADER_CONTENT_TYPE) ||
|
const mediaType = response.headers.get(constants_1.HEADER_CONTENT_TYPE) ||
|
||||||
/* istanbul ignore next */ '';
|
/* istanbul ignore next */ '';
|
||||||
@@ -11982,9 +12086,7 @@ class RegistryClient {
|
|||||||
// Retrieves a manifest by reference
|
// Retrieves a manifest by reference
|
||||||
async getManifest(reference) {
|
async getManifest(reference) {
|
||||||
const response = await __classPrivateFieldGet(this, _RegistryClient_fetch, "f").call(this, `${__classPrivateFieldGet(this, _RegistryClient_baseURL, "f")}/v2/${__classPrivateFieldGet(this, _RegistryClient_repository, "f")}/manifests/${reference}`, {
|
const response = await __classPrivateFieldGet(this, _RegistryClient_fetch, "f").call(this, `${__classPrivateFieldGet(this, _RegistryClient_baseURL, "f")}/v2/${__classPrivateFieldGet(this, _RegistryClient_repository, "f")}/manifests/${reference}`, {
|
||||||
headers: {
|
headers: { [constants_1.HEADER_ACCEPT]: ALL_MANIFEST_MEDIA_TYPES },
|
||||||
[constants_1.HEADER_ACCEPT]: `${constants_1.CONTENT_TYPE_OCI_MANIFEST},${constants_1.CONTENT_TYPE_OCI_INDEX}`,
|
|
||||||
},
|
|
||||||
}).then((0, error_1.ensureStatus)(200));
|
}).then((0, error_1.ensureStatus)(200));
|
||||||
const body = await response.json();
|
const body = await response.json();
|
||||||
const mediaType = response.headers.get(constants_1.HEADER_CONTENT_TYPE) ||
|
const mediaType = response.headers.get(constants_1.HEADER_CONTENT_TYPE) ||
|
||||||
@@ -13923,8 +14025,23 @@ exports.internalError = internalError;
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2023 The Sigstore Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
exports.checkStatus = exports.HTTPError = void 0;
|
exports.HTTPError = void 0;
|
||||||
class HTTPError extends Error {
|
class HTTPError extends Error {
|
||||||
constructor({ status, message, location, }) {
|
constructor({ status, message, location, }) {
|
||||||
super(`(${status}) ${message}`);
|
super(`(${status}) ${message}`);
|
||||||
@@ -13933,38 +14050,11 @@ class HTTPError extends Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.HTTPError = HTTPError;
|
exports.HTTPError = HTTPError;
|
||||||
const checkStatus = async (response) => {
|
|
||||||
if (response.ok) {
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
let message = response.statusText;
|
|
||||||
const location = response.headers?.get('Location') || undefined;
|
|
||||||
const contentType = response.headers?.get('Content-Type');
|
|
||||||
// If response type is JSON, try to parse the body for a message
|
|
||||||
if (contentType?.includes('application/json')) {
|
|
||||||
try {
|
|
||||||
await response.json().then((body) => {
|
|
||||||
message = body.message;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new HTTPError({
|
|
||||||
status: response.status,
|
|
||||||
message: message,
|
|
||||||
location: location,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
exports.checkStatus = checkStatus;
|
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 62960:
|
/***/ 78509:
|
||||||
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
@@ -13972,6 +14062,110 @@ exports.checkStatus = checkStatus;
|
|||||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
};
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
exports.fetchWithRetry = void 0;
|
||||||
|
/*
|
||||||
|
Copyright 2023 The Sigstore Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
const http2_1 = __nccwpck_require__(85158);
|
||||||
|
const make_fetch_happen_1 = __importDefault(__nccwpck_require__(9525));
|
||||||
|
const proc_log_1 = __nccwpck_require__(56528);
|
||||||
|
const promise_retry_1 = __importDefault(__nccwpck_require__(54742));
|
||||||
|
const util_1 = __nccwpck_require__(90724);
|
||||||
|
const error_1 = __nccwpck_require__(11294);
|
||||||
|
const { HTTP2_HEADER_LOCATION, HTTP2_HEADER_CONTENT_TYPE, HTTP2_HEADER_USER_AGENT, HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_TOO_MANY_REQUESTS, HTTP_STATUS_REQUEST_TIMEOUT, } = http2_1.constants;
|
||||||
|
async function fetchWithRetry(url, options) {
|
||||||
|
return (0, promise_retry_1.default)(async (retry, attemptNum) => {
|
||||||
|
const method = options.method || 'POST';
|
||||||
|
const headers = {
|
||||||
|
[HTTP2_HEADER_USER_AGENT]: util_1.ua.getUserAgent(),
|
||||||
|
...options.headers,
|
||||||
|
};
|
||||||
|
const response = await (0, make_fetch_happen_1.default)(url, {
|
||||||
|
method,
|
||||||
|
headers,
|
||||||
|
body: options.body,
|
||||||
|
timeout: options.timeout,
|
||||||
|
retry: false, // We're handling retries ourselves
|
||||||
|
}).catch((reason) => {
|
||||||
|
proc_log_1.log.http('fetch', `${method} ${url} attempt ${attemptNum} failed with ${reason}`);
|
||||||
|
return retry(reason);
|
||||||
|
});
|
||||||
|
if (response.ok) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const error = await errorFromResponse(response);
|
||||||
|
proc_log_1.log.http('fetch', `${method} ${url} attempt ${attemptNum} failed with ${response.status}`);
|
||||||
|
if (retryable(response.status)) {
|
||||||
|
return retry(error);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, retryOpts(options.retry));
|
||||||
|
}
|
||||||
|
exports.fetchWithRetry = fetchWithRetry;
|
||||||
|
// Translate a Response into an HTTPError instance. This will attempt to parse
|
||||||
|
// the response body for a message, but will default to the statusText if none
|
||||||
|
// is found.
|
||||||
|
const errorFromResponse = async (response) => {
|
||||||
|
let message = response.statusText;
|
||||||
|
const location = response.headers?.get(HTTP2_HEADER_LOCATION) || undefined;
|
||||||
|
const contentType = response.headers?.get(HTTP2_HEADER_CONTENT_TYPE);
|
||||||
|
// If response type is JSON, try to parse the body for a message
|
||||||
|
if (contentType?.includes('application/json')) {
|
||||||
|
try {
|
||||||
|
const body = await response.json();
|
||||||
|
message = body.message || message;
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new error_1.HTTPError({
|
||||||
|
status: response.status,
|
||||||
|
message: message,
|
||||||
|
location: location,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// Determine if a status code is retryable. This includes 5xx errors, 408, and
|
||||||
|
// 429.
|
||||||
|
const retryable = (status) => [HTTP_STATUS_REQUEST_TIMEOUT, HTTP_STATUS_TOO_MANY_REQUESTS].includes(status) || status >= HTTP_STATUS_INTERNAL_SERVER_ERROR;
|
||||||
|
// Normalize the retry options to the format expected by promise-retry
|
||||||
|
const retryOpts = (retry) => {
|
||||||
|
if (typeof retry === 'boolean') {
|
||||||
|
return { retries: retry ? 1 : 0 };
|
||||||
|
}
|
||||||
|
else if (typeof retry === 'number') {
|
||||||
|
return { retries: retry };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { retries: 0, ...retry };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 62960:
|
||||||
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
exports.Fulcio = void 0;
|
exports.Fulcio = void 0;
|
||||||
/*
|
/*
|
||||||
@@ -13989,33 +14183,26 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
const make_fetch_happen_1 = __importDefault(__nccwpck_require__(9525));
|
const fetch_1 = __nccwpck_require__(78509);
|
||||||
const util_1 = __nccwpck_require__(90724);
|
|
||||||
const error_1 = __nccwpck_require__(11294);
|
|
||||||
/**
|
/**
|
||||||
* Fulcio API client.
|
* Fulcio API client.
|
||||||
*/
|
*/
|
||||||
class Fulcio {
|
class Fulcio {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
this.fetch = make_fetch_happen_1.default.defaults({
|
this.options = options;
|
||||||
retry: options.retry,
|
|
||||||
timeout: options.timeout,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'User-Agent': util_1.ua.getUserAgent(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.baseUrl = options.baseURL;
|
|
||||||
}
|
}
|
||||||
async createSigningCertificate(request) {
|
async createSigningCertificate(request) {
|
||||||
const url = `${this.baseUrl}/api/v2/signingCert`;
|
const { baseURL, retry, timeout } = this.options;
|
||||||
const response = await this.fetch(url, {
|
const url = `${baseURL}/api/v2/signingCert`;
|
||||||
method: 'POST',
|
const response = await (0, fetch_1.fetchWithRetry)(url, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
body: JSON.stringify(request),
|
body: JSON.stringify(request),
|
||||||
|
timeout,
|
||||||
|
retry,
|
||||||
});
|
});
|
||||||
await (0, error_1.checkStatus)(response);
|
return response.json();
|
||||||
const data = await response.json();
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Fulcio = Fulcio;
|
exports.Fulcio = Fulcio;
|
||||||
@@ -14024,13 +14211,10 @@ exports.Fulcio = Fulcio;
|
|||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 56205:
|
/***/ 56205:
|
||||||
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
exports.Rekor = void 0;
|
exports.Rekor = void 0;
|
||||||
/*
|
/*
|
||||||
@@ -14048,23 +14232,13 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
const make_fetch_happen_1 = __importDefault(__nccwpck_require__(9525));
|
const fetch_1 = __nccwpck_require__(78509);
|
||||||
const util_1 = __nccwpck_require__(90724);
|
|
||||||
const error_1 = __nccwpck_require__(11294);
|
|
||||||
/**
|
/**
|
||||||
* Rekor API client.
|
* Rekor API client.
|
||||||
*/
|
*/
|
||||||
class Rekor {
|
class Rekor {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
this.fetch = make_fetch_happen_1.default.defaults({
|
this.options = options;
|
||||||
retry: options.retry,
|
|
||||||
timeout: options.timeout,
|
|
||||||
headers: {
|
|
||||||
Accept: 'application/json',
|
|
||||||
'User-Agent': util_1.ua.getUserAgent(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.baseUrl = options.baseURL;
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Create a new entry in the Rekor log.
|
* Create a new entry in the Rekor log.
|
||||||
@@ -14072,13 +14246,17 @@ class Rekor {
|
|||||||
* @returns {Promise<Entry>} The created entry
|
* @returns {Promise<Entry>} The created entry
|
||||||
*/
|
*/
|
||||||
async createEntry(propsedEntry) {
|
async createEntry(propsedEntry) {
|
||||||
const url = `${this.baseUrl}/api/v1/log/entries`;
|
const { baseURL, timeout, retry } = this.options;
|
||||||
const response = await this.fetch(url, {
|
const url = `${baseURL}/api/v1/log/entries`;
|
||||||
method: 'POST',
|
const response = await (0, fetch_1.fetchWithRetry)(url, {
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
body: JSON.stringify(propsedEntry),
|
body: JSON.stringify(propsedEntry),
|
||||||
|
timeout,
|
||||||
|
retry,
|
||||||
});
|
});
|
||||||
await (0, error_1.checkStatus)(response);
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return entryFromResponse(data);
|
return entryFromResponse(data);
|
||||||
}
|
}
|
||||||
@@ -14088,45 +14266,19 @@ class Rekor {
|
|||||||
* @returns {Promise<Entry>} The retrieved entry
|
* @returns {Promise<Entry>} The retrieved entry
|
||||||
*/
|
*/
|
||||||
async getEntry(uuid) {
|
async getEntry(uuid) {
|
||||||
const url = `${this.baseUrl}/api/v1/log/entries/${uuid}`;
|
const { baseURL, timeout, retry } = this.options;
|
||||||
const response = await this.fetch(url);
|
const url = `${baseURL}/api/v1/log/entries/${uuid}`;
|
||||||
await (0, error_1.checkStatus)(response);
|
const response = await (0, fetch_1.fetchWithRetry)(url, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
},
|
||||||
|
timeout,
|
||||||
|
retry,
|
||||||
|
});
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
return entryFromResponse(data);
|
return entryFromResponse(data);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Search the Rekor log index for entries matching the given query.
|
|
||||||
* @param opts {SearchIndex} Options to search the Rekor log
|
|
||||||
* @returns {Promise<string[]>} UUIDs of matching entries
|
|
||||||
*/
|
|
||||||
async searchIndex(opts) {
|
|
||||||
const url = `${this.baseUrl}/api/v1/index/retrieve`;
|
|
||||||
const response = await this.fetch(url, {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify(opts),
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
});
|
|
||||||
await (0, error_1.checkStatus)(response);
|
|
||||||
const data = await response.json();
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Search the Rekor logs for matching the given query.
|
|
||||||
* @param opts {SearchLogQuery} Query to search the Rekor log
|
|
||||||
* @returns {Promise<Entry[]>} List of matching entries
|
|
||||||
*/
|
|
||||||
async searchLog(opts) {
|
|
||||||
const url = `${this.baseUrl}/api/v1/log/entries/retrieve`;
|
|
||||||
const response = await this.fetch(url, {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify(opts),
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
});
|
|
||||||
await (0, error_1.checkStatus)(response);
|
|
||||||
const rawData = await response.json();
|
|
||||||
const data = rawData.map((d) => entryFromResponse(d));
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
exports.Rekor = Rekor;
|
exports.Rekor = Rekor;
|
||||||
// Unpack the response from the Rekor API into a more convenient format.
|
// Unpack the response from the Rekor API into a more convenient format.
|
||||||
@@ -14147,13 +14299,10 @@ function entryFromResponse(data) {
|
|||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 82759:
|
/***/ 82759:
|
||||||
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
exports.TimestampAuthority = void 0;
|
exports.TimestampAuthority = void 0;
|
||||||
/*
|
/*
|
||||||
@@ -14171,28 +14320,22 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
const make_fetch_happen_1 = __importDefault(__nccwpck_require__(9525));
|
const fetch_1 = __nccwpck_require__(78509);
|
||||||
const util_1 = __nccwpck_require__(90724);
|
|
||||||
const error_1 = __nccwpck_require__(11294);
|
|
||||||
class TimestampAuthority {
|
class TimestampAuthority {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
this.fetch = make_fetch_happen_1.default.defaults({
|
this.options = options;
|
||||||
retry: options.retry,
|
|
||||||
timeout: options.timeout,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'User-Agent': util_1.ua.getUserAgent(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.baseUrl = options.baseURL;
|
|
||||||
}
|
}
|
||||||
async createTimestamp(request) {
|
async createTimestamp(request) {
|
||||||
const url = `${this.baseUrl}/api/v1/timestamp`;
|
const { baseURL, timeout, retry } = this.options;
|
||||||
const response = await this.fetch(url, {
|
const url = `${baseURL}/api/v1/timestamp`;
|
||||||
method: 'POST',
|
const response = await (0, fetch_1.fetchWithRetry)(url, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
body: JSON.stringify(request),
|
body: JSON.stringify(request),
|
||||||
|
timeout,
|
||||||
|
retry,
|
||||||
});
|
});
|
||||||
await (0, error_1.checkStatus)(response);
|
|
||||||
return response.buffer();
|
return response.buffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40919,6 +41062,8 @@ class CacheEntry {
|
|||||||
const cacheWritePromise = new Promise((resolve, reject) => {
|
const cacheWritePromise = new Promise((resolve, reject) => {
|
||||||
cacheWriteResolve = resolve
|
cacheWriteResolve = resolve
|
||||||
cacheWriteReject = reject
|
cacheWriteReject = reject
|
||||||
|
}).catch((err) => {
|
||||||
|
body.emit('error', err)
|
||||||
})
|
})
|
||||||
|
|
||||||
body = new CachingMinipassPipeline({ events: ['integrity', 'size'] }, new MinipassFlush({
|
body = new CachingMinipassPipeline({ events: ['integrity', 'size'] }, new MinipassFlush({
|
||||||
@@ -41673,6 +41818,7 @@ const { Minipass } = __nccwpck_require__(14968)
|
|||||||
const fetch = __nccwpck_require__(68998)
|
const fetch = __nccwpck_require__(68998)
|
||||||
const promiseRetry = __nccwpck_require__(54742)
|
const promiseRetry = __nccwpck_require__(54742)
|
||||||
const ssri = __nccwpck_require__(4406)
|
const ssri = __nccwpck_require__(4406)
|
||||||
|
const { log } = __nccwpck_require__(56528)
|
||||||
|
|
||||||
const CachingMinipassPipeline = __nccwpck_require__(61064)
|
const CachingMinipassPipeline = __nccwpck_require__(61064)
|
||||||
const { getAgent } = __nccwpck_require__(79907)
|
const { getAgent } = __nccwpck_require__(79907)
|
||||||
@@ -41760,6 +41906,8 @@ const remoteFetch = (request, options) => {
|
|||||||
options.onRetry(res)
|
options.onRetry(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* eslint-disable-next-line max-len */
|
||||||
|
log.http('fetch', `${req.method} ${req.url} attempt ${attemptNum} failed with ${res.status}`)
|
||||||
return retryHandler(res)
|
return retryHandler(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41783,6 +41931,7 @@ const remoteFetch = (request, options) => {
|
|||||||
options.onRetry(err)
|
options.onRetry(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.http('fetch', `${req.method} ${req.url} attempt ${attemptNum} failed with ${err.code}`)
|
||||||
return retryHandler(err)
|
return retryHandler(err)
|
||||||
}
|
}
|
||||||
}, options.retry).catch((err) => {
|
}, options.retry).catch((err) => {
|
||||||
@@ -49022,6 +49171,166 @@ module.exports = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ 56528:
|
||||||
|
/***/ ((module) => {
|
||||||
|
|
||||||
|
const META = Symbol('proc-log.meta')
|
||||||
|
module.exports = {
|
||||||
|
META: META,
|
||||||
|
output: {
|
||||||
|
LEVELS: [
|
||||||
|
'standard',
|
||||||
|
'error',
|
||||||
|
'buffer',
|
||||||
|
'flush',
|
||||||
|
],
|
||||||
|
KEYS: {
|
||||||
|
standard: 'standard',
|
||||||
|
error: 'error',
|
||||||
|
buffer: 'buffer',
|
||||||
|
flush: 'flush',
|
||||||
|
},
|
||||||
|
standard: function (...args) {
|
||||||
|
return process.emit('output', 'standard', ...args)
|
||||||
|
},
|
||||||
|
error: function (...args) {
|
||||||
|
return process.emit('output', 'error', ...args)
|
||||||
|
},
|
||||||
|
buffer: function (...args) {
|
||||||
|
return process.emit('output', 'buffer', ...args)
|
||||||
|
},
|
||||||
|
flush: function (...args) {
|
||||||
|
return process.emit('output', 'flush', ...args)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
log: {
|
||||||
|
LEVELS: [
|
||||||
|
'notice',
|
||||||
|
'error',
|
||||||
|
'warn',
|
||||||
|
'info',
|
||||||
|
'verbose',
|
||||||
|
'http',
|
||||||
|
'silly',
|
||||||
|
'timing',
|
||||||
|
'pause',
|
||||||
|
'resume',
|
||||||
|
],
|
||||||
|
KEYS: {
|
||||||
|
notice: 'notice',
|
||||||
|
error: 'error',
|
||||||
|
warn: 'warn',
|
||||||
|
info: 'info',
|
||||||
|
verbose: 'verbose',
|
||||||
|
http: 'http',
|
||||||
|
silly: 'silly',
|
||||||
|
timing: 'timing',
|
||||||
|
pause: 'pause',
|
||||||
|
resume: 'resume',
|
||||||
|
},
|
||||||
|
error: function (...args) {
|
||||||
|
return process.emit('log', 'error', ...args)
|
||||||
|
},
|
||||||
|
notice: function (...args) {
|
||||||
|
return process.emit('log', 'notice', ...args)
|
||||||
|
},
|
||||||
|
warn: function (...args) {
|
||||||
|
return process.emit('log', 'warn', ...args)
|
||||||
|
},
|
||||||
|
info: function (...args) {
|
||||||
|
return process.emit('log', 'info', ...args)
|
||||||
|
},
|
||||||
|
verbose: function (...args) {
|
||||||
|
return process.emit('log', 'verbose', ...args)
|
||||||
|
},
|
||||||
|
http: function (...args) {
|
||||||
|
return process.emit('log', 'http', ...args)
|
||||||
|
},
|
||||||
|
silly: function (...args) {
|
||||||
|
return process.emit('log', 'silly', ...args)
|
||||||
|
},
|
||||||
|
timing: function (...args) {
|
||||||
|
return process.emit('log', 'timing', ...args)
|
||||||
|
},
|
||||||
|
pause: function () {
|
||||||
|
return process.emit('log', 'pause')
|
||||||
|
},
|
||||||
|
resume: function () {
|
||||||
|
return process.emit('log', 'resume')
|
||||||
|
},
|
||||||
|
},
|
||||||
|
time: {
|
||||||
|
LEVELS: [
|
||||||
|
'start',
|
||||||
|
'end',
|
||||||
|
],
|
||||||
|
KEYS: {
|
||||||
|
start: 'start',
|
||||||
|
end: 'end',
|
||||||
|
},
|
||||||
|
start: function (name, fn) {
|
||||||
|
process.emit('time', 'start', name)
|
||||||
|
function end () {
|
||||||
|
return process.emit('time', 'end', name)
|
||||||
|
}
|
||||||
|
if (typeof fn === 'function') {
|
||||||
|
const res = fn()
|
||||||
|
if (res && res.finally) {
|
||||||
|
return res.finally(end)
|
||||||
|
}
|
||||||
|
end()
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
return end
|
||||||
|
},
|
||||||
|
end: function (name) {
|
||||||
|
return process.emit('time', 'end', name)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
input: {
|
||||||
|
LEVELS: [
|
||||||
|
'start',
|
||||||
|
'end',
|
||||||
|
'read',
|
||||||
|
],
|
||||||
|
KEYS: {
|
||||||
|
start: 'start',
|
||||||
|
end: 'end',
|
||||||
|
read: 'read',
|
||||||
|
},
|
||||||
|
start: function (fn) {
|
||||||
|
process.emit('input', 'start')
|
||||||
|
function end () {
|
||||||
|
return process.emit('input', 'end')
|
||||||
|
}
|
||||||
|
if (typeof fn === 'function') {
|
||||||
|
const res = fn()
|
||||||
|
if (res && res.finally) {
|
||||||
|
return res.finally(end)
|
||||||
|
}
|
||||||
|
end()
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
return end
|
||||||
|
},
|
||||||
|
end: function () {
|
||||||
|
return process.emit('input', 'end')
|
||||||
|
},
|
||||||
|
read: function (...args) {
|
||||||
|
let resolve, reject
|
||||||
|
const promise = new Promise((_resolve, _reject) => {
|
||||||
|
resolve = _resolve
|
||||||
|
reject = _reject
|
||||||
|
})
|
||||||
|
process.emit('input', 'read', resolve, reject, ...args)
|
||||||
|
return promise
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 54742:
|
/***/ 54742:
|
||||||
@@ -79642,14 +79951,25 @@ const endpoints_1 = __nccwpck_require__(69112);
|
|||||||
const predicate_1 = __nccwpck_require__(72103);
|
const predicate_1 = __nccwpck_require__(72103);
|
||||||
const subject_1 = __nccwpck_require__(95206);
|
const subject_1 = __nccwpck_require__(95206);
|
||||||
const COLOR_CYAN = '\x1B[36m';
|
const COLOR_CYAN = '\x1B[36m';
|
||||||
|
const COLOR_GRAY = '\x1B[38;5;244m';
|
||||||
const COLOR_DEFAULT = '\x1B[39m';
|
const COLOR_DEFAULT = '\x1B[39m';
|
||||||
const ATTESTATION_FILE_NAME = 'attestation.jsonl';
|
const ATTESTATION_FILE_NAME = 'attestation.jsonl';
|
||||||
const MAX_SUBJECT_COUNT = 64;
|
const MAX_SUBJECT_COUNT = 64;
|
||||||
|
const OCI_TIMEOUT = 2000;
|
||||||
|
const OCI_RETRY = 3;
|
||||||
|
/* istanbul ignore next */
|
||||||
|
const logHandler = (level, ...args) => {
|
||||||
|
// Send any HTTP-related log events to the GitHub Actions debug log
|
||||||
|
if (level === 'http') {
|
||||||
|
core.debug(args.join(' '));
|
||||||
|
}
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* The main function for the action.
|
* The main function for the action.
|
||||||
* @returns {Promise<void>} Resolves when the action is complete.
|
* @returns {Promise<void>} Resolves when the action is complete.
|
||||||
*/
|
*/
|
||||||
async function run() {
|
async function run() {
|
||||||
|
process.on('log', logHandler);
|
||||||
// Provenance visibility will be public ONLY if we can confirm that the
|
// Provenance visibility will be public ONLY if we can confirm that the
|
||||||
// repository is public AND the undocumented "private-signing" arg is NOT set.
|
// repository is public AND the undocumented "private-signing" arg is NOT set.
|
||||||
// Otherwise, it will be private.
|
// Otherwise, it will be private.
|
||||||
@@ -79694,13 +80014,17 @@ async function run() {
|
|||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
// Fail the workflow run if an error occurs
|
// Fail the workflow run if an error occurs
|
||||||
core.setFailed(err instanceof Error ? err.message : /* istanbul ignore next */ `${err}`);
|
core.setFailed(err instanceof Error ? err : /* istanbul ignore next */ `${err}`);
|
||||||
|
// Log the cause of the error if one is available
|
||||||
/* istanbul ignore if */
|
/* istanbul ignore if */
|
||||||
if (err instanceof Error && 'cause' in err) {
|
if (err instanceof Error && 'cause' in err) {
|
||||||
const innerErr = err.cause;
|
const innerErr = err.cause;
|
||||||
core.debug(innerErr instanceof Error ? innerErr.message : `${innerErr}}`);
|
core.info(mute(innerErr instanceof Error ? innerErr.toString() : `${innerErr}`));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
process.removeListener('log', logHandler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
exports.run = run;
|
exports.run = run;
|
||||||
const createAttestation = async (subject, predicate, sigstoreInstance) => {
|
const createAttestation = async (subject, predicate, sigstoreInstance) => {
|
||||||
@@ -79737,14 +80061,19 @@ const createAttestation = async (subject, predicate, sigstoreInstance) => {
|
|||||||
annotations: {
|
annotations: {
|
||||||
'dev.sigstore.bundle.content': 'dsse-envelope',
|
'dev.sigstore.bundle.content': 'dsse-envelope',
|
||||||
'dev.sigstore.bundle.predicateType': core.getInput('predicate-type')
|
'dev.sigstore.bundle.predicateType': core.getInput('predicate-type')
|
||||||
}
|
},
|
||||||
|
fetchOpts: { timeout: OCI_TIMEOUT, retry: OCI_RETRY }
|
||||||
});
|
});
|
||||||
core.info(highlight('Attestation uploaded to registry'));
|
core.info(highlight('Attestation uploaded to registry'));
|
||||||
core.info(`${subject.name}@${artifact.digest}`);
|
core.info(`${subject.name}@${artifact.digest}`);
|
||||||
}
|
}
|
||||||
return attestation;
|
return attestation;
|
||||||
};
|
};
|
||||||
|
// Emphasis string using ANSI color codes
|
||||||
const highlight = (str) => `${COLOR_CYAN}${str}${COLOR_DEFAULT}`;
|
const highlight = (str) => `${COLOR_CYAN}${str}${COLOR_DEFAULT}`;
|
||||||
|
// De-emphasize string using ANSI color codes
|
||||||
|
/* istanbul ignore next */
|
||||||
|
const mute = (str) => `${COLOR_GRAY}${str}${COLOR_DEFAULT}`;
|
||||||
const tempDir = () => {
|
const tempDir = () => {
|
||||||
const basePath = process.env['RUNNER_TEMP'];
|
const basePath = process.env['RUNNER_TEMP'];
|
||||||
/* istanbul ignore if */
|
/* istanbul ignore if */
|
||||||
@@ -79869,6 +80198,9 @@ const subjectFromInputs = async () => {
|
|||||||
const subjectPath = core.getInput('subject-path', { required: false });
|
const subjectPath = core.getInput('subject-path', { required: false });
|
||||||
const subjectDigest = core.getInput('subject-digest', { required: false });
|
const subjectDigest = core.getInput('subject-digest', { required: false });
|
||||||
const subjectName = core.getInput('subject-name', { required: false });
|
const subjectName = core.getInput('subject-name', { required: false });
|
||||||
|
const pushToRegistry = core.getBooleanInput('push-to-registry', {
|
||||||
|
required: false
|
||||||
|
});
|
||||||
if (!subjectPath && !subjectDigest) {
|
if (!subjectPath && !subjectDigest) {
|
||||||
throw new Error('One of subject-path or subject-digest must be provided');
|
throw new Error('One of subject-path or subject-digest must be provided');
|
||||||
}
|
}
|
||||||
@@ -79878,11 +80210,14 @@ const subjectFromInputs = async () => {
|
|||||||
if (subjectDigest && !subjectName) {
|
if (subjectDigest && !subjectName) {
|
||||||
throw new Error('subject-name must be provided when using subject-digest');
|
throw new Error('subject-name must be provided when using subject-digest');
|
||||||
}
|
}
|
||||||
|
// If push-to-registry is enabled, ensure the subject name is lowercase
|
||||||
|
// to conform to OCI image naming conventions
|
||||||
|
const name = pushToRegistry ? subjectName.toLowerCase() : subjectName;
|
||||||
if (subjectPath) {
|
if (subjectPath) {
|
||||||
return await getSubjectFromPath(subjectPath, subjectName);
|
return await getSubjectFromPath(subjectPath, name);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return [getSubjectFromDigest(subjectDigest, subjectName)];
|
return [getSubjectFromDigest(subjectDigest, name)];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
exports.subjectFromInputs = subjectFromInputs;
|
exports.subjectFromInputs = subjectFromInputs;
|
||||||
@@ -83326,7 +83661,7 @@ exports.LRUCache = LRUCache;
|
|||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
exports.Glob = void 0;
|
exports.Glob = void 0;
|
||||||
const minimatch_1 = __nccwpck_require__(7111);
|
const minimatch_1 = __nccwpck_require__(7111);
|
||||||
const path_scurry_1 = __nccwpck_require__(69569);
|
const path_scurry_1 = __nccwpck_require__(51081);
|
||||||
const url_1 = __nccwpck_require__(57310);
|
const url_1 = __nccwpck_require__(57310);
|
||||||
const pattern_js_1 = __nccwpck_require__(92895);
|
const pattern_js_1 = __nccwpck_require__(92895);
|
||||||
const walker_js_1 = __nccwpck_require__(45548);
|
const walker_js_1 = __nccwpck_require__(45548);
|
||||||
@@ -89034,7 +89369,7 @@ exports.Minipass = Minipass;
|
|||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
/***/ 69569:
|
/***/ 51081:
|
||||||
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
@@ -89115,21 +89450,21 @@ const IFMT = 0b1111;
|
|||||||
// mask to unset low 4 bits
|
// mask to unset low 4 bits
|
||||||
const IFMT_UNKNOWN = ~IFMT;
|
const IFMT_UNKNOWN = ~IFMT;
|
||||||
// set after successfully calling readdir() and getting entries.
|
// set after successfully calling readdir() and getting entries.
|
||||||
const READDIR_CALLED = 16;
|
const READDIR_CALLED = 0b0000_0001_0000;
|
||||||
// set after a successful lstat()
|
// set after a successful lstat()
|
||||||
const LSTAT_CALLED = 32;
|
const LSTAT_CALLED = 0b0000_0010_0000;
|
||||||
// set if an entry (or one of its parents) is definitely not a dir
|
// set if an entry (or one of its parents) is definitely not a dir
|
||||||
const ENOTDIR = 64;
|
const ENOTDIR = 0b0000_0100_0000;
|
||||||
// set if an entry (or one of its parents) does not exist
|
// set if an entry (or one of its parents) does not exist
|
||||||
// (can also be set on lstat errors like EACCES or ENAMETOOLONG)
|
// (can also be set on lstat errors like EACCES or ENAMETOOLONG)
|
||||||
const ENOENT = 128;
|
const ENOENT = 0b0000_1000_0000;
|
||||||
// cannot have child entries -- also verify &IFMT is either IFDIR or IFLNK
|
// cannot have child entries -- also verify &IFMT is either IFDIR or IFLNK
|
||||||
// set if we fail to readlink
|
// set if we fail to readlink
|
||||||
const ENOREADLINK = 256;
|
const ENOREADLINK = 0b0001_0000_0000;
|
||||||
// set if we know realpath() will fail
|
// set if we know realpath() will fail
|
||||||
const ENOREALPATH = 512;
|
const ENOREALPATH = 0b0010_0000_0000;
|
||||||
const ENOCHILD = ENOTDIR | ENOENT | ENOREALPATH;
|
const ENOCHILD = ENOTDIR | ENOENT | ENOREALPATH;
|
||||||
const TYPEMASK = 1023;
|
const TYPEMASK = 0b0011_1111_1111;
|
||||||
const entToType = (s) => s.isFile()
|
const entToType = (s) => s.isFile()
|
||||||
? IFREG
|
? IFREG
|
||||||
: s.isDirectory()
|
: s.isDirectory()
|
||||||
@@ -89743,7 +90078,7 @@ class PathBase {
|
|||||||
/* c8 ignore stop */
|
/* c8 ignore stop */
|
||||||
try {
|
try {
|
||||||
const read = await this.#fs.promises.readlink(this.fullpath());
|
const read = await this.#fs.promises.readlink(this.fullpath());
|
||||||
const linkTarget = this.parent.resolve(read);
|
const linkTarget = (await this.parent.realpath())?.resolve(read);
|
||||||
if (linkTarget) {
|
if (linkTarget) {
|
||||||
return (this.#linkTarget = linkTarget);
|
return (this.#linkTarget = linkTarget);
|
||||||
}
|
}
|
||||||
@@ -89772,7 +90107,7 @@ class PathBase {
|
|||||||
/* c8 ignore stop */
|
/* c8 ignore stop */
|
||||||
try {
|
try {
|
||||||
const read = this.#fs.readlinkSync(this.fullpath());
|
const read = this.#fs.readlinkSync(this.fullpath());
|
||||||
const linkTarget = this.parent.resolve(read);
|
const linkTarget = (this.parent.realpathSync())?.resolve(read);
|
||||||
if (linkTarget) {
|
if (linkTarget) {
|
||||||
return (this.#linkTarget = linkTarget);
|
return (this.#linkTarget = linkTarget);
|
||||||
}
|
}
|
||||||
@@ -89787,7 +90122,9 @@ class PathBase {
|
|||||||
this.#type |= READDIR_CALLED;
|
this.#type |= READDIR_CALLED;
|
||||||
// mark all remaining provisional children as ENOENT
|
// mark all remaining provisional children as ENOENT
|
||||||
for (let p = children.provisional; p < children.length; p++) {
|
for (let p = children.provisional; p < children.length; p++) {
|
||||||
children[p].#markENOENT();
|
const c = children[p];
|
||||||
|
if (c)
|
||||||
|
c.#markENOENT();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#markENOENT() {
|
#markENOENT() {
|
||||||
@@ -93860,7 +94197,7 @@ exports.parse = parse;
|
|||||||
/***/ ((module) => {
|
/***/ ((module) => {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
module.exports = {"i8":"2.3.0"};
|
module.exports = {"i8":"2.3.1"};
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
@@ -93940,7 +94277,7 @@ module.exports = JSON.parse('[["0","\\u0000",128],["a1","。",62],["8140","
|
|||||||
/***/ ((module) => {
|
/***/ ((module) => {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
module.exports = JSON.parse('{"name":"make-fetch-happen","version":"13.0.0","description":"Opinionated, caching, retrying fetch client","main":"lib/index.js","files":["bin/","lib/"],"scripts":{"test":"tap","posttest":"npm run lint","eslint":"eslint","lint":"eslint \\"**/*.js\\"","lintfix":"npm run lint -- --fix","postlint":"template-oss-check","snap":"tap","template-oss-apply":"template-oss-apply --force"},"repository":{"type":"git","url":"https://github.com/npm/make-fetch-happen.git"},"keywords":["http","request","fetch","mean girls","caching","cache","subresource integrity"],"author":"GitHub Inc.","license":"ISC","dependencies":{"@npmcli/agent":"^2.0.0","cacache":"^18.0.0","http-cache-semantics":"^4.1.1","is-lambda":"^1.0.1","minipass":"^7.0.2","minipass-fetch":"^3.0.0","minipass-flush":"^1.0.5","minipass-pipeline":"^1.2.4","negotiator":"^0.6.3","promise-retry":"^2.0.1","ssri":"^10.0.0"},"devDependencies":{"@npmcli/eslint-config":"^4.0.0","@npmcli/template-oss":"4.18.0","nock":"^13.2.4","safe-buffer":"^5.2.1","standard-version":"^9.3.2","tap":"^16.0.0"},"engines":{"node":"^16.14.0 || >=18.0.0"},"tap":{"color":1,"files":"test/*.js","check-coverage":true,"timeout":60,"nyc-arg":["--exclude","tap-snapshots/**"]},"templateOSS":{"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten.","ciVersions":["16.14.0","16.x","18.0.0","18.x"],"version":"4.18.0","publish":"true"}}');
|
module.exports = JSON.parse('{"name":"make-fetch-happen","version":"13.0.1","description":"Opinionated, caching, retrying fetch client","main":"lib/index.js","files":["bin/","lib/"],"scripts":{"test":"tap","posttest":"npm run lint","eslint":"eslint","lint":"eslint \\"**/*.{js,cjs,ts,mjs,jsx,tsx}\\"","lintfix":"npm run lint -- --fix","postlint":"template-oss-check","snap":"tap","template-oss-apply":"template-oss-apply --force"},"repository":{"type":"git","url":"https://github.com/npm/make-fetch-happen.git"},"keywords":["http","request","fetch","mean girls","caching","cache","subresource integrity"],"author":"GitHub Inc.","license":"ISC","dependencies":{"@npmcli/agent":"^2.0.0","cacache":"^18.0.0","http-cache-semantics":"^4.1.1","is-lambda":"^1.0.1","minipass":"^7.0.2","minipass-fetch":"^3.0.0","minipass-flush":"^1.0.5","minipass-pipeline":"^1.2.4","negotiator":"^0.6.3","proc-log":"^4.2.0","promise-retry":"^2.0.1","ssri":"^10.0.0"},"devDependencies":{"@npmcli/eslint-config":"^4.0.0","@npmcli/template-oss":"4.21.4","nock":"^13.2.4","safe-buffer":"^5.2.1","standard-version":"^9.3.2","tap":"^16.0.0"},"engines":{"node":"^16.14.0 || >=18.0.0"},"tap":{"color":1,"files":"test/*.js","check-coverage":true,"timeout":60,"nyc-arg":["--exclude","tap-snapshots/**"]},"templateOSS":{"//@npmcli/template-oss":"This file is partially managed by @npmcli/template-oss. Edits may be overwritten.","version":"4.21.4","publish":"true"}}');
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
||||||
|
|||||||
19
dist/licenses.txt
generated
vendored
19
dist/licenses.txt
generated
vendored
@@ -2887,6 +2887,25 @@ will be liable to anyone for any damages related to this
|
|||||||
software or this license, under any kind of legal claim.***
|
software or this license, under any kind of legal claim.***
|
||||||
|
|
||||||
|
|
||||||
|
proc-log
|
||||||
|
ISC
|
||||||
|
The ISC License
|
||||||
|
|
||||||
|
Copyright (c) GitHub, Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||||
|
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
promise-retry
|
promise-retry
|
||||||
MIT
|
MIT
|
||||||
Copyright (c) 2014 IndigoUnited
|
Copyright (c) 2014 IndigoUnited
|
||||||
|
|||||||
727
package-lock.json
generated
727
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "actions/attest",
|
"name": "actions/attest",
|
||||||
"description": "Generate signed attestations for workflow artifacts",
|
"description": "Generate signed attestations for workflow artifacts",
|
||||||
"version": "1.1.0",
|
"version": "1.1.2",
|
||||||
"author": "",
|
"author": "",
|
||||||
"private": true,
|
"private": true,
|
||||||
"homepage": "https://github.com/actions/attest",
|
"homepage": "https://github.com/actions/attest",
|
||||||
@@ -72,25 +72,25 @@
|
|||||||
"@actions/attest": "^1.2.1",
|
"@actions/attest": "^1.2.1",
|
||||||
"@actions/core": "^1.10.1",
|
"@actions/core": "^1.10.1",
|
||||||
"@actions/glob": "^0.4.0",
|
"@actions/glob": "^0.4.0",
|
||||||
"@sigstore/oci": "^0.3.0",
|
"@sigstore/oci": "^0.3.3",
|
||||||
"csv-parse": "^5.5.5"
|
"csv-parse": "^5.5.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sigstore/mock": "^0.7.2",
|
"@sigstore/mock": "^0.7.3",
|
||||||
"@types/jest": "^29.5.12",
|
"@types/jest": "^29.5.12",
|
||||||
"@types/make-fetch-happen": "^10.0.4",
|
"@types/make-fetch-happen": "^10.0.4",
|
||||||
"@types/node": "^20.12.7",
|
"@types/node": "^20.12.11",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.8.0",
|
"@typescript-eslint/eslint-plugin": "^7.9.0",
|
||||||
"@typescript-eslint/parser": "^7.8.0",
|
"@typescript-eslint/parser": "^7.9.0",
|
||||||
"@vercel/ncc": "^0.38.1",
|
"@vercel/ncc": "^0.38.1",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-plugin-github": "^4.10.2",
|
"eslint-plugin-github": "^4.10.2",
|
||||||
"eslint-plugin-jest": "^28.3.0",
|
"eslint-plugin-jest": "^28.5.0",
|
||||||
"eslint-plugin-jsonc": "^2.15.1",
|
"eslint-plugin-jsonc": "^2.15.1",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"markdownlint-cli": "^0.39.0",
|
"markdownlint-cli": "^0.40.0",
|
||||||
"nock": "^13.5.4",
|
"nock": "^13.5.4",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"prettier-eslint": "^16.3.0",
|
"prettier-eslint": "^16.3.0",
|
||||||
|
|||||||
31
src/main.ts
31
src/main.ts
@@ -13,16 +13,30 @@ type SigstoreInstance = 'public-good' | 'github'
|
|||||||
type AttestedSubject = { subject: Subject; attestationID: string }
|
type AttestedSubject = { subject: Subject; attestationID: string }
|
||||||
|
|
||||||
const COLOR_CYAN = '\x1B[36m'
|
const COLOR_CYAN = '\x1B[36m'
|
||||||
|
const COLOR_GRAY = '\x1B[38;5;244m'
|
||||||
const COLOR_DEFAULT = '\x1B[39m'
|
const COLOR_DEFAULT = '\x1B[39m'
|
||||||
const ATTESTATION_FILE_NAME = 'attestation.jsonl'
|
const ATTESTATION_FILE_NAME = 'attestation.jsonl'
|
||||||
|
|
||||||
const MAX_SUBJECT_COUNT = 64
|
const MAX_SUBJECT_COUNT = 64
|
||||||
|
|
||||||
|
const OCI_TIMEOUT = 2000
|
||||||
|
const OCI_RETRY = 3
|
||||||
|
|
||||||
|
/* istanbul ignore next */
|
||||||
|
const logHandler = (level: string, ...args: unknown[]): void => {
|
||||||
|
// Send any HTTP-related log events to the GitHub Actions debug log
|
||||||
|
if (level === 'http') {
|
||||||
|
core.debug(args.join(' '))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main function for the action.
|
* The main function for the action.
|
||||||
* @returns {Promise<void>} Resolves when the action is complete.
|
* @returns {Promise<void>} Resolves when the action is complete.
|
||||||
*/
|
*/
|
||||||
export async function run(): Promise<void> {
|
export async function run(): Promise<void> {
|
||||||
|
process.on('log', logHandler)
|
||||||
|
|
||||||
// Provenance visibility will be public ONLY if we can confirm that the
|
// Provenance visibility will be public ONLY if we can confirm that the
|
||||||
// repository is public AND the undocumented "private-signing" arg is NOT set.
|
// repository is public AND the undocumented "private-signing" arg is NOT set.
|
||||||
// Otherwise, it will be private.
|
// Otherwise, it will be private.
|
||||||
@@ -86,14 +100,19 @@ export async function run(): Promise<void> {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Fail the workflow run if an error occurs
|
// Fail the workflow run if an error occurs
|
||||||
core.setFailed(
|
core.setFailed(
|
||||||
err instanceof Error ? err.message : /* istanbul ignore next */ `${err}`
|
err instanceof Error ? err : /* istanbul ignore next */ `${err}`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Log the cause of the error if one is available
|
||||||
/* istanbul ignore if */
|
/* istanbul ignore if */
|
||||||
if (err instanceof Error && 'cause' in err) {
|
if (err instanceof Error && 'cause' in err) {
|
||||||
const innerErr = err.cause
|
const innerErr = err.cause
|
||||||
core.debug(innerErr instanceof Error ? innerErr.message : `${innerErr}}`)
|
core.info(
|
||||||
|
mute(innerErr instanceof Error ? innerErr.toString() : `${innerErr}`)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
process.removeListener('log', logHandler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +166,8 @@ const createAttestation = async (
|
|||||||
annotations: {
|
annotations: {
|
||||||
'dev.sigstore.bundle.content': 'dsse-envelope',
|
'dev.sigstore.bundle.content': 'dsse-envelope',
|
||||||
'dev.sigstore.bundle.predicateType': core.getInput('predicate-type')
|
'dev.sigstore.bundle.predicateType': core.getInput('predicate-type')
|
||||||
}
|
},
|
||||||
|
fetchOpts: { timeout: OCI_TIMEOUT, retry: OCI_RETRY }
|
||||||
})
|
})
|
||||||
core.info(highlight('Attestation uploaded to registry'))
|
core.info(highlight('Attestation uploaded to registry'))
|
||||||
core.info(`${subject.name}@${artifact.digest}`)
|
core.info(`${subject.name}@${artifact.digest}`)
|
||||||
@@ -156,8 +176,13 @@ const createAttestation = async (
|
|||||||
return attestation
|
return attestation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emphasis string using ANSI color codes
|
||||||
const highlight = (str: string): string => `${COLOR_CYAN}${str}${COLOR_DEFAULT}`
|
const highlight = (str: string): string => `${COLOR_CYAN}${str}${COLOR_DEFAULT}`
|
||||||
|
|
||||||
|
// De-emphasize string using ANSI color codes
|
||||||
|
/* istanbul ignore next */
|
||||||
|
const mute = (str: string): string => `${COLOR_GRAY}${str}${COLOR_DEFAULT}`
|
||||||
|
|
||||||
const tempDir = (): string => {
|
const tempDir = (): string => {
|
||||||
const basePath = process.env['RUNNER_TEMP']
|
const basePath = process.env['RUNNER_TEMP']
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ export const subjectFromInputs = async (): Promise<Subject[]> => {
|
|||||||
const subjectPath = core.getInput('subject-path', { required: false })
|
const subjectPath = core.getInput('subject-path', { required: false })
|
||||||
const subjectDigest = core.getInput('subject-digest', { required: false })
|
const subjectDigest = core.getInput('subject-digest', { required: false })
|
||||||
const subjectName = core.getInput('subject-name', { required: false })
|
const subjectName = core.getInput('subject-name', { required: false })
|
||||||
|
const pushToRegistry = core.getBooleanInput('push-to-registry', {
|
||||||
|
required: false
|
||||||
|
})
|
||||||
|
|
||||||
if (!subjectPath && !subjectDigest) {
|
if (!subjectPath && !subjectDigest) {
|
||||||
throw new Error('One of subject-path or subject-digest must be provided')
|
throw new Error('One of subject-path or subject-digest must be provided')
|
||||||
@@ -32,10 +35,14 @@ export const subjectFromInputs = async (): Promise<Subject[]> => {
|
|||||||
throw new Error('subject-name must be provided when using subject-digest')
|
throw new Error('subject-name must be provided when using subject-digest')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If push-to-registry is enabled, ensure the subject name is lowercase
|
||||||
|
// to conform to OCI image naming conventions
|
||||||
|
const name = pushToRegistry ? subjectName.toLowerCase() : subjectName
|
||||||
|
|
||||||
if (subjectPath) {
|
if (subjectPath) {
|
||||||
return await getSubjectFromPath(subjectPath, subjectName)
|
return await getSubjectFromPath(subjectPath, name)
|
||||||
} else {
|
} else {
|
||||||
return [getSubjectFromDigest(subjectDigest, subjectName)]
|
return [getSubjectFromDigest(subjectDigest, name)]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user