Skip to main content
Fleetshift’s npm-package shift type lets you write a deterministic shift as a standard npm package. You publish a Node.js CLI to your Portal instance’s private registry and select it in the fleetshift wizard. This is useful when you want the shift logic to live in your own repository, go through your normal code review process, and be pinned to an exact version. Each change to the shift is a reviewed PR, and each deployment is an npm publish.

Writing a shift package

A shift package is a regular npm package with a bin entry. When fleetshift runs your shift against a target repository, it:
  1. Clones the target repository into a working directory.
  2. Sets process.cwd() to the cloned repo.
  3. Runs your binary.
Your binary modifies files in the working directory and exits. Fleetshift handles the git diff, branch creation, and pull request.

Minimal example

Directory structure:
package.json:
bin/my-shift:
Make the binary executable: chmod +x bin/my-shift

Package naming rules

  • All packages must use the @fleetshift/ scope: @fleetshift/my-shift
  • The unscoped part must be lowercase and can only contain letters, digits, ., _, -
  • No protocol or path specifiers (github:, https://, file:)

Exit codes

Publishing to your Portal registry

Portal exposes an npm registry proxy that your shift packages are published through. This works the same way as publishing custom plugins — you use your existing Backstage service token to authenticate.

Step 1: Configure npm authentication

Add an .npmrc file to your shift repository (or your home directory):
Replace <your-portal-host> with your Portal instance’s hostname (for example, my-company.spotifyportal.com). The first line tells npm to route @fleetshift/* packages to your Portal registry. Without it, npm uses the default registry and authentication will fail. To create your publish token:
  1. Generate a secure random token string (e.g. openssl rand -base64 32).
  2. In your Portal instance, go to App Settings (/admin/app-settings).
  3. Under External Access, click Add Item.
  4. Set type static, subject fleetshift-npm-registry, access restriction plugin fleetshift, and paste your generated token.
  5. Save. Use the same token value in your .npmrc above.

Step 2: Publish

No --registry flag is needed — the .npmrc scope line handles routing.

Publishing from CI

For automated publishing, store the service token as a CI secret. Example with GitHub Actions:

Creating a shift in the wizard

  1. Open Fleetshift in your Portal sidebar.
  2. Click New Shift and select npm Package.
  3. Enter the package name (for example, @fleetshift/my-shift).
  4. Pick a version to pin. Only exact versions are accepted — no ranges like ^1.0.0 or ~1.0.0.
  5. Optionally specify a custom bin name. Defaults to the unscoped package name (for example, my-shift for @fleetshift/my-shift).
  6. Optionally add arguments to pass to the binary.
  7. Configure targets, PR template, and other settings as usual.
  8. Click Create.

Updating a shift version

To roll out a new version of your shift logic:
  1. Make your changes and bump the version in package.json.
  2. Open a PR in your shift repository and get it reviewed.
  3. Merge and publish the new version.
  4. In Fleetshift, edit the shift and update the pinned version.

Sandbox constraints

npm package shifts run inside a locked-down container. Keep these restrictions in mind when writing your binary.

A note on dependencies

Since lifecycle scripts are disabled, stick to pure JavaScript or TypeScript dependencies.