Skip to content

Commit aaa9d32

Browse files
authored
fix: decouple npm provenance from OIDC trusted publishing (#1050)
1 parent 37d3047 commit aaa9d32

6 files changed

Lines changed: 72 additions & 5 deletions

File tree

packages/shipjs-lib/src/lib/config/defaultConfig.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ _This pull request is automatically generated by [Ship.js](https://github.com/al
109109
beforePublish: undefined, // ({ exec, dir }) => {}
110110
publishCommand: ({ isYarn, tag, defaultCommand, dir }) => defaultCommand,
111111
useOidcTokenProvider: false,
112+
generateProvenance: false,
112113
afterPublish: undefined, // ({ exec, dir, version, releaseTag }) => {}
113114
getTagName: ({ version }) => `v${version}`,
114115
testCommandBeforeRelease: undefined, // ({ isYarn }) => isYarn ? 'yarn test' : 'npm run test',

packages/shipjs/src/helper/getPublishCommand.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ export default function getPublishCommand({
33
publishCommand,
44
tag,
55
dir,
6-
useOidcTokenProvider,
6+
generateProvenance,
77
}) {
8-
const provenance = useOidcTokenProvider ? ' --provenance' : '';
8+
const provenance = generateProvenance ? ' --provenance' : '';
99
const npmPublish = `npm publish --tag ${tag}${provenance}`;
1010
const setRegistry = 'npm_config_registry=https://registry.npmjs.org/';
1111
const defaultCommand = isYarn ? `${setRegistry} ${npmPublish}` : npmPublish;

packages/shipjs/src/step/release/__tests__/runPublish.spec.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,34 @@ describe('runPublish', () => {
8181
expect(run.mock.calls[0][0].command).not.toContain('npm config set');
8282
});
8383

84+
it('adds --provenance when generateProvenance is true', () => {
85+
runPublish({
86+
isYarn: true,
87+
config: {
88+
publishCommand: ({ defaultCommand }) => defaultCommand,
89+
generateProvenance: true,
90+
},
91+
releaseTag: 'latest',
92+
dir: '.',
93+
dryRun: false,
94+
});
95+
expect(run.mock.calls[1][0].command).toContain('--provenance');
96+
});
97+
98+
it('does not add --provenance when only useOidcTokenProvider is true', () => {
99+
runPublish({
100+
isYarn: true,
101+
config: {
102+
publishCommand: ({ defaultCommand }) => defaultCommand,
103+
useOidcTokenProvider: true,
104+
},
105+
releaseTag: 'latest',
106+
dir: '.',
107+
dryRun: false,
108+
});
109+
expect(run.mock.calls[0][0].command).not.toContain('--provenance');
110+
});
111+
84112
it('works with monorepo', () => {
85113
const output = [];
86114
mockPrint(print, output);

packages/shipjs/src/step/release/runPublish.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ import runStep from '../runStep.js';
77

88
export default ({ isYarn, config, releaseTag: tag, dir, dryRun }) =>
99
runStep({ title: 'Publishing.' }, () => {
10-
const { publishCommand, monorepo, useOidcTokenProvider } = config;
10+
const {
11+
publishCommand,
12+
monorepo,
13+
useOidcTokenProvider,
14+
generateProvenance,
15+
} = config;
1116

1217
// This adds the following line to ~/.npmrc
1318
// > registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}
@@ -29,7 +34,7 @@ export default ({ isYarn, config, releaseTag: tag, dir, dryRun }) =>
2934
publishCommand,
3035
tag,
3136
dir: packageDir,
32-
useOidcTokenProvider,
37+
generateProvenance,
3338
});
3439
if (command) {
3540
print(`Running the following at ${info(packageDir)}`);
@@ -44,7 +49,7 @@ export default ({ isYarn, config, releaseTag: tag, dir, dryRun }) =>
4449
publishCommand,
4550
tag,
4651
dir,
47-
useOidcTokenProvider,
52+
generateProvenance,
4853
});
4954
run({ command, dir, dryRun });
5055
}

website/guide/getting-started.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ permissions:
164164
165165
Note: OIDC trusted publishing requires npm v11.5.1 or later.
166166
167+
To attach a [provenance statement](https://docs.npmjs.com/generating-provenance-statements) to your package, set [`generateProvenance`](/reference/all-config.html#generateprovenance) to `true` (off by default). It requires the same `id-token: write` permission and only works for public repositories. This is independent from `useOidcTokenProvider`: you can generate provenance whether you authenticate with a classic npm token or with OIDC trusted publishing.
168+
167169
## Setup with 'Nothing'
168170
169171
If you never use any CI environment, you need to use NPM token to release package to NPM:

website/reference/all-config.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,37 @@ permissions:
332332
OIDC trusted publishing requires npm v11.5.1 or later.
333333
:::
334334
335+
This option only controls authentication. To attach a provenance attestation to your published package, use [`generateProvenance`](#generateprovenance).
336+
337+
## `generateProvenance`
338+
339+
_used at_: `shipjs trigger`
340+
341+
_default:_ `false`
342+
343+
When `true`, Ship.js adds `--provenance` to `npm publish` so npm generates a [provenance statement](https://docs.npmjs.com/generating-provenance-statements) linking the published package to the CI workflow that built it.
344+
345+
```js
346+
// ship.config.js
347+
module.exports = {
348+
generateProvenance: true,
349+
};
350+
```
351+
352+
This is independent from [`useOidcTokenProvider`](#useoidctokenprovider): provenance works whether you authenticate with a classic npm token or with OIDC trusted publishing.
353+
354+
Provenance signing relies on the CI's OIDC token, so your GitHub Actions workflow job needs the `id-token: write` permission:
355+
356+
```yaml
357+
permissions:
358+
id-token: write
359+
contents: read
360+
```
361+
362+
::: warning Public repositories only
363+
npm rejects provenance for packages built from private or internal repositories. Enabling this on a private/internal repo will make the publish step fail.
364+
:::
365+
335366
## `afterPublish`
336367
337368
_used at_: `shipjs trigger`

0 commit comments

Comments
 (0)