Search code examples
gitlab-cipnpm

Use pnpm in diferent Gitlab CI stages


I'm struggling with Gitlab CI and pnpm. I have a simple pipeline with npm, two stages, install and test, using cache:

stages:
  - install
  - test

install:
  stage: install
  tags:
      - node:LTS
  script:
    - npm install
  cache:
    key: node_modules
    paths:
      - node_modules
  only:
    - develop

test:
  stage: test
  tags:
      - node:LTS
  cache:
    key: node_modules
    paths:
      - node_modules
    policy: pull
  coverage: /All files[^|]*\|[^|]*\s+([\d\.]+)/
  dependencies:
    - install
  script:
    - npm run test:ci
  only:
    - develop
  artifacts:
    when: always
    reports:
      junit: coverage/junit-report.xml
      coverage_report: 
        coverage_format: cobertura
        path: coverage/coverage-final.json

This works perfectly fine, and I want to take advantage of pnpm and start using it. According to the docs, I modified my code as follows:

install:
  stage: install
  tags:
      - node:LTS
  before_script:
    - corepack enable
    - corepack prepare pnpm@latest-7 --activate
    - pnpm config set store-dir .pnpm-store
  script:
    - pnpm install # install dependencies
  cache:
    key:
      files:
        - pnpm-lock.yaml
    paths:
      - .pnpm-store
  only:
    - develop
    - /\d+\.\d+\.\d+$/

test:
  stage: test
  tags:
      - node:LTS
  coverage: /All files[^|]*\|[^|]*\s+([\d\.]+)/
  dependencies:
    - install
  script:
    - pnpm test:ci
  only:
    - develop
  artifacts:
    when: always
    reports:
      junit: coverage/junit-report.xml
      coverage_report: 
        coverage_format: cobertura
        path: coverage/coverage-final.json

As you can imagine, it doens't work. In test stage, I get this error:

$ pnpm test:ci
/bin/bash: line 140: pnpm: command not found

Do I have to add the before_script in every stage whereI want to use pnpm? I saw many examples on the internet, one of them Here, but I don't know if I have to add this

default:
  image: node:lts-alpine
  cache: &cache
    key: "$CI_COMMIT_REF_SLUG"
    paths:
      - .pnpm-store
      - ./node_modules
      - apps/web/node_modules
    policy: pull


before_script:
  - npm i -g pnpm
  - pnpm config set store-dir .pnpm-store

Any help would be appreciated


Solution

  • We have pnpm running in our Gitlab CI pipelines. What we do is run before_script and add pnpm to every task. I'm not sure if it's the best way to go about it, but it works. My guess is that since each job/task runs in isolation, it doesn't know aobut the previous task's installation of pnpm. It can access the cache though because you instruct it to, but that doesn't mean that the pnpm CLI is installed.

    Taking our configuration and applying it to your example would be as below.

    Two things to add:

    1. before_script to install pnpm CLI to this runner instance
    2. cache to utilize the cache you have populated in install step
    install:
      stage: install
      tags:
          - node:LTS
      before_script:
        - corepack enable
        - corepack prepare pnpm@latest-7 --activate
        - pnpm config set store-dir .pnpm-store
      script:
        - pnpm install # install dependencies
      cache:
        key:
          files:
            - pnpm-lock.yaml
        paths:
          - .pnpm-store
      only:
        - develop
        - /\d+\.\d+\.\d+$/
    
    test:
      stage: test
      tags:
          - node:LTS
      coverage: /All files[^|]*\|[^|]*\s+([\d\.]+)/
      dependencies: # this one we don't have, not sure if you need to keep it?
        - install
      before_script: # add this
        - corepack enable
        - corepack prepare pnpm@latest-7 --activate
        - pnpm config set store-dir .pnpm-store
      cache: # tell Gitlab to pull from cache
        - key:
              files:
                  - pnpm-lock.yaml
              prefix: pnpm-cache
          paths:
              - .pnpm-cache
          policy: pull
      script:
        - pnpm test:ci
      only:
        - develop
      artifacts:
        when: always
        reports:
          junit: coverage/junit-report.xml
          coverage_report: 
            coverage_format: cobertura
            path: coverage/coverage-final.json