Node Scripts

node-scripts@1.0.0 Template

Install dependencies and run npm scripts in order - the usual lint, typecheck and test job.

Start from it

flightstack template use node-scripts

What it does

Install dependencies with the package manager the repo already uses, then run npm scripts in order, stopping at the first one that fails.

Supports npm, pnpm, yarn and bun, and installs lockfile-faithfully by default.

Inputs

scripts array required
npm script names to run, in order. Each must exist in package.json. The job stops at the first failure.
workingDir string default .
Directory holding package.json. For a workspace monorepo this is the REPO ROOT, not the app.
packageManager auto | npm | pnpm | yarn | bun default auto
Which package manager to use. auto picks the one whose lockfile is committed.
install boolean default true
Install dependencies first. Leave on: a job gets a fresh workspace, so there is nothing in node_modules to reuse.
frozenLockfile boolean default true
Install exactly what the lockfile says and fail if it is out of date (npm ci).
env object
Extra environment variables for the scripts.

Definition

name: Node Scripts
description: >-
  Install dependencies and run one or more npm scripts in order - the usual
  lint, typecheck and test job.

triggers:
  - type: push
    branches: [main]

jobs:
  checks:
    name: Lint and test
    type: plugin/node-scripts
    with:
      workingDir: .
      scripts:
        - lint
        - test

plugin:
  name: node-scripts
  displayName: Node Scripts
  description: >-
    Install dependencies with the package manager the repo already uses, then
    run npm scripts in order, stopping at the first one that fails.
  category: quality

  requiredTools:
    - name: nodejs
      version: ">=20.0.0"

  supportedPlatforms:
    - linux
    - macos
    - windows

  parameters:
    type: object
    properties:
      scripts:
        type: array
        description: >-
          npm script names to run, in order. Each must exist in package.json.
          The job stops at the first failure.
      workingDir:
        type: string
        default: "."
        description: >-
          Directory holding package.json. For a workspace monorepo this is the
          REPO ROOT, not the app.
      packageManager:
        type: string
        enum: [auto, npm, pnpm, yarn, bun]
        default: auto
        description: >-
          Which package manager to use. `auto` picks the one whose lockfile is
          committed.
      install:
        type: boolean
        default: true
        description: >-
          Install dependencies first. Leave on: a job gets a fresh workspace,
          so there is nothing in node_modules to reuse.
      frozenLockfile:
        type: boolean
        default: true
        description: >-
          Install exactly what the lockfile says and fail if it is out of date
          (`npm ci`).
      env:
        type: object
        description: Extra environment variables for the scripts.
    required: [scripts]

  script: |
    set -euo pipefail
    cd "{{workingDir}}"

    pm="{{packageManager}}"
    if [ "$pm" = "auto" ]; then
      if [ -f pnpm-lock.yaml ]; then pm=pnpm
      elif [ -f yarn.lock ]; then pm=yarn
      elif [ -f bun.lockb ] || [ -f bun.lock ]; then pm=bun
      else pm=npm
      fi
    fi
    echo "package manager: $pm"

    case "$pm" in
      pnpm|yarn) corepack enable >/dev/null 2>&1 || true ;;
    esac

    {{#install}}
    echo "--- installing dependencies"
    case "$pm" in
      npm)
        if [ "{{frozenLockfile}}" = "true" ] && [ -f package-lock.json ]; then
          npm ci
        else
          npm install
        fi
        ;;
      pnpm)
        if [ "{{frozenLockfile}}" = "true" ]; then pnpm install --frozen-lockfile; else pnpm install; fi
        ;;
      yarn)
        if [ "{{frozenLockfile}}" = "true" ]; then
          yarn install --immutable || yarn install --frozen-lockfile
        else
          yarn install
        fi
        ;;
      bun)
        if [ "{{frozenLockfile}}" = "true" ]; then bun install --frozen-lockfile; else bun install; fi
        ;;
    esac
    {{/install}}

    {{#each env}}
    export {{@key}}="{{this}}"
    {{/each}}

    {{#each scripts}}
    echo "--- $pm run {{this}}"
    "$pm" run "{{this}}"
    {{/each}}