feat: adds circleci to oidc (#8925) · npm/cli@9a33ad0 · GitHub
Skip to content

Commit 9a33ad0

Browse files
authored
feat: adds circleci to oidc (#8925)
This pull request adds support for CircleCI as a provider of OpenID Connect (OIDC) tokens in CI environments, alongside existing support for GitHub Actions and GitLab. The implementation includes both code changes to detect and handle CircleCI OIDC tokens and new tests to ensure correct behavior. ## Usage In your `.circleci/config.yml`: ```yaml version: 2.1 jobs: publish: docker: - image: cimg/node:lts steps: - checkout - run: name: Publish to npm command: | NPM_AUDIENCE="npm:$(npm config get registry | sed 's|https\?://||;s|/$||')" NPM_ID_TOKEN=$(circleci run oidc get --claims "{\"aud\": \"$NPM_AUDIENCE\"}") npm publish workflows: publish: jobs: - publish ``` Note: Unlike GitHub Actions and GitLab, CircleCI requires manually fetching the OIDC token with the correct audience claim using the `circleci` CLI.
1 parent 07e6edd commit 9a33ad0

3 files changed

Lines changed: 60 additions & 6 deletions

File tree

lib/utils/oidc.js

Lines changed: 8 additions & 4 deletions

test/fixtures/mock-oidc.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ function githubIdToken ({ visibility = 'public' } = { visibility: 'public' }) {
3333
return makeJwt(payload)
3434
}
3535

36+
function circleciIdToken () {
37+
const now = Math.floor(Date.now() / 1000)
38+
const payload = {
39+
'oidc.circleci.com/org-id': 'c9035eb6-6eb2-4c85-8a81-d9ee6a1fa8c2',
40+
'oidc.circleci.com/project-id': 'ecc458d2-fbdc-4d9a-93c4-ac065ed3c3ca',
41+
'oidc.circleci.com/vcs-origin': 'github.com/npm/trust-publish-test',
42+
iat: now,
43+
exp: now + 3600, // 1 hour expiration
44+
}
45+
return makeJwt(payload)
46+
}
47+
3648
const mockOidc = async (t, {
3749
oidcOptions = {},
3850
packageName = '@npmcli/test-package',
@@ -47,6 +59,7 @@ const mockOidc = async (t, {
4759
}) => {
4860
const github = oidcOptions.github ?? false
4961
const gitlab = oidcOptions.gitlab ?? false
62+
const circleci = oidcOptions.circleci ?? false
5063

5164
const ACTIONS_ID_TOKEN_REQUEST_URL = oidcOptions.ACTIONS_ID_TOKEN_REQUEST_URL ?? 'https://github.com/actions/id-token'
5265
const ACTIONS_ID_TOKEN_REQUEST_TOKEN = oidcOptions.ACTIONS_ID_TOKEN_REQUEST_TOKEN ?? 'ACTIONS_ID_TOKEN_REQUEST_TOKEN'
@@ -56,9 +69,10 @@ const mockOidc = async (t, {
5669
env: {
5770
ACTIONS_ID_TOKEN_REQUEST_TOKEN: ACTIONS_ID_TOKEN_REQUEST_TOKEN,
5871
ACTIONS_ID_TOKEN_REQUEST_URL: ACTIONS_ID_TOKEN_REQUEST_URL,
59-
CI: github || gitlab ? 'true' : undefined,
72+
CI: github || gitlab || circleci ? 'true' : undefined,
6073
...(github ? { GITHUB_ACTIONS: 'true' } : {}),
6174
...(gitlab ? { GITLAB_CI: 'true' } : {}),
75+
...(circleci ? { CIRCLECI: 'true' } : {}),
6276
...(oidcOptions.NPM_ID_TOKEN ? { NPM_ID_TOKEN: oidcOptions.NPM_ID_TOKEN } : {}),
6377
/* eslint-disable-next-line max-len */
6478
...(oidcOptions.SIGSTORE_ID_TOKEN ? { SIGSTORE_ID_TOKEN: oidcOptions.SIGSTORE_ID_TOKEN } : {}),
@@ -68,17 +82,23 @@ const mockOidc = async (t, {
6882

6983
const GITHUB_ACTIONS = ciInfo.GITHUB_ACTIONS
7084
const GITLAB = ciInfo.GITLAB
85+
const CIRCLE = ciInfo.CIRCLE
7186
delete ciInfo.GITHUB_ACTIONS
7287
delete ciInfo.GITLAB
88+
delete ciInfo.CIRCLE
7389
if (github) {
7490
ciInfo.GITHUB_ACTIONS = 'true'
7591
}
7692
if (gitlab) {
7793
ciInfo.GITLAB = 'true'
7894
}
95+
if (circleci) {
96+
ciInfo.CIRCLE = 'true'
97+
}
7998
t.teardown(() => {
8099
ciInfo.GITHUB_ACTIONS = GITHUB_ACTIONS
81100
ciInfo.GITLAB = GITLAB
101+
ciInfo.CIRCLE = CIRCLE
82102
})
83103

84104
const { npm, registry, joinedOutput, logs } = await loadNpmWithRegistry(t, {
@@ -156,6 +176,7 @@ const oidcPublishTest = (opts) => {
156176
}
157177

158178
module.exports = {
179+
circleciIdToken,
159180
gitlabIdToken,
160181
githubIdToken,
161182
mockOidc,

test/lib/commands/publish.js

Lines changed: 30 additions & 1 deletion

0 commit comments

Comments
 (0)