GitLab CI cli for changesets, like its GitHub Action, it creates a merge request with all of the package versions and changelogs updated and updates it when there are new changesets on the default branch. When you're ready, you can merge the merge request and either publish the packages to npm manually or set it up to publish automatically. Check out the Automating Changesets guide to learn more.
- The repo checked out and
@changesets/cliv3 installed — resolved from the repository first, with the package manager's global directory (npm/Yarn/pnpm) as a fallback GITLAB_TOKENwith permission to push, publish to the package registry and use the merge request API (theCI_JOB_TOKENis not sufficient)- A branch pipeline on the default branch for releasing, and a merge request pipeline for the
commentcommand
Note: environment variables are case-sensitive. Input names follow the same kebab-case as
changesets/action; because GitLab CI/CD variable names cannot contain hyphens, they are set through the underscore-normalizedINPUT_*variable (publish-scriptisINPUT_PUBLISH_SCRIPT). Boolean inputs accepttrue/false(any YAML spelling) and GitLab-style1/0.
INPUT_PUBLISH_SCRIPT- The command to use to build and publish packagesINPUT_VERSION_SCRIPT- The command to update version, edit CHANGELOG, read and delete changesets. Default tochangeset versionif not providedINPUT_COMMIT_MESSAGE- The commit message. Default toVersion PackagesINPUT_PR_TITLE- The merge request title. Default toVersion PackagesINPUT_PR_DRAFT- Controls draft MR behavior. Usecreateto create new version MRs as draft, oralwaysto also convert existing version MRs back to draft when updating themINPUT_PR_BASE_BRANCH- Sets the base branch of the merge request. Defaults toCI_COMMIT_REF_NAMEINPUT_CREATE_GITLAB_RELEASES- Whether to create GitLab releases after publishINPUT_PUSH_GIT_TAGS- Whether to create git tags after publish. IfINPUT_CREATE_GITLAB_RELEASESistrue, this option will also always betrueINPUT_PUSH_WITH_GIT_CLI- Whether to use the Git CLI instead of the GitLab API to push release commits and tags. Defaults totrue. When using the GitLab API, commits and tags are attributed to the owner ofGITLAB_TOKEN, and signed only if the instance signs commitsINPUT_CWD- The working directory to execute Changesets in. Defaults to the root of the repository
INPUT_PUBLISHED- Command executed after publishing (receivesPUBLISHEDandPUBLISHED_PACKAGES)INPUT_ONLY_CHANGESETS- Command executed when changesets are detectedINPUT_REMOVE_SOURCE_BRANCH- Enables the merge request "Delete source branch" checkbox. DefaultfalseINPUT_LABELS- Comma-separated labels for the version merge request
Inputs renamed to match
changesets/action:INPUT_PUBLISH,INPUT_VERSION,INPUT_COMMIT,INPUT_TITLEandINPUT_TARGET_BRANCHmust be renamed (they now error with the variable to use). Inputs whose normalized variable is unchanged (INPUT_CREATE_GITLAB_RELEASES,INPUT_REMOVE_SOURCE_BRANCH,INPUT_ONLY_CHANGESETS) keep working.
The CLI exposes separate commands, mirroring the changesets/action sub-actions. The default main command runs the whole release flow and is what most projects need; the others can be used to split the release across stages.
Run them with whichever package manager installed the CLI: the examples below use npx, and yarn changesets-gitlab / pnpm changesets-gitlab work the same. The Changesets CLI is resolved from the repository when present, so a globally installed changesets-gitlab also works.
comment- Comment on the merge request (like https://github.com/changesets/bot)pr-status- Generate changeset status in merge requests, and set thecomment-bodyoutputpr-comment- Create or update comments on merge requests fromINPUT_BODY, matched by the marker derived fromINPUT_UPDATE_ID(defaultchangesets-gitlab-pr-comment), and set thecomment-idoutputselect-mode- Select the mode to run a changesets workflow. Sets themode(andpublish-plan-pathwhen publishing) outputs; passINPUT_PUBLISH_PLAN_PATHto pin the plan to a fixed pathversion- Version packages and create or update a merge request with the changes. ReadsINPUT_SCRIPTlike the upstream/versionsub-action, falling back toINPUT_VERSION_SCRIPTpack- Pack publishable packages into tarballs. Accepts--publish-plan <path>and--out-dir <dir>, and sets thepack-diroutputpublish- Publish packages to npm. Accepts--from-pack-dir <dir>. ReadsINPUT_SCRIPTlike the upstream/publishsub-action, falling back toINPUT_PUBLISH_SCRIPTmain- The default full flow (select-mode + version + publish)
# Split the release across stages, using fixed paths so they can be shared
export INPUT_PUBLISH_PLAN_PATH="$CI_PROJECT_DIR/.changeset-publish-plan/publish-plan.json"
npx changesets-gitlab select-mode
npx changesets-gitlab version
npx changesets-gitlab pack --publish-plan "$INPUT_PUBLISH_PLAN_PATH" --out-dir "$CI_PROJECT_DIR/.changeset-pack"
npx changesets-gitlab publish --from-pack-dir "$CI_PROJECT_DIR/.changeset-pack"Every output is set with @actions/core. On GitHub Actions that writes the native $GITHUB_OUTPUT file; elsewhere it falls back to ~/.changesets-gitlab.outputs (same KEY<<delimiter format), so a later step in the same job can read the values. Set $GITHUB_OUTPUT to an empty string to opt out of the fallback.
published- A "true" or "false" string value to indicate whether a publishing is happened or notpublished-packages- A JSON array to present the published packages. The format is[{"name": "@xx/xx", "version": "1.2.0"}, {"name": "@xx/xy", "version": "0.8.9"}]has-changesets- A "true" or "false" string value about whether there were changesets. Useful if you want to create your own publishing functionalitypr-number- The merge request number that was created or updated
The select-mode (mode, publish-plan-path), pack (pack-dir), pr-status (comment-body) and pr-comment (comment-id) commands expose their outputs the same way. The INPUT_PUBLISHED command is run with PUBLISHED and PUBLISHED_PACKAGES set in its environment; prefer explicit paths/options when a later job needs a value.
GLOBAL_AGENT_HTTP_PROXY # optional, if you're using custom GitLab service under proxy
GLOBAL_AGENT_HTTPS_PROXY # As above but for https requests
GLOBAL_AGENT_NO_PROXY # Like above but for no proxied requests
# http_proxy, https_proxy, no_proxy environment variables are supported at the same time
GITLAB_HOST # optional, if you're using custom GitLab host, will fallback to `CI_SERVER_URL` if not provided
CI_COMMIT_SHA # required, the pipeline trigger commit; used to reset the release branch and to attribute API pushes/tags
CI_COMMIT_REF_NAME # required, the pipeline branch name, used as the default merge request base branch
CI_PROJECT_ID # required, the project id used by the GitLab API
# The CI_* variables above are injected automatically by GitLab CI, but may be
# unavailable by default in other CI environments, where they must be set explicitly.
GITLAB_TOKEN # required, token with accessibility to push, package registries, and merge request APIs. Note the CI_JOB_TOKEN does not have sufficient permissions
GITLAB_TOKEN_TYPE # optional, type of the provided token in GITLAB_TOKEN. defaults to personal access token. Can be `oauth` if you use Gitlab Oauth (personal access) token
GITLAB_CI_USER_NAME # optional, username with accessibility to push, used in pairs of the above token (if it was personal access token). If not set read it from the Gitlab API
GITLAB_CI_USER_EMAIL # optional, default `gitlab[bot]@users.noreply.gitlab.com`
GITLAB_COMMENT_TYPE # optional, type of the comment. defaults to `discussion`. can be set to `note` to not create a discussion instead of a thread
GITLAB_COMMENT_DISCUSSION_AUTO_RESOLVE # optional, automatically resolve added discussion when changeset is present, if you want to always resolve the discussion, you should actually use `GITLAB_COMMENT_TYPE=note` instead, default `true`
GITLAB_COMMENT_CUSTOM_LINKS # optional, override the links content referenced in the cli bot comment, use {{ addChangesetUrl }} placeholder for the dynamic URL to add a changeset
GITLAB_ADD_CHANGESET_MESSAGE # optional, default commit message for adding changesets on GitLab Web UI
DEBUG_GITLAB_CREDENTIAL # optional, set to `1`/`true` to echo the remote URL when debugging git authentication; WARNING: the remote URL may contain credentialsCreate a file at .gitlab-ci.yml with the following content.
stages:
- comment
- release
before_script: yarn --frozen-lockfile
comment:
image: node:lts-alpine
stage: comment
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script: yarn changesets-gitlab comment # comment automatically like https://github.com/changesets/bot
release:
image: node:lts-alpine
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
script: yarn changesets-gitlabnpm authentication is left to npm itself (the CLI never touches ~/.npmrc). Use one of:
-
Trusted Publishing / OIDC (preferred): configure npm Trusted Publishers for your GitLab pipeline (see the npm docs: https://docs.npmjs.com/trusted-publishers#supported-cicd-providers) and request
NPM_ID_TOKENin the release job withid_tokens(as in the example below). No token or.npmrcis needed. -
Classic automation token: create an npm automation token and expose it to the pipeline as
NODE_AUTH_TOKEN:release: variables: NODE_AUTH_TOKEN: $NPM_TOKEN # a masked/protected GitLab CI variable
If your npm version does not pick up
NODE_AUTH_TOKENon its own, reference it from a committed project.npmrc://registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}
For either method, create a file at .gitlab-ci.yml with the following content:
stages:
- comment
- release
before_script: yarn --frozen-lockfile
comment:
image: node:lts-alpine
stage: comment
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script: yarn changesets-gitlab comment
release:
image: node:lts-alpine
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
id_tokens:
NPM_ID_TOKEN:
aud: npm:registry.npmjs.org
script: yarn changesets-gitlab
variables:
INPUT_PUBLISH_SCRIPT: yarn releaseIf you need to add additional logic to the version command, you can do so by using a version script.
If the version script is present, this action will run that script instead of changeset version, so please make sure that your script calls changeset version at some point. All the changes made by the script will be included in the MR.
stages:
- comment
- release
before_script: yarn --frozen-lockfile
comment:
image: node:lts-alpine
stage: comment
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script: yarn changesets-gitlab comment
release:
image: node:lts-alpine
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
script: yarn changesets-gitlab
variables:
INPUT_VERSION_SCRIPT: yarn versionIf you are using Yarn Plug'n'Play, you should use a custom version command so that the action can resolve the changeset CLI:
stages:
- comment
- release
before_script: yarn --frozen-lockfile
comment:
image: node:lts-alpine
stage: comment
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script: yarn changesets-gitlab comment
release:
image: node:lts-alpine
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
script: yarn changesets-gitlab
variables:
INPUT_VERSION_SCRIPT: yarn changeset versionYou may also want to run yarn install after the changeset version command to update the yarn.lock in the version MR. You need to disable immutable lock file setting using an env variable:
release:
image: node:lts-alpine
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
script: yarn changesets-gitlab
variables:
YARN_ENABLE_IMMUTABLE_INSTALLS: 'false'
INPUT_VERSION_SCRIPT: yarn update-versionsAnd your update-versions script would be:
{
"update-versions": "changeset version && yarn install"
}| 1stG | RxTS | UnTS |
|---|---|---|
| 1stG | RxTS | UnTS |
|---|---|---|
Detailed changes for each release are documented in CHANGELOG.md.