Pipelines npm
GitLab CI templates for Node/npm consumer repos.
Canonical source: singletonsd/pipelines/npm. Agent contract in that repo: AGENTS.md. Consumer copy-paste: examples/.
Compose with engineering/repo-init-npm-publish when scaffolding a new publishable package.
When to use
- Adding or editing
.gitlab-ci.ymlin a library/CLI that should use shared npm jobs - Enabling GitLab and/or npmjs publish from
release_job - Changing templates in
singletonsd/pipelines/npm(matchAGENTS.mdthere)
Consumer include
image: "node:22-alpine"
include:
- project: "singletonsd/pipelines/npm"
file: "/src/.gitlab-ci-main.yml"
variables:
GLOBAL_IMAGE_NAME: "node"
GLOBAL_IMAGE_TAG: "22-alpine"
ENABLE_RELEASE_JOB: "true"
ENABLE_RELEASE_PUBLISH_ALL: "true"
NPMJS_SCOPE: "singleton-sd"
PAGES_ENABLED: "false"
stages:
- install
- test_static
- build
- test_dynamic
- release
- package
- deploy
Full snippets: examples/.gitlab-ci-example-main.yml, examples/.gitlab-ci-example-common.yml, examples/.gitlab-ci-example-release.yml.
The consumer must define yarn release:ci (usually release-it). Package name is always package.json "name" on every registry. Scopes (RELEASE_GROUP_NAME, NPMJS_SCOPE) must match that name. The npm org/scope is @singleton-sd; the GitLab include path stays singletonsd/pipelines/npm (project path, not npm scope).
Publish flags
| Variable | Effect |
|---|---|
ENABLE_RELEASE_PUBLISH=true |
Legacy GitLab-only when the new flags are unset |
ENABLE_RELEASE_PUBLISH_ALL=true |
GitLab Package Registry and npmjs.org |
ENABLE_RELEASE_PUBLISH_GITLAB=true |
GitLab only |
ENABLE_RELEASE_PUBLISH_NPMJS=true |
npmjs only (npm publish --access $NPMJS_ACCESS) |
NPMJS_ACCESS defaults to public. NPMJS_SCOPE defaults to RELEASE_GROUP_NAME. Example consumer org: singleton-sd.
Resolution (union / OR, not exclusive winner)
- If
ENABLE_RELEASE_PUBLISH_ALL == "true"→ publish GitLab and npmjs._GITLAB/_NPMJS/ legacy cannot turn a target off while_ALLis true. - Else GitLab if
ENABLE_RELEASE_PUBLISH_GITLAB == "true"; npmjs ifENABLE_RELEASE_PUBLISH_NPMJS == "true"(both can be true; that equals_ALL). - Legacy
ENABLE_RELEASE_PUBLISH == "true"applies only when_ALL,_GITLAB, and_NPMJSare all not"true"→ GitLab only. - Any new flag (
_ALL,_GITLAB, or_NPMJSset to"true") suppresses the legacy alias even ifENABLE_RELEASE_PUBLISHis also"true".
Examples:
_NPMJS=true+ENABLE_RELEASE_PUBLISH=true→ npmjs only (legacy off)_ALL=true+_NPMJS=false→ still both (no per-target off-switch)
Secrets (masked CI variables, never in YAML)
| Variable | Required when |
|---|---|
SSH_PRIVATE_KEY |
ENABLE_RELEASE_JOB=true (push release commit/tag) |
NPMJS_TOKEN |
npmjs publish (_ALL or _NPMJS) |
NPM_TOKEN |
GitLab registry auth (defaults to CI_JOB_TOKEN) |
If npmjs publish is on and NPMJS_TOKEN is missing, release_job must fail before yarn release:ci.
The trigger flag is RELEASE_TRIGGER_PIPELINE. Do not use NODE_COMMON_RELEASE_TRIGGER_PIPELINE or ORIGINAL_REPOSITORY — those names are unused in the templates.
Do not
- Invent a second package name for npmjs
- Commit tokens or rewrite
.npmrcsecrets into git - Point one scope at two registries at once (the job rewrites
@scope:registrybetween publishes) - Treat
ENABLE_RELEASE_PUBLISH=trueas publish-everywhere (that remains GitLab-only)
Related
- Common templates (Pages, AWS, YAML lint):
singletonsd/pipelines/common(AGENTS.mdthere) - New package scaffold:
engineering/repo-init-npm-publish