CI integration
There are two parts to CI integration with beachball:
- Add a PR build step to call
beachball checkto validate that change files are included. - Add a release build step to call
beachball publishto publish to npm and push back to git (this page).
To automate the bumping of package versions based on change files, you'll need to configure your release workflow/pipeline so that beachball publish has write access to the git repo and npm registry. The exact steps will vary between CI systems, but general concepts as well as steps for some common setups are outlined below.
Setting options for publishing
⚠️ Beachball v3 respects
.npmrc, so in many cases it's no longer necessary to manually provideregistryor a token. (Exception due to unfinished features as of writing: ifBEACHBALL_NPM_TOKENor--tokenis set, you must explicitly setregistry.)
Most beachball publish options such as --access and --registry can be set in the beachball config if they don't interfere with other commands. As of v3, commitMessage can also be used to customize --message for publish. For example:
/** @type {Partial<import('beachball').RepoOptions>} */
const config = {
// this should almost always be set
access: 'public',
// if you want to customize the commit message
commitMessage: (options, packageInfos, bumpInfo) => {
return options.command === 'publish' ? 'Bump package versions' : undefined;
},
// ... other options ...
};
module.exports = config;
If you need to set CLI options that are specific to publishing, it's recommended to use a package.json script wrapping beachball publish.
Providing the npm token (--token or -n) on the command line is not recommended. See npm authentication below for alternatives.
Authentication
In the most common workflow, beachball publish requires authenticating with:
npmto publish packagesgitto push changes (version bumps, changelog updates, change file cleanup) back to the target branch
If using personal access tokens for authentication, they should have the minimum necessary permissions and be stored as secrets that are only available to release builds.
npm authentication
⚠️ Beachball v3 respects
.npmrc, so in many cases it's no longer necessary to manually provideregistryor a token. (Exception due to unfinished features as of writing: ifBEACHBALL_NPM_TOKENor--tokenis set, you must explicitly setregistry.)
Trusted publishing (preferred)
If publishing to the public npm registry (registry.npmjs.org) from GitHub Actions or another supported CI platform, you should configure trusted publishing instead of using a token.
Azure DevOps doesn't support trusted publishing as of June 2026, so in that case you'll need to use a token.
Token-based authentication
If publishing to the public npm registry (registry.npmjs.org) from Azure DevOps or another CI platform that doesn't support trusted publishing, create a granular access token with write access to only the relevant package(s) and/or scope(s), and store it as a secret.
Token authentication can potentially also be used for publishing to private registries, but setup details will vary.
To pass an npm token to beachball publish, do one of the following:
- Set the
BEACHBALL_NPM_TOKENenvironment variable while runningbeachball publish(NPM_TOKENis also respected) - Manually set the token in
.npmrc - Old way (not recommended): use
--token <token>on the command line
Temporarily, you must also set registry if explicitly providing a token. (This will be picked up from .npmrc in the Beachball v3 official release.)
Other approaches
For Azure DevOps repos publishing to a private registry, the most common approach is to run the npmAuthenticate task prior to beachball publish (which will pick up that credential automatically). Alternatively, you can pass a token using one of the approaches described in the previous section.
If manually running beachball publish locally, you can run npm login beforehand, and beachball will use those credentials.
git authentication
By default, beachball publish pushes changes (version bumps, changelog updates, change file cleanup) back to main/master or the configured branch option. Since this branch should be protected, some extra configuration is needed to provide a token with permission to bypass branch policies.
GitHub repos
The built-in GITHUB_TOKEN can't be given permission to bypass branch protection rules, so you'll need to manually create a token using one of the following approaches:
- Traditional approach: use a fine-grained personal access token (PAT) with write permissions for only the specific repo, and store it as a secret.
- The user creating the token must have admin access or permission to bypass branch protection rules.
- Variant: create a fine-grained PAT with a "machine user" account. Create a new account with an alternate email or subaddress (
+address), give it contributor permissions to only this repo, and give it permission to bypass rules.
- New: use a GitHub app installation token. For this purpose, an "app" is essentially just an identity with permissions; you don't need to define any logic or endpoints. Create a GitHub app, install it in your repo, and give it permission to bypass policies, then use the
beachball-auth-helperCLI to create a token.
After creating a GitHub token, it can be passed through to beachball publish via the BEACHBALL_GIT_TOKEN environment variable. For example:
- name: Publish packages
run: npx beachball publish
env:
BEACHBALL_GIT_TOKEN: ${{ secrets.BEACHBALL_GIT_TOKEN }}
(Using BEACHBALL_GIT_TOKEN is preferred over the old approach of setting the remote URL since it reduces potential for exposure of credentials. The token is passed to git processes via git config environment variables, and any conflicting extraheader config is automatically overridden.)
Azure DevOps or other repos
For Azure DevOps repos publishing to a private registry, there are other possible approaches (such as using a service account with credentials stored in a key vault) which are not currently covered by these docs.
If the authentication approach uses a token, it can be passed to beachball publish via the BEACHBALL_GIT_TOKEN environment variable, similar to the GitHub example above.
Storing secrets
GitHub Actions
To restrict secret access to appropriate branches, use an environment. (That doc link focuses on cloud deployments or resources, but environments can also be used only for secret storage.)
- Create an environment (example below uses the name
release). - Restrict deployment branches to "Selected branches" and add a rule to allow only your release branch(es) (e.g.
main/master). - Add the relevant secrets.
- To use the environment, add a key
environment: your-env-namein your release workflow job. (Full example below.)
Azure Pipelines
There are a couple of options here:
- Use secret variables in your release pipeline.
- Use secrets in a variable group, which can optionally be linked to a key vault. Ensure that this variable group is only accessible to your release pipeline.
Publishing
The exact publishing setup will vary depending on your CI setup, but the overall steps are as follows:
- Ensure the git user name and email are set, or git will reject the commit. Somewhere in your pipeline:
git config user.name "someone" git config user.email "someone@example.com" - Set up git authentication using a token, SSH keys, or some other non-interactive method
- Set up npm authentication
- Run
beachball publish!
GitHub repo + GitHub Actions
Here's a sample setup for publishing from a GitHub repo using GitHub actions. The environment, secret, and script names can be modified as you prefer.
This sample assumes the following:
- An environment called
release(set up as described above) - In the
releaseenvironment, aBEACHBALL_GIT_TOKENsecret storing a fine-grained personal access token with write access (as described above) - Trusted publishing is enabled for the package(s), linked to this workflow, and given access to the
releaseenvironment.
# Publishing on manual trigger only is recommended
on:
workflow_dispatch:
jobs:
publish:
runs-on: ubuntu-latest
environment: release
permissions:
# Required for trusted publishing
id-token: write
steps:
- name: Check out code
uses: actions/checkout@v6
# ... Other steps to prepare for publishing (install, build, test, etc) ...
- name: Publish
run: |
git config user.name "someone"
git config user.email "someone@example.com"
npx beachball publish
env:
# No npm token needed with trusted publishing
BEACHBALL_GIT_TOKEN: ${{ secrets.BEACHBALL_GIT_TOKEN }}
GitHub repo + Azure Pipelines
Here's a sample setup for publishing from a GitHub repo using Azure Pipelines. The environment, secret, and script names can be modified as you prefer.
This sample assumes the following:
- A variable group called
Beachball secrets(set up as described above) with the following secrets:BEACHBALL_NPM_TOKEN: An npm token with write access to the package(s) and/or scope(s), such as a fine-grained token for public npmBEACHBALL_GIT_TOKEN: A GitHub fine-grained personal access token with write access (as described above).- Alternatively, this could be an app installation token configured in an earlier step rather than stored in the key vault.
# Publishing on manual trigger only is recommended
pr: none
trigger: none
# This group should only be accessible to the release pipeline
variables:
- group: Beachball secrets
steps:
# ... Other steps to set up repo and prepare for publishing (install, build, test, etc) ...
- script: |
git config user.name "someone"
git config user.email "someone@example.com"
npx beachball publish
name: Publish
env:
BEACHBALL_GIT_TOKEN: $(BEACHBALL_GIT_TOKEN)
BEACHBALL_NPM_TOKEN: $(BEACHBALL_NPM_TOKEN)
Azure Repos + Azure Pipelines
This should be very similar to the GitHub version, aside from possibly the authentication method. You could potentially use personal access tokens for git and npm feed authentication (similar to above), or other methods are available which aren't currently covered here.
If you're publishing to a private Azure Artifacts npm feed, be sure to set registry in the beachball config as described above.