prod like a pro, npm edition
similar to how i’ve been able to automate how i deploy backend services, i wanted to ensure that when releasing libraries, every step of the way was fully automated.
overall, i wanted the following to hold true:
- i work on new changes on the library in a feature branch.
- when i raise a pull request from the feature branch to main, a “preview” version of the changes which i just worked on gets published to npm (or whichever registry) - something installable by anyone.
- once validated and merged, a “canary” or “next” version gets automatically released to the registry.
- once i am ready to “cut” a new version, i create a new release & tag on github, then publishing it properly releases the library in the registry on the
latesttag.
after trialing out the above for a bit, it became clear that there was no value in having step 2 since i work solo on the library.
npm link locally was sufficient, so i simplified to just:
- on every push/merge to main, release a
canaryversion of the library. - once ready for proper release, release the
lateststable version.
canary
published versions under the canary tag are what i use to validate e2e that the functionality i am introducing or the bug that i am fixing works the way it’s intended to.
it’s also a version i can point anyone looking to trial a fix or new feature without breaking the stable version.
for chronos’ sdk, installing the latest canary would just be:
npm i @chronos.sh/sdk@canaryor if looking to eval a specific canary version:
npm i @chronos.sh/[email protected]to get this happening automatically on merge to main, i have the following action job:
# snippet from the full workflow
on:
push:
branches: [main]
jobs:
canary:
name: Publish canary
runs-on: ubuntu-latest
environment: npm-publish
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/setup
- name: Set canary version
run: |
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7)
NEXT_PATCH=$(npm version patch --no-git-tag-version)
npm version "${NEXT_PATCH#v}-canary.${SHORT_SHA}" --no-git-tag-version
- run: pnpm build
- name: Publish
run: npm publish --tag canary --access publicnote: to authenticate with npm without an explicit npm token, i am using npm’s OIDC trusted publishing
latest
once satisfied with whatever i was validating in the canary tag, releasing the package on the latest tag then becomes similar to how i release backend services to prod.
i first bump the version in package.json, then create a release and corresponding tag in github and hit publish.
upon publishing the github release, an action is responsible for automatically publishing the library:
# snippet from the full workflow
on:
release:
types: [published]
jobs:
release:
name: Publish stable
runs-on: ubuntu-latest
environment: npm-publish
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v6
- uses: ./.github/actions/setup
- name: Validate tag matches package version
run: |
PKG_VERSION=$(node -p "require('./package.json').version")
TAG_VERSION="${GITHUB_REF_NAME#v}"
if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then
echo "::error::Tag '${GITHUB_REF_NAME}' does not match package.json version '${PKG_VERSION}'"
exit 1
fi
- run: pnpm build
- name: Publish
run: npm publish --access publicupon publishing, the latest stable version of the library is then installable via:
npm i @chronos.sh/sdk