Skip to content

Commit f064696

Browse files
authored
fix: Update publish /w provenance to ignore pkg vis 404 (#6437)
Some registries (e.g. GH packages) require auth to check visibility, and always return 404 when no auth is supplied. In this case we assume the package is always private and require `--access public` to publish. I've also updated this to only perform a visibility check when this is actually needed (i.e. when `provenance` is true and `access` is not `public`). Fixes #6436
1 parent bdab631 commit f064696

2 files changed

Lines changed: 91 additions & 3 deletions

File tree

workspaces/libnpmpublish/lib/publish.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,23 @@ const buildMetadata = async (registry, manifest, tarballData, spec, opts) => {
177177
)
178178
}
179179

180-
const visibility =
181-
await npmFetch.json(`${registry}/-/package/${spec.escapedName}/visibility`, opts)
180+
// Some registries (e.g. GH packages) require auth to check visibility,
181+
// and always return 404 when no auth is supplied. In this case we assume
182+
// the package is always private and require `--access public` to publish
183+
// with provenance.
184+
let visibility = { public: false }
185+
if (opts.provenance === true && opts.access !== 'public') {
186+
try {
187+
const res = await npmFetch
188+
.json(`${registry}/-/package/${spec.escapedName}/visibility`, opts)
189+
visibility = res
190+
} catch (err) {
191+
if (err.code !== 'E404') {
192+
throw err
193+
}
194+
}
195+
}
196+
182197
if (!visibility.public && opts.provenance === true && opts.access !== 'public') {
183198
throw Object.assign(
184199
/* eslint-disable-next-line max-len */

workspaces/libnpmpublish/test/publish.js

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,6 @@ t.test('publish existing package with provenance in gha', async t => {
776776
.post('/api/v1/log/entries')
777777
.reply(201, rekorEntry)
778778

779-
registry.getVisibility({ spec, visibility: { public: true } })
780779
registry.nock.put(`/${spec.escapedName}`, body => {
781780
const bundleAttachment = body._attachments['@npmcli/libnpmpublish-test-1.0.0.sigstore']
782781
const bundle = JSON.parse(bundleAttachment.data)
@@ -855,6 +854,80 @@ t.test('publish new/private package with provenance in gha - no access', async t
855854
)
856855
})
857856

857+
t.test('publish new package with provenance in gha when visibility 404s - no access', async t => {
858+
const oidcURL = 'https://mock.oidc'
859+
const requestToken = 'decafbad'
860+
mockGlobals(t, {
861+
'process.env': {
862+
CI: true,
863+
GITHUB_ACTIONS: true,
864+
ACTIONS_ID_TOKEN_REQUEST_URL: oidcURL,
865+
ACTIONS_ID_TOKEN_REQUEST_TOKEN: requestToken,
866+
},
867+
})
868+
const { publish } = t.mock('..', { 'ci-info': t.mock('ci-info') })
869+
const registry = new MockRegistry({
870+
tap: t,
871+
registry: opts.registry,
872+
authorization: token,
873+
strict: true,
874+
})
875+
const manifest = {
876+
name: '@npmcli/libnpmpublish-test',
877+
version: '1.0.0',
878+
description: 'test libnpmpublish package',
879+
}
880+
const spec = npa(manifest.name)
881+
registry.nock.get(`/-/package/${npa(spec).escapedName}/visibility`)
882+
.reply(404)
883+
884+
await t.rejects(
885+
publish(manifest, Buffer.from(''), {
886+
...opts,
887+
access: null,
888+
provenance: true,
889+
}),
890+
{ code: 'EUSAGE' }
891+
)
892+
})
893+
894+
t.test('publish new package with provenance in gha when visibility 500s - no access', async t => {
895+
const oidcURL = 'https://mock.oidc'
896+
const requestToken = 'decafbad'
897+
mockGlobals(t, {
898+
'process.env': {
899+
CI: true,
900+
GITHUB_ACTIONS: true,
901+
ACTIONS_ID_TOKEN_REQUEST_URL: oidcURL,
902+
ACTIONS_ID_TOKEN_REQUEST_TOKEN: requestToken,
903+
},
904+
})
905+
const { publish } = t.mock('..', { 'ci-info': t.mock('ci-info') })
906+
const registry = new MockRegistry({
907+
tap: t,
908+
registry: opts.registry,
909+
authorization: token,
910+
strict: true,
911+
})
912+
const manifest = {
913+
name: '@npmcli/libnpmpublish-test',
914+
version: '1.0.0',
915+
description: 'test libnpmpublish package',
916+
}
917+
const spec = npa(manifest.name)
918+
registry.nock.get(`/-/package/${npa(spec).escapedName}/visibility`)
919+
.reply(500)
920+
921+
await t.rejects(
922+
publish(manifest, Buffer.from(''), {
923+
...opts,
924+
access: null,
925+
provenance: true,
926+
}),
927+
{ code: 'E500' }
928+
)
929+
})
930+
858931
t.test('automatic provenance in unsupported environment', async t => {
859932
mockGlobals(t, {
860933
'process.env': {

0 commit comments

Comments
 (0)