Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/yummy-hairs-enjoy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"changesets-gitlab": minor
---

Add support for Trusted Publishers
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,12 @@ release:

#### With Publishing

Before you can setup this action with publishing, you'll need to have an [npm token](https://docs.npmjs.com/creating-and-viewing-authentication-tokens) that can publish the packages in the repo you're setting up the action for and doesn't have 2FA on publish enabled ([2FA on auth can be enabled](https://docs.npmjs.com/about-two-factor-authentication)). You'll also need to [add it as a custom environment variable on your GitLab repo](https://docs.gitlab.com/ee/ci/variables/#custom-cicd-variables) with the name `NPM_TOKEN`. Once you've done that, you can create a file at `.gitlab-ci.yml` with the following content.
There are two ways to authenticate with npm when publishing:

1. Trusted Publishers (recommended): Configure npm Trusted Publishers for your GitLab pipeline (see the npm docs: <https://docs.npmjs.com/trusted-publishers#supported-cicd-providers>). When the pipeline runs, npm will inject an `NPM_ID_TOKEN`, which this tool detects. In this mode you do NOT need to set `NPM_TOKEN`, and no `.npmrc` file is required—the npm CLI exchanges the identity token automatically.
2. Classic Automation Token: Create an [npm automation token](https://docs.npmjs.com/creating-and-viewing-authentication-tokens) (without 2FA on publish) and add it as a [custom environment variable in GitLab](https://docs.gitlab.com/ee/ci/variables/#custom-cicd-variables) named `NPM_TOKEN`.

For any of the methods, create a file at `.gitlab-ci.yml` with the following content:

```yml
stages:
Expand All @@ -114,13 +119,14 @@ release:
INPUT_PUBLISH: yarn release
```

By default the GitLab CI cli creates a `.npmrc` file with the following content:
By default the GitLab CI cli creates a `.npmrc` file with the following content when `NPM_TOKEN` is present and no `.npmrc` exists (classic token mode):

```sh
//registry.npmjs.org/:_authToken=${process.env.NPM_TOKEN}
```

However, if a `.npmrc` file is found, the GitLab CI cli does not recreate the file. This is useful if you need to configure the `.npmrc` file on your own.
If `NPM_ID_TOKEN` is detected (Trusted Publishers), no `.npmrc` file is created or required.
For example, you can add a step before running the Changesets GitLab CI cli:

```yml
Expand Down
11 changes: 8 additions & 3 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
export const main = async ({
published,
onlyChangesets,
}: MainCommandOptions = {}) => {

Check failure on line 24 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint and Test with Node.js 22

Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed

Check failure on line 24 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint and Test with Node.js 18

Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed

Check failure on line 24 in src/main.ts

View workflow job for this annotation

GitHub Actions / Lint and Test with Node.js 20

Refactor this function to reduce its Cognitive Complexity from 16 to the 15 allowed
const { GITLAB_TOKEN, NPM_TOKEN } = env
const { GITLAB_TOKEN, NPM_TOKEN, NPM_ID_TOKEN } = env

setOutput('published', false)
setOutput('publishedPackages', [])
Expand Down Expand Up @@ -69,15 +69,20 @@
const npmrcPath = `${env.HOME}/.npmrc`
if (fs.existsSync(npmrcPath)) {
console.log('Found existing .npmrc file')
} else if (NPM_ID_TOKEN) {
// Using npm Trusted Publishers: npm will exchange the OIDC token for a publish token internally.
console.log(
'Detected `NPM_ID_TOKEN`; skipping `.npmrc` creation (Trusted Publishers mode).',
)
} else if (NPM_TOKEN) {
console.log('No .npmrc file found, creating one')
console.log('No .npmrc file found, creating one with `NPM_TOKEN`')
await fs.promises.writeFile(
npmrcPath,
`//registry.npmjs.org/:_authToken=${NPM_TOKEN}`,
)
} else {
setFailed(
'No `.npmrc` found nor `NPM_TOKEN` provided, unable to publish packages',
'No `.npmrc` found and neither `NPM_TOKEN` nor `NPM_ID_TOKEN` provided, unable to publish packages',
)
return
}
Expand Down
3 changes: 3 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ export type Env = GitLabCIPredefinedVariables &

HOME: string
NPM_TOKEN?: string
// Presence of NPM_ID_TOKEN indicates usage of npm Trusted Publishers;
// when set we don't require nor create an .npmrc with NPM_TOKEN.
NPM_ID_TOKEN?: string
}

type MergeRequestVariables =
Expand Down
Loading