diff --git a/__mocks__/@actions/github.js b/__mocks__/@actions/github.js index bf57e5c..2c44ce7 100644 --- a/__mocks__/@actions/github.js +++ b/__mocks__/@actions/github.js @@ -2,7 +2,7 @@ module.exports = { context: { repo: { owner: 'test-owner', repo: 'test-repo' }, runId: 12345, - workflow: 'ci.yml' + serverUrl: 'https://github.com' }, getOctokit: jest.fn() } diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 8d443b1..38bc814 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -77,7 +77,12 @@ describe('SBOM Action', () => { } getInputMock.mockImplementation(mockInput(inputs)) const originalEnv = process.env - process.env = { ...originalEnv, RUNNER_TEMP: '/tmp' } + process.env = { + ...originalEnv, + RUNNER_TEMP: '/tmp', + GITHUB_WORKFLOW_REF: + 'test-owner/test-repo/.github/workflows/ci.yml@refs/heads/main' + } // Run the main function await main.run() @@ -145,7 +150,12 @@ describe('SBOM Action', () => { } getInputMock.mockImplementation(mockInput(inputs)) const originalEnv = process.env - process.env = { ...originalEnv, RUNNER_TEMP: '/tmp' } + process.env = { + ...originalEnv, + RUNNER_TEMP: '/tmp', + GITHUB_WORKFLOW_REF: + 'test-owner/test-repo/.github/workflows/ci.yml@refs/heads/main' + } // Mock release not found mockGetReleaseByTag.mockRejectedValue({ status: 404 }) diff --git a/__tests__/release.test.ts b/__tests__/release.test.ts index 37c34a5..737d528 100644 --- a/__tests__/release.test.ts +++ b/__tests__/release.test.ts @@ -13,17 +13,33 @@ describe('generateAssetName', () => { }) describe('buildAttesterId', () => { - it('builds correct attester ID URL', () => { - const result = buildAttesterId('octocat', 'hello-world', 'ci.yml') + it('builds correct attester ID URL from workflow ref', () => { + const result = buildAttesterId( + 'https://github.com', + 'octocat/hello-world/.github/workflows/ci.yml@refs/heads/main' + ) expect(result).toBe( 'https://github.com/octocat/hello-world/.github/workflows/ci.yml' ) }) - it('handles workflow names with spaces', () => { - const result = buildAttesterId('owner', 'repo', 'Build and Test.yml') + it('handles workflow refs with tags', () => { + const result = buildAttesterId( + 'https://github.com', + 'owner/repo/.github/workflows/release.yml@refs/tags/v1.0.0' + ) expect(result).toBe( - 'https://github.com/owner/repo/.github/workflows/Build and Test.yml' + 'https://github.com/owner/repo/.github/workflows/release.yml' + ) + }) + + it('handles enterprise server URLs', () => { + const result = buildAttesterId( + 'https://github.example.com', + 'owner/repo/.github/workflows/build.yml@refs/heads/main' + ) + expect(result).toBe( + 'https://github.example.com/owner/repo/.github/workflows/build.yml' ) }) }) diff --git a/dist/index.js b/dist/index.js index e79ffb3..5a3da70 100644 --- a/dist/index.js +++ b/dist/index.js @@ -58393,13 +58393,17 @@ async function run() { // Get context for release upload const { owner, repo } = github.context.repo; const runId = github.context.runId; - const workflow = github.context.workflow; + const serverUrl = github.context.serverUrl; + const workflowRef = process.env.GITHUB_WORKFLOW_REF; + if (!workflowRef) { + throw new Error('Missing GITHUB_WORKFLOW_REF environment variable'); + } // Upload SBOM to release core.debug('Uploading SBOM to release'); const octokit = github.getOctokit(token); const { downloadUrl } = await (0, release_1.uploadSBOMToRelease)(octokit, owner, repo, runId, sbomPath); // Generate reference predicate - const attesterId = (0, release_1.buildAttesterId)(owner, repo, workflow); + const attesterId = (0, release_1.buildAttesterId)(serverUrl, workflowRef); const mediaType = (0, reference_1.getMediaType)(sbom.type); const predicate = (0, reference_1.generateReferencePredicate)({ attesterId, @@ -58542,8 +58546,11 @@ function generateAssetName(runId, sbomPath) { const originalName = path_1.default.basename(sbomPath); return `${runId}-${originalName}`; } -function buildAttesterId(owner, repo, workflow) { - return `https://github.com/${owner}/${repo}/.github/workflows/${workflow}`; +function buildAttesterId(serverUrl, workflowRef) { + // workflowRef is in the format: owner/repo/.github/workflows/file.yml@refs/heads/branch + // Extract just the owner/repo/.github/workflows/file.yml part + const workflowPath = workflowRef.split('@')[0]; + return `${serverUrl}/${workflowPath}`; } diff --git a/src/main.ts b/src/main.ts index e272e78..ae0917d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -27,7 +27,12 @@ export async function run(): Promise { // Get context for release upload const { owner, repo } = github.context.repo const runId = github.context.runId - const workflow = github.context.workflow + const serverUrl = github.context.serverUrl + const workflowRef = process.env.GITHUB_WORKFLOW_REF + + if (!workflowRef) { + throw new Error('Missing GITHUB_WORKFLOW_REF environment variable') + } // Upload SBOM to release core.debug('Uploading SBOM to release') @@ -41,7 +46,7 @@ export async function run(): Promise { ) // Generate reference predicate - const attesterId = buildAttesterId(owner, repo, workflow) + const attesterId = buildAttesterId(serverUrl, workflowRef) const mediaType = getMediaType(sbom.type) const predicate = generateReferencePredicate({ attesterId, diff --git a/src/release.ts b/src/release.ts index dee5358..7babc78 100644 --- a/src/release.ts +++ b/src/release.ts @@ -81,9 +81,11 @@ export function generateAssetName(runId: number, sbomPath: string): string { } export function buildAttesterId( - owner: string, - repo: string, - workflow: string + serverUrl: string, + workflowRef: string ): string { - return `https://github.com/${owner}/${repo}/.github/workflows/${workflow}` + // workflowRef is in the format: owner/repo/.github/workflows/file.yml@refs/heads/branch + // Extract just the owner/repo/.github/workflows/file.yml part + const workflowPath = workflowRef.split('@')[0] + return `${serverUrl}/${workflowPath}` }