Skip to content

Commit bdab631

Browse files
feat: expose provenance transparency url (#6428)
* feat(libnpmpublish): expose provenance transparency url * chore: apply transparency url in 409 retry case * chore: update workspaces/libnpmpublish/lib/publish.js Co-authored-by: Gar <[email protected]> --------- Co-authored-by: Gar <[email protected]>
1 parent 3d5bbcc commit bdab631

File tree

2 files changed

+34
-6
lines changed

2 files changed

+34
-6
lines changed

workspaces/libnpmpublish/lib/publish.js

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,25 @@ Remove the 'private' field from the package.json to publish it.`),
4242
)
4343
}
4444

45-
const metadata = await buildMetadata(reg, pubManifest, tarballData, spec, opts)
45+
const { metadata, transparencyLogUrl } = await buildMetadata(
46+
reg,
47+
pubManifest,
48+
tarballData,
49+
spec,
50+
opts
51+
)
4652

4753
try {
48-
return await npmFetch(spec.escapedName, {
54+
const res = await npmFetch(spec.escapedName, {
4955
...opts,
5056
method: 'PUT',
5157
body: metadata,
5258
ignoreBody: true,
5359
})
60+
if (transparencyLogUrl) {
61+
res.transparencyLogUrl = transparencyLogUrl
62+
}
63+
return res
5464
} catch (err) {
5565
if (err.code !== 'E409') {
5666
throw err
@@ -64,12 +74,17 @@ Remove the 'private' field from the package.json to publish it.`),
6474
query: { write: true },
6575
})
6676
const newMetadata = patchMetadata(current, metadata)
67-
return npmFetch(spec.escapedName, {
77+
const res = await npmFetch(spec.escapedName, {
6878
...opts,
6979
method: 'PUT',
7080
body: newMetadata,
7181
ignoreBody: true,
7282
})
83+
/* istanbul ignore next */
84+
if (transparencyLogUrl) {
85+
res.transparencyLogUrl = transparencyLogUrl
86+
}
87+
return res
7388
}
7489
}
7590

@@ -138,6 +153,7 @@ const buildMetadata = async (registry, manifest, tarballData, spec, opts) => {
138153
}
139154

140155
// Handle case where --provenance flag was set to true
156+
let transparencyLogUrl
141157
if (provenance === true) {
142158
const subject = {
143159
name: npa.toPurl(spec),
@@ -178,8 +194,11 @@ const buildMetadata = async (registry, manifest, tarballData, spec, opts) => {
178194
const tlogEntry = provenanceBundle?.verificationMaterial?.tlogEntries[0]
179195
/* istanbul ignore else */
180196
if (tlogEntry) {
181-
const logUrl = `${TLOG_BASE_URL}?logIndex=${tlogEntry.logIndex}`
182-
log.notice('publish', `Provenance statement published to transparency log: ${logUrl}`)
197+
transparencyLogUrl = `${TLOG_BASE_URL}?logIndex=${tlogEntry.logIndex}`
198+
log.notice(
199+
'publish',
200+
`Provenance statement published to transparency log: ${transparencyLogUrl}`
201+
)
183202
}
184203

185204
const serializedBundle = JSON.stringify(provenanceBundle)
@@ -190,7 +209,10 @@ const buildMetadata = async (registry, manifest, tarballData, spec, opts) => {
190209
}
191210
}
192211

193-
return root
212+
return {
213+
metadata: root,
214+
transparencyLogUrl,
215+
}
194216
}
195217

196218
const patchMetadata = (current, newData) => {

workspaces/libnpmpublish/test/publish.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,7 @@ t.test('publish includes access', async t => {
511511
})
512512

513513
t.ok(ret, 'publish succeeded')
514+
t.notOk(ret.transparencyLogUrl, 'no transparencyLogUrl for non-provenance publish')
514515
})
515516

516517
t.test('refuse if package is unscoped plus `restricted` access', async t => {
@@ -804,6 +805,11 @@ t.test('publish existing package with provenance in gha', async t => {
804805
rekorURL: rekorURL,
805806
})
806807
t.ok(ret, 'publish succeeded')
808+
t.equal(
809+
ret.transparencyLogUrl,
810+
'https://search.sigstore.dev/?logIndex=2513258',
811+
'has appropriate transparencyLogUrl property'
812+
)
807813
t.match(log, [
808814
['notice', 'publish',
809815
'Signed provenance statement with source and build information from GitHub Actions'],

0 commit comments

Comments
 (0)