diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 652e3b6..3ecabca 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -207,6 +207,112 @@ describe('run', () => { expect(setFailedMock).toHaveBeenCalledWith('Something went wrong') }) + it('fails if creating attestation fails', async () => { + resolvePublishActionOptionsMock.mockReturnValue(baseOptions()) + + ensureCorrectShaCheckedOutMock.mockImplementation(() => {}) + + createTempDirMock.mockImplementation(() => { + return 'stagingOrArchivesDir' + }) + + stageActionFilesMock.mockImplementation(() => {}) + + calculateManifestDigestMock.mockImplementation(() => { + return 'sha256:my-test-digest' + }) + + createArchivesMock.mockImplementation(() => { + return { + zipFile: { + path: 'test', + size: 5, + sha256: '123' + }, + tarFile: { + path: 'test2', + size: 52, + sha256: '1234' + } + } + }) + + publishOCIArtifactMock.mockImplementation(() => { + return { + packageURL: 'https://ghcr.io/v2/test-org/test-repo:1.2.3', + publishedDigest: 'sha256:my-test-digest' + } + }) + + generateAttestationMock.mockImplementation(async () => { + throw new Error('Something went wrong') + }) + + // Run the action + await main.run() + + // Check the results + expect(setFailedMock).toHaveBeenCalledWith('Something went wrong') + }) + + it('fails if uploading attestation to GHCR fails', async () => { + resolvePublishActionOptionsMock.mockReturnValue(baseOptions()) + + ensureCorrectShaCheckedOutMock.mockImplementation(() => {}) + + createTempDirMock.mockImplementation(() => { + return 'stagingOrArchivesDir' + }) + + stageActionFilesMock.mockImplementation(() => {}) + + createArchivesMock.mockImplementation(() => { + return { + zipFile: { + path: 'test', + size: 5, + sha256: '123' + }, + tarFile: { + path: 'test2', + size: 52, + sha256: '1234' + } + } + }) + + calculateManifestDigestMock.mockImplementation(() => { + return 'sha256:my-test-digest' + }) + + generateAttestationMock.mockImplementation(async options => { + expect(options).toHaveProperty('skipWrite', true) + + return { + attestationID: 'test-attestation-id', + certificate: 'test', + bundle: { + mediaType: 'application/vnd.cncf.notary.v2+jwt', + verificationMaterial: { + publicKey: { + hint: 'test-hint' + } + } + } + } + }) + + attachArtifactToImageMock.mockImplementation(() => { + throw new Error('Something went wrong') + }) + + // Run the action + await main.run() + + // Check the results + expect(setFailedMock).toHaveBeenCalledWith('Something went wrong') + }) + it('fails if publishing OCI artifact fails', async () => { resolvePublishActionOptionsMock.mockReturnValue(baseOptions()) @@ -254,6 +360,15 @@ describe('run', () => { } }) + attachArtifactToImageMock.mockImplementation(() => { + return { + digest: 'sha256:my-test-attestation-digest', + urls: [ + 'ghcr.io/v2/test-org/test-package/manifests/sha256:my-test-attestation-digest' + ] + } + }) + publishOCIArtifactMock.mockImplementation(() => { throw new Error('Something went wrong') }) @@ -312,6 +427,15 @@ describe('run', () => { } }) + attachArtifactToImageMock.mockImplementation(() => { + return { + digest: 'sha256:some-other-digest', + urls: [ + 'ghcr.io/v2/test-org/test-package/manifests/sha256:some-other-digest' + ] + } + }) + publishOCIArtifactMock.mockImplementation(() => { return { packageURL: 'https://ghcr.io/v2/test-org/test-repo:1.2.3', @@ -328,119 +452,6 @@ describe('run', () => { ) }) - it('fails if uploading attestation to GHCR fails', async () => { - resolvePublishActionOptionsMock.mockReturnValue(baseOptions()) - - ensureCorrectShaCheckedOutMock.mockImplementation(() => {}) - - createTempDirMock.mockImplementation(() => { - return 'stagingOrArchivesDir' - }) - - stageActionFilesMock.mockImplementation(() => {}) - - createArchivesMock.mockImplementation(() => { - return { - zipFile: { - path: 'test', - size: 5, - sha256: '123' - }, - tarFile: { - path: 'test2', - size: 52, - sha256: '1234' - } - } - }) - - calculateManifestDigestMock.mockImplementation(() => { - return 'sha256:my-test-digest' - }) - - publishOCIArtifactMock.mockImplementation(() => { - return { - packageURL: 'https://ghcr.io/v2/test-org/test-repo:1.2.3', - publishedDigest: 'sha256:my-test-digest' - } - }) - - generateAttestationMock.mockImplementation(async options => { - expect(options).toHaveProperty('skipWrite', true) - - return { - attestationID: 'test-attestation-id', - certificate: 'test', - bundle: { - mediaType: 'application/vnd.cncf.notary.v2+jwt', - verificationMaterial: { - publicKey: { - hint: 'test-hint' - } - } - } - } - }) - - attachArtifactToImageMock.mockImplementation(() => { - throw new Error('Something went wrong') - }) - - // Run the action - await main.run() - - // Check the results - expect(setFailedMock).toHaveBeenCalledWith('Something went wrong') - }) - - it('fails if creating attestation fails', async () => { - resolvePublishActionOptionsMock.mockReturnValue(baseOptions()) - - ensureCorrectShaCheckedOutMock.mockImplementation(() => {}) - - createTempDirMock.mockImplementation(() => { - return 'stagingOrArchivesDir' - }) - - stageActionFilesMock.mockImplementation(() => {}) - - calculateManifestDigestMock.mockImplementation(() => { - return 'sha256:my-test-digest' - }) - - createArchivesMock.mockImplementation(() => { - return { - zipFile: { - path: 'test', - size: 5, - sha256: '123' - }, - tarFile: { - path: 'test2', - size: 52, - sha256: '1234' - } - } - }) - - publishOCIArtifactMock.mockImplementation(() => { - return { - packageURL: 'https://ghcr.io/v2/test-org/test-repo:1.2.3', - publishedDigest: 'sha256:my-test-digest' - } - }) - - generateAttestationMock.mockImplementation(async () => { - throw new Error('Something went wrong') - }) - - // Run the action - await main.run() - - // Check the results - expect(setFailedMock).toHaveBeenCalledWith('Something went wrong') - }) - it('uploads the artifact, returns package metadata from GHCR, and skips writing attestation in enterprise', async () => { const options = baseOptions() options.isEnterprise = true @@ -535,13 +546,6 @@ describe('run', () => { return 'sha256:my-test-digest' }) - publishOCIArtifactMock.mockImplementation(() => { - return { - packageURL: 'https://ghcr.io/v2/test-org/test-repo:1.2.3', - publishedDigest: 'sha256:my-test-digest' - } - }) - generateAttestationMock.mockImplementation(async options => { expect(options).toHaveProperty('skipWrite', true) @@ -568,6 +572,13 @@ describe('run', () => { } }) + publishOCIArtifactMock.mockImplementation(() => { + return { + packageURL: 'https://ghcr.io/v2/test-org/test-repo:1.2.3', + publishedDigest: 'sha256:my-test-digest' + } + }) + // Run the action await main.run() diff --git a/dist/index.js b/dist/index.js index 4f139f9..053ad57 100644 --- a/dist/index.js +++ b/dist/index.js @@ -107636,13 +107636,9 @@ async function run() { const archives = await fsHelper.createArchives(stagedActionFilesDir, archiveDir); const manifest = ociContainer.createActionPackageManifest(archives.tarFile, archives.zipFile, options.nameWithOwner, options.repositoryId, options.repositoryOwnerId, options.sha, semverTag.raw, new Date()); const manifestDigest = ociContainer.sha256Digest(manifest); - const { packageURL, publishedDigest } = await ghcr.publishOCIArtifact(options.token, options.containerRegistryUrl, options.nameWithOwner, semverTag.raw, archives.zipFile, archives.tarFile, manifest); - if (manifestDigest !== publishedDigest) { - throw new Error(`Unexpected digest returned for manifest. Expected ${manifestDigest}, got ${publishedDigest}`); - } - // Attestations are not currently supported in GHES. + // Attestations are not supported in GHES. if (!options.isEnterprise) { - const attestation = await uploadAttestation(publishedDigest, semverTag.raw, options); + const attestation = await uploadAttestation(manifestDigest, semverTag.raw, options); if (attestation.digest !== undefined) { core.info(`Uploaded attestation ${attestation.digest}`); core.setOutput('attestation-manifest-sha', attestation.digest); @@ -107652,6 +107648,10 @@ async function run() { core.setOutput('attestation-url', attestation.urls[0]); } } + const { packageURL, publishedDigest } = await ghcr.publishOCIArtifact(options.token, options.containerRegistryUrl, options.nameWithOwner, semverTag.raw, archives.zipFile, archives.tarFile, manifest); + if (manifestDigest !== publishedDigest) { + throw new Error(`Unexpected digest returned for manifest. Expected ${manifestDigest}, got ${publishedDigest}`); + } core.setOutput('package-url', packageURL.toString()); core.setOutput('package-manifest', JSON.stringify(manifest)); core.setOutput('package-manifest-sha', publishedDigest); diff --git a/src/main.ts b/src/main.ts index f8180b2..6905ca8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -53,6 +53,23 @@ export async function run(): Promise { const manifestDigest = ociContainer.sha256Digest(manifest) + // Attestations are not supported in GHES. + if (!options.isEnterprise) { + const attestation = await uploadAttestation( + manifestDigest, + semverTag.raw, + options + ) + if (attestation.digest !== undefined) { + core.info(`Uploaded attestation ${attestation.digest}`) + core.setOutput('attestation-manifest-sha', attestation.digest) + } + if (attestation.urls !== undefined && attestation.urls.length > 0) { + core.info(`Attestation URL: ${attestation.digest}`) + core.setOutput('attestation-url', attestation.urls[0]) + } + } + const { packageURL, publishedDigest } = await ghcr.publishOCIArtifact( options.token, options.containerRegistryUrl, @@ -69,23 +86,6 @@ export async function run(): Promise { ) } - // Attestations are not currently supported in GHES. - if (!options.isEnterprise) { - const attestation = await uploadAttestation( - publishedDigest, - semverTag.raw, - options - ) - if (attestation.digest !== undefined) { - core.info(`Uploaded attestation ${attestation.digest}`) - core.setOutput('attestation-manifest-sha', attestation.digest) - } - if (attestation.urls !== undefined && attestation.urls.length > 0) { - core.info(`Attestation URL: ${attestation.digest}`) - core.setOutput('attestation-url', attestation.urls[0]) - } - } - core.setOutput('package-url', packageURL.toString()) core.setOutput('package-manifest', JSON.stringify(manifest)) core.setOutput('package-manifest-sha', publishedDigest)