Guide: Npm

Automate based on a npm package

npm

Goal

The purpose of this pipeline is to track one npm dependency update, and then update both the package.json and package-lock.json in case of a version change.

Requirement

This guide requires:

  1. updatecli

  2. npm

  3. IDE

  4. GitHub Personal Access Token

updatecli

Updatecli is a declarative dependency management tool. The application is available as a command line compatible with Linux/macOS/Windows. Updatecli is designed to work the same way, both from a local machine and a CI environment.

It can easily be installed using Homebrew by running the two following commands:

-> brew tap updatecli/updatecli
-> brew install updatecli

Additional installation instructions are available at www.updatecli.io/docs/prologue/installation.

IDE

The best way to write Updatecli manifest(s) is by using an IDE compatible with jsonschema hosted on schemastore.org, such as Vscode, Intellij, or Neovim. The full list of compatible IDE is available on www.schemastore.org.

For the IDE to load the correct Updatecli jsonschema, Updatecli manifest must have both a parent directory named "updatecli.d" and one of the file extension ".yaml", or ".yml". This provides auto-completion and validation out of the box.

For example, from VScode, typing [ctrl][space] should display a box with various suggestions

npm

npm is a package manager for the Javascript programming language.

GitHub PAT

The GitHub Personal Access Token is the token used to interact with the GitHub API Documentation

Pipeline

Description

Updatecli relies on one or multiple pipeline manifests to describe the expected Update pipeline. In this guide, we use the two following components

  1. A source of kind npm to monitor the npm dependency

  2. A target of kind shell to run a command for updating both the 'package-lock.json' and 'package.json'

#package.json
{
  "name": "guide-npm",
  "version": "1.0.0",
  "description": "An Updatecli guide for npm project",
  "author": "Olivier Vernin",
  "dependencies": {
    "axios": "^1.6.8"
  }
}

Manifest

#updatecli.d/manifest.yaml
name: npm manifest guide

sources:
  npm:
    name: Get latest axios version
    kind: npm
    spec:
      name: axios
      versionfilter:
        kind: semver
        pattern: ^1.0.0

targets:
  npn:
    name: Ensure package.json and package-lock.json is up to date
    kind: shell

    # The default behavior for a target is to have one of its spec fields defaulting to the source resource output.
    #
    # More specifically for a resource of kind "shell", updatecli would append the value after the command such as
    # `npm install --package-lock-only --dry-run=$DRY_RUN axios@ 1.0.0`
    # Please note the space between axios@ and 1.0.0
    #
    # In this context, it doesn't work as the npm command requires axios@1.0.0 to be attached without a space
    #
    # Therefore we disable the default source output by using the parameter "disablesourceinput: true"
    # And then we use the Updatecli specific templating function {{ source "<sourceID>" }}
    disablesourceinput: true

    # scmid binds a target with a scm configuration.
    # Updatecli clones the git repository in a temporary location, then updates it
    # according to the current declarative pipeline.
    scmid: default

    # Spec contains the specific parameter for a specific kind of resource which in this case is the "shell" resource
    spec:

      # The DRY_RUN environment variable is set and used by Updatecli to identify:
      #   1. If we are in "dry-run" mode by running `updatecli diff --config manifest.yaml`
      #   2. If we are in "apply" mode by running `updatecli apply --config manifest.yaml`
      command: npm install --package-lock-only --dry-run=$DRY_RUN axios@{{ source "npm" }}

      # By default, shell command only have access to the DRY_RUN environment variable.
      # But in this situation, we would also need the PATH value to identify where the npm command is located.
      #
      # As the PATH environment value is not defined it inherits its value from the Updatecli process.
      environments:
        - name: PATH

      # changedif defines how Updatecli should interpret a failure or a change.
      # In this case we use the "file/checksum" changedif kind.
      # A filechecksum change would report a change.
      changedif:
        kind: file/checksum
        spec:
          files:
            - package-lock.json
            - package.json

      # npm expects to run the command from the directory containing the package.json
      # workdir allows to specify the path where to run the command.
      # If the resource has a scmid, then the workdir relative path is from the cloned scm directory
      # in the temporary directory such as /tmp/updatecli on POSIX system.
      workdir: "assets/code_example/docs/guides/npm/"

# scms defines the git repository configuration used by the target and the action.
# Updatecli will clone that repository in the OS temporary location such as /tmp on Darwin or Linux system.
scms:
  default:
    kind: github
    spec:
      owner: updatecli
      repository: website
      # To handle secrets, Updatecli can either use environment variable or sops secrets.
      # When executed from GitHub Action, using GITHUB_TOKEN and GITHUB_ACTOR is quite convenient.
      token: '{{ requiredEnv "GITHUB_TOKEN" }}'
      username: '{{ requiredEnv "GITHUB_ACTOR" }}'
      branch: master

# actions are actions to execute if the state of a binded target is changed.
# Ex: opening a pullrequest.
actions:
  default:
    # The github/pullrequest means Updatecli will create a temporary branch containing all the changes
    # generated by the different targets using the same scmid.
    #
    # Then if there is a change, it will opens a pull request targeting the scm branch referenced by scmid.
    kind: github/pullrequest
    scmid: default
    spec:
      labels:
        - dependencies
      automerge: true
      usetitleforautomerge: true
      mergemethod: squash

Then you can run:

export UPDATECLI_GITHUB_TOKEN=<your_PAT>
export UPDATECLI_GITHUB_ACTOR=<your GH username>
updatecli diff --config updatecli.d/manifest.yaml`

Going further

Once you’re happy with the Update pipeline, you can leverage CI environment to run it regularly. You’ll need Updatecli installed in your CI environment, and the right credentials. More information in the corresponding GitHub Action documentation

This guide demonstrated a simple update pipeline, but real-world situations usually require either updating all dependencies specified in a package.json, or updating additional resources such as documentation, CI environment, etc.

In the case of updating all dependencies from a package.json at once, the Autodiscovery feature is our current experimentation for addressing the problem. Feel free to reach out as we are still shaping this feature. To see what it looks like, you can run updatecli diff --experimental from a repository containing package.json

In the situation of a more tailored update scenario, you may need to extend the current pipeline using additional resources such as:

Dockerfile Adding a target of kind dockerfile, Updatecli could update the npm dependency used within a Dockerfile as part of the same operation.

Yaml Adding a target of kind yaml, Updatecli could also update the npm dependency used in any yaml as part of the same operation.

Feel free to chat on the Updatecli Matrix channel.

Top