Skip to content

Release Process

This document describes how to release new versions of packages under the LavaMoat umbrella and how that works

How to Publish to npm

  1. Review, approve, then merge the currently-open Release Please pull request.

  2. Immediately after merging, checkout the main branch and pull the changes from LavaMoat/LavaMoat into your working copy.

  3. Assert you are logged in to the npm registry; use npm login and/or npm whoami. Do not do this on an untrusted machine.

  4. Assert your working copy has no modifications (e.g., via git status).

  5. Assert you are running Node.js v18.0.0 or later (via node --version) and npm v9.8.1 or later (via npm --version).

  6. Execute npm ci (“Clean Install”; not “Continuous Integration”).

  7. This step depends on whether you are publishing a new package:

    • If you are not publishing a new package, execute npm run release
    • If you are publishing a new package, execute npm run release --newPkg=<package-name>

    In both cases, Artifacts will be rebuilt and the default set of tests will run. Do not attempt to publish individual packages!

  8. Check the output of npm pack to ensure the correct files are being published.

  9. If prompted, enter your 2FA passcode or visit the URL npm provides you. Once authenticated, the publish will proceed.

  10. Verify the published package(s) on npm.

  11. For extra credit, verify the GitHub Releases.

How Releases Work

The Release Please GitHub Action automates all parts of the release process except the publish to the public npm registry.

This is the process:

  1. A contributor creates a PR targeting the main branch (main). PRs may contain changes across packages. They may not contain version bumps.

  2. The contributor’s PR is reviewed, approved, then squashed & merged into main.

  3. The Release Please Action triggers, and it creates (or updates) a “release” pull request (there will only ever be one at a time); we call this the Release Please PR. The PR will contain a single commit, and its description will contain an auto-generated changelog. Release Please will also create a Draft GitHub Release for each package to be released.

  4. As additional PRs from contributors are merged into main, the Release Please Action will rebase and update the Release Please PR to reflect these changes. Dependencies will be automatically bumped between packages as needed—and kept at the latest version regardless of any major version bumps.

  5. A maintainer reviews a Release Please PR, and when they are satisfied with the changes, they merge it into main. This will trigger the Release Please Action again—but this time, the GitHub Releases will come out of “draft” status and be “official”. Release Please will now delete its PR branch.

  6. The maintainer must immediately publish to npm.

  7. Go to step 1.

A Note About Lifecycle Scripts

npm’s ignore-scripts flag disables all lifecycle scripts for all packages. This means, for example, a prepublishOnly script will not automatically run upon an npm publish.

This is intentional. Thus, any actions that must happen pre-publish (or pre-anything) must be invoked explicitly in our package.json scripts.

This does not, however, prevent a maintainer from running npm publish without having rebuilt and tested beforehand! So: don’t do that. Use npm run publish only.

Publishing, Under the Hood

If npm ignored workspaces that have already been published, we wouldn’t need any extra tooling (Laverna). But it does not ignore them, and instead aborts the operation. To avoid this, we need to first analyze the workspaces and query the registry for each to determine which packages have already been published. We filter those packages out of the list of packages to be published.

This “has this been published already?” query (done via npm view) will naturally fail if the package does not yet exist. Since we have no way of knowing whether it should exist—or perhaps was a typo—the maintainer must explicitly declare the names of the new, never-published packages. This is done via the --newPkg flag to npm run release, which makes its way into Laverna.

Addendum: Workspace Dependency Matrix

This is a table describing which packages depend on which other packages.

Directories are relative to packages/.

DirectoryPackage NameDependencies
aa@lavamoat/aa
allow-scripts@lavamoat/allow-scripts@lavamoat/aa
browserifylavamoat-browserify@lavamoat/aa, @lavamoat/lavapack, lavamoat-core
corelavamoat-corelavamoat-tofu
lavapack@lavamoat/lavapacklavamoat-core
nodelavamoat@lavamoat/aa, lavamoat-core, lavamoat-tofu
perf(private)lavamoat-browserify, lavamoat
preinstall-always-fail@lavamoat/preinstall-always-fail
survey(private)lavamoat, lavamoat-core, lavamoat-tofu
tofulavamoat-tofulavamoat-core (peer)
yarn-plugin-allow-scripts(private)