Stage npm Releases with GitHub Actions
Stage npm package releases in GitHub Actions and promote them after review.
Introduction
30 Second Summary
Release automation saves time. A leaked publishing credential can turn one bad workflow run into a public release.
In this project, you will publish a tiny npm package by hand. You will build a GitHub Actions workflow that stages each new version for human review before it can go live.
What You'll Build
Your final demo shows a pushed change becoming a staged package version while 0.1.0 remains live until you manually promote the release.
By the end of this project, you'll have:
- A public npm package with version 0.1.0 visible on its package page.
- A stage-only workflow that prepares a new package version whenever you push a change without making that version public.
- A manual promotion step followed by a fresh install that proves the approved version is available to everyone.
- An optional Secret Mission to push your release-safety skills further.
Are there any prerequisites?
You'll need an npm account plus a GitHub repository. You also need Node installed plus a public package name nobody has taken.
Before We Start
Your release pipeline moves package code from your computer to a public registry. Each part needs to be ready before you create the package.
Node.js runs the package code. npm connects your terminal to the registry.
Git records your changes. GitHub hosts the repository that runs the review workflow.
In this step, get ready to:
- Prepare the local command-line tools needed for package work.
- Sign in to npm for registry access.
- Sign in to GitHub for repository access.
Check Node.js and npm
Node.js gives your computer a JavaScript runtime. Its installer also includes the npm command-line tool used to publish packages.
macOS
- Press Cmd+Space to open Spotlight.
- Type Terminal into Spotlight.
- Press Enter to open Terminal.
Windows
- Press the Windows key to open search.
- Type PowerShell into search.
- Press Enter to open PowerShell.
- Check whether Node.js and npm are available by running:
node -v
npm -v
What do these checks prove?
- node -v asks the Node.js runtime to print its installed version.
- npm -v asks the npm command-line tool to print its installed version.
✔️ I see two version numbers
Good start. Your computer can now run package code through Node.js and work with the registry through npm.
ⓧ One check does not return a version
A missing version means the required tool is unavailable in your terminal. Installing the Node.js LTS release adds both tools.
- Open the official Node.js download page.
- Choose the LTS release.
- Choose the prebuilt installer for the operating system shown on the page.
- Open the downloaded installer.
- Accept the default installation options.
- Close your current terminal window after the installer finishes.
- Repeat the platform steps above to open a new terminal window.
- Check the installation again by running:
node -v
npm -v
Why open a new terminal?
The installer makes the commands available to new terminal sessions. Reopening the terminal ensures it can find both tools.
You should now see one version number for Node.js followed by another version number for npm.
Still missing a version?
- Confirm that the installer finished before reopening your terminal.
- Restart your computer if the newly installed commands remain unavailable.
Help me fix my Node.js or npm installation.
Check Git
Git creates the change history that GitHub receives. The workflow later runs from that hosted history.
- Check whether Git is available by running:
git --version
What does this check prove?
git --version asks Git to identify the installed version. A version response confirms that your terminal can use Git.
✔️ Git returns a version
Git is ready to record the package changes that you send to GitHub.
ⓧ Git does not return a version
Git needs a platform-specific installation. Choose the tab for your computer.
macOS
macOS opens a system installation dialog after the next command.
- Start the command-line tools installation by running:
xcode-select --install
What does this command do?
xcode-select --install asks macOS to install Apple's command-line tools. Those tools include Git.
- Complete the macOS installation prompt.
- Return to Terminal after the installation finishes.
- Verify Git by running:
git --version
What confirms success?
The command checks whether Terminal can now find Git. You should see a Git version in the output.
Windows
- Open the official Git for Windows download page.
- Choose the x64 or ARM64 standalone installer that matches your computer.
- Open the downloaded installer.
- Accept the default installation options.
- Repeat the Windows search steps above to return to PowerShell.
- Verify Git by running:
git --version
What confirms success?
The command checks whether PowerShell can now find Git. You should see a Git version in the output.
Git still unavailable?
- Confirm that the installation completed before checking the version.
- Restart your terminal so it can detect the newly installed command.
Help me get Git working.
Prepare your npm and GitHub accounts
Your npm account owns the public package. Your GitHub account owns the repository that stages each release.
Credentials deserve care here. Enter them only on official npm pages or official GitHub pages.
✔️ I have an npm account
- Open the official npm sign-in page.
- Enter your npm account credentials.
- Complete any authentication prompt shown for your account.
ⓧ I need an npm account
- Open the official npm signup page.
- Enter a lowercase username in the Username field.
- Enter your email address in the Email address field.
- Enter a strong password in the Password field.
- Agree to the npm terms shown on the page.
- Click Create An Account.
- Complete the verification link sent to your email address.
Why verify your email?
npm requires a verified email address before your account can publish packages to the registry. Verification prepares the account for the first release.
✔️ I have a GitHub account
- Open the official GitHub sign-in page.
- Enter your GitHub account credentials.
- Complete any authentication prompt shown for your account.
ⓧ I need a GitHub account
- Open the official GitHub signup page.
- Follow the prompts to create your personal account.
- Complete the verification link sent to your email address.
Why verify your email?
GitHub requires a verified email address for basic account tasks such as creating a repository. Verification prepares your account for the project workflow.
- Connect the local npm command-line tool to your account by running:
npm login
What does this command do?
npm login starts npm's authentication process for your terminal. This gives later npm commands access to your account.
- Follow the authentication prompts shown by npm.
Before you check, which npm username do you expect the terminal to return?
- Verify the signed-in npm account by running:
npm whoami
What does this check prove?
npm whoami asks the registry which account your terminal is using. The response proves that local npm commands are authenticated.
You should see your npm username in the terminal.
No npm username returned?
- Confirm that you completed every authentication prompt from the login command.
- Confirm that your npm email address is verified.
- Run the login command again if the authentication session expired.
Help me authenticate the npm command-line tool.
Before you open the form, do you expect GitHub to show your personal account as an available owner?
- Open GitHub's new repository page.
- Confirm that the Owner field lists your personal account.
You should see the new repository form with your account available as its owner. This confirms that you are signed in with repository creation access.
Your tools and accounts are ready. Next, you will create the small package and publish its first release by hand.
Create and Publish the Package
Your review-gated pipeline needs a live release that future staged versions can be compared against. Publishing version 0.1.0 by hand creates that baseline on the npm registry.
You will create the package under your npm username. You will also save it in a local Git repository that is ready for GitHub.
In this step, get ready to:
- Create a scoped npm package with version 0.1.0.
- Save the package in a local Git repository.
- Publish the package manually as a public release.
Create the scoped package
An npm scope places a package under your account namespace. Your package name becomes @YOUR_NPM_USERNAME/review-gated-package.
- Confirm your signed-in npm username by running this command:
npm whoami
What does this command do?
The command asks the registry which npm account is connected to your terminal. The printed username becomes the scope for your package.
- Store the printed username as YOUR_NPM_USERNAME.
- Move to your Desktop by running this command:
cd ~/Desktop
Where does this command take you?
This command moves your terminal into the Desktop folder. Your new package folder will be easy to find there.
- Create the review-gated-package folder by running these commands:
mkdir review-gated-package
cd review-gated-package
npm init --yes
What does this setup create?
- The first command creates the review-gated-package folder on your Desktop.
- The second command moves your terminal into that folder.
- The final command creates package.json with npm's default package metadata.
- Set the package name to your npm scope by running this command:
npm pkg set name=@[[YOUR_NPM_USERNAME="YOUR_NPM_USERNAME"]]/review-gated-package version=0.1.0 description="A package released through a review gate"
Why do these fields matter?
- The name field gives the package its unique registry address under your account.
- The version field establishes 0.1.0 as the first release.
- The description field explains the purpose of the package on its npm page.
- Verify the package identity by running this command:
npm pkg get name version
What does this check prove?
This command reads the package identity directly from package.json. It catches a wrong scope or version before anything becomes public.
You should see your scoped package name with version 0.1.0.
Package details look wrong?
- Check that your stored npm username matches the value printed by npm whoami.
- Check that your terminal is inside the review-gated-package folder.
Ask for help with the package metadata here: Help me fix the name or version in my npm package metadata.
Save the package in Git
A local repository records the exact package state that produced the first public release. That same history becomes the starting point for the workflow in a later step.
- Initialize the package folder as a Git repository by running this command:
git init
What does Git initialize?
Git creates a hidden repository inside review-gated-package. The existing package files remain unchanged.
You should see confirmation that an empty Git repository was initialized.
- Record the package metadata in the first commit by running these commands:
git add .
git commit -m 'Initial project version'
What does this commit capture?
- The first command stages every package file for the next snapshot.
- The second command records that snapshot with the message Initial project version.
You should see Git confirm a first commit containing package.json.
Git did not create the commit?
- Configure your Git author name if the terminal asks for your identity.
- Configure your Git author email if the terminal asks for your identity.
- Rerun the commit command after completing the requested configuration.
Get help with the failed commit here: Help me complete the first Git commit for my npm package.
Publish version 0.1.0
Publishing is the point where your package becomes public. Your verified 0.1.0 baseline is ready for that step.
Why publish this version manually?
The manual release proves that you control the package before automation receives access. It also gives later staged versions a live release to sit beside.
Before you run the publish command, which package name and version do you expect npm to release?
- Complete your npm account's publish authentication if npm requests it.
- Publish the scoped package publicly by running this command:
npm publish --access public
What does public access mean?
The command uploads the current package to the npm registry. The access setting makes this scoped package publicly visible.
A published name and version pair cannot be reused. Future releases need a new version number.
You should see npm report that @YOUR_NPM_USERNAME/review-gated-package version 0.1.0 was published.
Publish did not complete?
- Confirm that the package scope matches the npm username printed earlier.
- Complete any publish authentication requested by your npm account.
- Check whether version 0.1.0 was already published during an earlier attempt.
Get help with the publish result here: Help me diagnose why my scoped npm package did not publish.
Before you check the package page, do you expect version 0.1.0 to be private or publicly available?
- Switch back to your browser.
- Load your package page by entering this address:
https://npmjs.com/package/@[[YOUR_NPM_USERNAME="YOUR_NPM_USERNAME"]]/review-gated-package
What does this page confirm?
The package page is the public registry record for your release. It shows the package visibility plus the version available to other npm users.
You should see public below the package name. You should also see version 0.1.0 as the live version.
That is your first release complete. Your package now has a public baseline that the review-gated workflow can protect.
✔️ Awesome, I've got everything!
Your local Git repository and live npm package match the checkpoint.
ⓧ I'd like to double check the full code
Package created in a local Git repository and manually published to npm as version 0.1.0. Version 0.1.0 is live and publicly available on the package's npm page.
Your public baseline is ready. Next, you will create the scoped credential that can stage future versions without publishing them directly.
Create a Stage-Only Token
Your package is live on npm at version 0.1.0. The local Git repository is ready for automation.
The next goal is to give GitHub Actions permission to stage only this package. A granular access token keeps direct live publishing outside the workflow.
If the workflow is compromised, the token can only prepare a staged version of the package. A maintainer still controls whether that version becomes live.
In this step, get ready to:
- Create an empty GitHub repository for the existing local project.
- Create a granular npm token scoped to @YOUR_NPM_USERNAME/review-gated-package.
- Store the token as the NPM_STAGE_TOKEN repository secret.
Create the GitHub repository
A repository secret belongs to one GitHub repository. An empty remote repository gives your existing local history a destination without introducing conflicting files.
- In your signed-in GitHub account, select the menu in the upper-right corner.
- Click New repository.
- Select your personal account from the Owner menu.
- Enter review-gated-package in the Repository name field.
GitHub checks the repository name as you type. You should see that review-gated-package is available under your account.
- Select Public under Choose visibility.
- Leave the repository initialization options unselected.
- Click Create repository.
Good progress: your empty review-gated-package repository is ready to receive the existing local history.
Generate the stage-only token
Granular tokens limit which packages an automated workflow can access. The stage-only permission sends new versions into a review queue before they can become live.
- In your signed-in npm account, click your profile picture in the upper-right corner.
- Click Access Tokens.
- Click Generate New Token.
You'll see the granular token form. Its package controls define the exact boundary your workflow receives.
- Enter review-gated-package-stage-only in the Token name field.
- Select Read and write (stage only) from the Permissions menu in the Packages and scopes section.
The permission summary should now show Read and write (stage only). This setting prevents direct publication of a new version.
- Select Only select packages and scopes under Select Packages.
- Select @YOUR_NPM_USERNAME/review-gated-package from the package menu.
The token summary should name only @YOUR_NPM_USERNAME/review-gated-package. It should also show Read and write (stage only).
This credential appears in full only once, so this part deserves a careful minute.
- Click Generate Token.
- Copy the token value from the one-time reveal.
That is the sensitive part handled: this token can stage new versions of your selected package for review. It cannot publish those versions directly to the live registry.
What Does Stage-Only Protect?
For new versions, Read and write (stage only) limits this token to staging. A maintainer must review and promote the version before it becomes live.
Cannot Find the Package?
- Confirm that your signed-in npm account owns @YOUR_NPM_USERNAME/review-gated-package.
- Check that the package is selected under Only select packages and scopes.
- Change the permission to Read and write (stage only) if the summary shows a direct-publishing option.
Need help checking your token scope? Ask in the npm community discussions if the package or permission is still missing.
Store the token as a repository secret
A repository secret gives the workflow access to the token without placing the credential in your files. GitHub encrypts the secret when you submit it.
- Switch back to the empty review-gated-package repository from earlier.
- Click Settings under the repository name.
- Select Secrets and variables in the Security section of the sidebar.
- Click Actions.
You'll see the repository's Actions secrets page. This page stores credentials that workflows can request by name.
- Click the Secrets tab.
- Click New repository secret.
The form has separate fields for the reference name and the protected credential value.
- Enter NPM_STAGE_TOKEN in the Name field.
- Paste the copied npm token into the Secret field.
Before you save it, what do you expect GitHub to show once the token value is hidden?
- Click Add secret.
You've secured the handoff: you'll see NPM_STAGE_TOKEN listed under repository secrets without its value. This confirms the workflow can reference the credential without exposing it.
Secret Name Missing?
- Confirm that you are viewing the Secrets tab under Actions.
- Check that the Name field contains NPM_STAGE_TOKEN exactly.
- Confirm that the full token was pasted into the Secret field.
Help me troubleshoot this repository secret. Keep the token value private while you troubleshoot.
Your repository now holds a package-scoped credential that cannot send a new version straight to the live registry. Next up, you'll build the workflow that uses it to stage a release for review.
Automate Staged Publishing
You secured NPM_STAGE_TOKEN in the previous step. GitHub Actions can now use it without placing the token in your repository.
This workflow prepares 0.1.1 on every push. The stage-only permission holds that version for human review.
A compromised workflow can create a staged version. It cannot turn that version into a live npm registry release.
In this step, get ready to:
- Create a push-triggered workflow for staged publishing.
- Use NPM_STAGE_TOKEN to stage version 0.1.1.
- Confirm the workflow run completes successfully.
Create the staged publishing workflow
GitHub Actions reads workflow definitions from YAML files inside .github/workflows. Each push event starts the jobs defined in the file.
- Return to the GitHub repository where you saved the package secret.
- Select the Add file dropdown above the repository files.
- Click Create new file.
- Enter .github/workflows/stage-publish.yml in the file name field.
- Build the staged publishing workflow by pasting this code into the file editor:
name: Stage Publish
on:
push:
jobs:
stage:
runs-on: ubuntu-latest
steps:
# Pull the package files into the runner
- uses: actions/checkout@v6
# Configure Node and npm registry authentication
- uses: actions/setup-node@v6
with:
node-version: '24'
registry-url: 'https://registry.npmjs.org'
package-manager-cache: false
# Reproduce the locked dependency tree
- run: npm ci
# Prepare the next patch without a Git tag
- run: npm version patch --no-git-tag-version
# Submit the package for maintainer review
- run: npm stage publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_STAGE_TOKEN }}
What Does This Workflow Do?
- The push trigger starts the workflow whenever a commit reaches the repository.
- The actions/checkout@v6 step downloads the repository onto the runner.
- The actions/setup-node@v6 step provides Node.js 24. It also configures authentication for the npm registry.
- The npm ci step installs the dependency tree recorded by the package lockfile.
- The npm version patch --no-git-tag-version step changes the package version from 0.1.0 to 0.1.1 without creating a Git tag.
- The npm stage publish step submits 0.1.1 for review. NODE_AUTH_TOKEN receives the saved NPM_STAGE_TOKEN secret only while that step runs.
✔️ Awesome, I've got everything!
The workflow file is complete. It is ready to commit.
ⓧ I'd like to double check the full code
name: Stage Publish
on:
push:
jobs:
stage:
runs-on: ubuntu-latest
steps:
# Pull the package files into the runner
- uses: actions/checkout@v6
# Configure Node and npm registry authentication
- uses: actions/setup-node@v6
with:
node-version: '24'
registry-url: 'https://registry.npmjs.org'
package-manager-cache: false
# Reproduce the locked dependency tree
- run: npm ci
# Prepare the next patch without a Git tag
- run: npm version patch --no-git-tag-version
# Submit the package for maintainer review
- run: npm stage publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_STAGE_TOKEN }}
Before the push starts the workflow, what outcome do you expect for 0.1.1?
- Click Preview above the file editor.
- Click Commit changes.
- Enter Add staged publishing workflow in the Commit message field.
- Choose the option that commits to the current default branch.
- Click Commit changes to push the workflow file.
GitHub records the commit as a push. That event starts the Stage Publish workflow.
Workflow Did Not Start?
- Confirm the file path is exactly .github/workflows/stage-publish.yml.
- Check that the workflow contains the push trigger.
Ask for help checking the workflow structure without sharing the token value: Help me find why my Stage Publish GitHub Actions workflow did not start after I committed stage-publish.yml.
Watch the staged publish finish
Each workflow step reports its own result. The final green status proves the complete automation path reached npm staging.
Before you open the run, which version do you expect the patch step to prepare?
- Select the Actions tab in the repository navigation.
- Select Stage Publish in the workflow list.
- Open the newest run for the Add staged publishing workflow commit.
- Select the stage job.
You will see the workflow steps listed in execution order.
- Expand the step that runs npm version patch --no-git-tag-version.
You will see 0.1.1 in the version output.
- Expand the step that runs npm stage publish.
You will see that the staging command completed successfully.
- Confirm the overall stage job displays a green success check.
That green run proves your release boundary works. Automation created staged 0.1.1 while 0.1.0 remained live.
What Did the Green Run Prove?
The npm stage publish command uploaded 0.1.1 to npm staging. The workflow contains no approval step.
Version 0.1.0 stays available to package users until a maintainer reviews the staged release.
Seeing a Failed Workflow Run?
- If dependency installation fails, confirm the repository contains the package lockfile used by npm ci.
- If staging authentication fails, confirm the repository secret is named exactly NPM_STAGE_TOKEN.
- If npm rejects the package scope, confirm the granular token is scoped to the same package as the repository.
Get help reading the failed step without exposing the secret: Help me diagnose my failed staged publishing workflow.
Your workflow has staged 0.1.1 behind a review gate. Next, you will inspect the staged version beside the live 0.1.0 release.
Review the Staged Version
Your GitHub Actions run has successfully handed version 0.1.1 to npm. A green run proves that automation reached staging.
The release gate matters only if the public package stays on 0.1.0. The CI-created 0.1.1 must wait for a human decision.
In this step, get ready to:
- Find version 0.1.1 in the staged package queue.
- Review the package details prepared by your workflow.
- Confirm version 0.1.0 remains live.
Open the staged package queue
Staged publishing holds a package version outside the live registry until a maintainer approves it. The staged package queue gives you a dedicated place to review that pending release.
- Open a new browser tab.
- Go to npmjs.com.
- Open the Staged Packages tab.
- Select @YOUR_NPM_USERNAME/review-gated-package from the staged package list.
There it is. Your workflow created a reviewable release without changing the public package.
Can't find the staged package?
- Refresh the staged package queue.
- Confirm you are signed in with the npm account that maintains @YOUR_NPM_USERNAME/review-gated-package.
- Switch back to the GitHub Actions run from earlier to confirm it completed successfully.
Help me find my staged npm package.
Review the staged version
A staged release is the point where automation stops. Its details show whether CI prepared the intended package version.
- Confirm the staged entry names @YOUR_NPM_USERNAME/review-gated-package.
- Confirm the entry identifies version 0.1.1.
- Confirm version 0.1.1 is awaiting manual approval.
- Leave version 0.1.1 in staging.
The staged entry matches the patch version created by your workflow. The release remains unavailable to normal npm installs.
Why Staging Changes the Risk
The NPM_STAGE_TOKEN can prepare a new package version for review. It cannot make that version live.
Manual promotion supplies the human checkpoint protected by two-factor authentication. A leaked workflow token cannot cross that release boundary by itself.
Confirm the live version stays unchanged
The package page shows what normal npm users can currently install. Its version history also shows the pending release visible to maintainers.
- Search for @YOUR_NPM_USERNAME/review-gated-package using npm's search field.
- Select @YOUR_NPM_USERNAME/review-gated-package from the search results.
Before you compare both views, which version do you expect npm to offer to normal installs?
- Read the current version shown on the package page.
- Open the Versions tab.
- Locate version 0.1.1 in the version history.
You'll see 0.1.0 as the live version. You'll see 0.1.1 still staged.
You have now proved that the release gate works. Version 0.1.1 is not yet available to normal npm installs.
Versions Don't Show the Expected Split?
- Refresh the package page.
- Confirm you are viewing @YOUR_NPM_USERNAME/review-gated-package.
- Return to the Staged Packages tab to verify version 0.1.1 remains in the queue.
Help me verify my npm version states.
Your release gate is doing its job. Next, you will promote the reviewed version by hand.
Promote and Verify the Release
You proved that the workflow can prepare version 0.1.1 without changing the live 0.1.0 release. The last gap is the human decision that lets users receive it.
In this step, you'll promote the staged version through npm. A clean installation then proves that normal consumers receive version 0.1.1.
In this step, get ready to:
- Promote staged version 0.1.1 with human approval.
- Install the package in a fresh test folder.
- Confirm that npm resolves live version 0.1.1.
Promote the staged version
Staged publishing places a human-controlled boundary between automation and a public release. Approval moves the reviewed package from staging to the live registry.
Approval requires two-factor authentication (2FA). This security check confirms that a maintainer is present for the release.
- Switch back to the npm package management page from earlier.
- Select the Staged Packages tab.
- Locate version 0.1.1.
- Click Approve for version 0.1.1.
- Complete the two-factor authentication prompt using your configured method.
Why does approval require 2FA?
The workflow can stage a release without a human present. The approval step requires a maintainer to authenticate before npm publishes the version.
A compromised workflow can prepare another version for review. It cannot cross this human approval gate by itself.
The registry may take a few minutes to finish processing the promoted version. A short wait means npm is preparing the release for normal installs.
- Return to the package page.
- Refresh the page.
You'll see version 0.1.1 as the live release. Version 0.1.0 remains available in the package history.
Still see version 0.1.1 in staging?
- Confirm that you completed the two-factor authentication prompt after clicking Approve.
- Refresh the package page after npm finishes processing the release.
- Check that you approved version 0.1.1 for @YOUR_NPM_USERNAME/review-gated-package.
Help me troubleshoot a staged npm version that remains pending after approval.
Create a fresh test folder
A fresh folder gives the installation the same starting point as a new consumer. Local files from the package project cannot influence this check.
- Press Cmd+Space on macOS or the Windows key on Windows to open system search.
- Type Terminal on macOS or PowerShell on Windows.
- Press Enter.
- Move to your Desktop by running this command:
cd ~/Desktop
What does this command do?
The cd command moves your terminal to the Desktop. This keeps the test folder easy to find.
- Create the fresh test folder by running these commands:
mkdir ~/Desktop/npm-release-check
cd ~/Desktop/npm-release-check
What do these commands do?
- The first command creates npm-release-check on your Desktop.
- The second command moves your terminal into that folder.
- Confirm that your terminal is inside the fresh folder by running this command:
pwd
What does this command do?
The pwd command prints the folder your terminal is currently using. This confirms where npm creates the installation files.
You'll see a path ending in Desktop/npm-release-check.
Don't see the test folder path?
- Check that the folder name is exactly npm-release-check.
- Run the folder creation commands again if the terminal reports that the folder does not exist.
- Confirm that pwd ends with the test folder name before continuing.
Help me get my terminal into the npm-release-check folder.
Install and verify the live release
A standard install asks the live registry for the package version available to consumers. Successful installation from this clean folder proves that promotion changed the public release.
- Install the package in the fresh folder by running this command:
npm install @YOUR_NPM_USERNAME/review-gated-package
What does this command do?
The command requests @YOUR_NPM_USERNAME/review-gated-package from the live npm registry. npm stores the installed package inside the fresh folder.
The stage-only token is not involved in this consumer installation. The command can access only the version that passed the approval gate.
You'll see npm report a successful installation. The fresh folder now contains the live package.
Package installation failed?
- Confirm that the package name includes your npm username in place of YOUR_NPM_USERNAME.
- Check the npm package page to confirm version 0.1.1 has finished processing.
- Confirm that your terminal is still inside npm-release-check.
Help me troubleshoot the fresh npm package installation.
Before you check, which version should appear in the installed dependency tree?
- Display the installed package version by running this command:
npm ls @YOUR_NPM_USERNAME/review-gated-package
What does this command do?
The npm ls command prints the installed dependency tree for the named package. The version beside the package name is the release that a normal installation received.
You'll see @YOUR_NPM_USERNAME/review-gated-package@0.1.1 in the dependency tree. This proves that the reviewed version is live and installable.
See a different installed version?
- Confirm that you ran the check inside npm-release-check.
- Check that version 0.1.1 appears as live on the npm package page.
- Remove the test folder after confirming the release status.
- Repeat the fresh-folder installation once npm finishes processing version 0.1.1.
Help me understand why npm installed a different package version.
You have closed the release loop: normal npm installs now receive version 0.1.1 after human review.
Your GitHub Actions workflow remains ready to stage the next reviewed release. The NPM_STAGE_TOKEN remains configured with stage-only access.
Secret mission
Audit Your Release Tokens
Audit every npm credential that can reach your package. Remove obsolete direct-publish access. Keep the stage-only workflow ready for reviewed releases.
Clean Up Your Resources
Clean Up Your Resources
Your reviewed npm release setup has no ongoing project cost. Choose whether to keep it ready, pause staged releases, or remove the automation and credentials.
The live package remains available on npm under @YOUR_NPM_USERNAME/review-gated-package. Its published versions 0.1.0 and 0.1.1 stay in the package history.
Resources you used:
- The granular npm access token scoped to @YOUR_NPM_USERNAME/review-gated-package with read and write access plus stage-only publishing permission.
- The GitHub Actions repository secret named NPM_STAGE_TOKEN.
- The .github/workflows/stage-publish.yml workflow file that stages a patch version after each push.
- The fresh npm install test folder on your machine.
Keep everything running
No action is needed for the reviewed release path. Choose this if you plan to keep staging versions for manual promotion.
The stage-only token is worth keeping because it cannot directly publish a live version. Removing an older direct-publish token closes any bypass around your review step.
- Keep .github/workflows/stage-publish.yml in the repository.
- Keep the NPM_STAGE_TOKEN repository secret configured.
- Keep the granular npm token active for future staged releases.
- Review the token list in your npm account for any older token scoped to @YOUR_NPM_USERNAME/review-gated-package.
- Revoke every older token that can publish directly.
Pause - I'll come back to this later
Pause future staged releases without deleting the workflow or its credentials. You can enable the same workflow when you are ready to continue.
- Open the GitHub Actions area of the repository that contains .github/workflows/stage-publish.yml.
- Select the workflow associated with .github/workflows/stage-publish.yml.
- Disable the workflow from its management controls.
Future pushes no longer trigger staged publication. The workflow file, repository secret, and stage-only npm token remain available for your return.
- Return to the workflow management controls when you want to resume releases.
- Enable the workflow to restore staging on each push.
Delete - I don't want to use this again
Remove the release automation, its credentials, and the local test folder. Your promoted package remains live on npm.
Removing these items feels permanent because the token cannot be recovered. Existing installs of version 0.1.1 continue to work.
- Open the access token area in your npm account settings.
- Open the list of granular access tokens.
- Revoke the token scoped to @YOUR_NPM_USERNAME/review-gated-package with stage-only publishing permission.
- Open the repository settings page for GitHub Actions secrets.
- Open the repository secret named NPM_STAGE_TOKEN.
- Delete the NPM_STAGE_TOKEN repository secret.
The registry credential path is now closed. Removing the workflow next prevents future pushes from attempting staged publication.
- Open .github/workflows/stage-publish.yml in the repository file browser.
- Delete .github/workflows/stage-publish.yml using the repository file controls.
- Commit the workflow deletion to the repository.
- Locate the fresh npm install test folder in Finder on macOS or File Explorer on Windows.
- Move the fresh npm install test folder to the Trash on macOS or the Recycle Bin on Windows.
Cleanup complete. Future pushes can no longer stage a package version through this workflow.
Nice Work!
Nice Work!
You did it! Version 0.1.1 of @YOUR_NPM_USERNAME/review-gated-package is live after passing through your staged review gate.
You've learned how to:
- Publish a scoped npm package by hand. Verify its live version on the npm registry.
- Protect CI publishing credentials with a granular stage-only token scoped to one package. Store it as the NPM_STAGE_TOKEN repository secret.
- Use GitHub Actions to stage version 0.1.1 automatically. Promote the reviewed version by hand before confirming it through a fresh install.
- Secret Mission: Extend this reviewed-release pipeline with an optional challenge that pushes your skills further.
Ready to quiz yourself?