Skip to content
Snippets Groups Projects
Select Git revision
  • master default protected
  • 4
  • 4.2
  • 4.2.2
  • 4.2.1
  • 4.2.0
  • 4.1
  • 4.1.1
  • 4.1.0
  • 4.0.3
  • 4.0.2
  • 4.0
  • 4.0.1
  • 4.0.0
14 results

node

  • Clone with SSH
  • Clone with HTTPS
  • user avatar
    to be continuous bot authored
    chore(deps): update dependency to-be-continuous/semantic-release to v3.13
    
    See merge request to-be-continuous/node!82
    9d7c384d
    History

    GitLab CI template for Node.js

    This project implements a GitLab CI/CD template to build, test and analyse your JavaScript/TypeScript/Node.js projects.

    More precisely, it can be used by all projects based on npm, yarn or pnpm package managers.

    Usage

    This template can be used both as a CI/CD component or using the legacy include:project syntax.

    Use as a CI/CD component

    Add the following to your .gitlab-ci.yml:

    include:
      # 1: include the component
      - component: $CI_SERVER_FQDN/to-be-continuous/node/gitlab-ci-node@4.2.1
        # 2: set/override component inputs
        inputs:
          image: "registry.hub.docker.com/library/node:20" # ⚠ this is only an example
          lint-enabled: "true"

    Use as a CI/CD template (legacy)

    Add the following to your .gitlab-ci.yml:

    include:
      # 1: include the template
      - project: "to-be-continuous/node"
        ref: "4.2.1"
        file: "/templates/gitlab-ci-node.yml"
    
    variables:
      # 2: set/override template variables
      NODE_IMAGE: "registry.hub.docker.com/library/node:20" # ⚠ this is only an example
      NODE_LINT_ENABLED: "true"

    Global configuration

    The Node.js template uses some global configuration used throughout all jobs.

    Input / Variable Description Default value
    image / NODE_IMAGE The Docker image used to run Node.js
    ⚠️ set the version required by your project
    registry.hub.docker.com/library/node:lts-alpine
    manager / NODE_MANAGER The package manager used by your project (one of npm, yarn or pnpm)
    If undefined, automatic detection
    none (auto)
    config-registry / NODE_CONFIG_REGISTRY Main npm registry to use none
    config-scoped-registries / NODE_CONFIG_SCOPED_REGISTRIES Space separated list of npm scoped registries (formatted as @somescope:https://some.npm.registry/some/repo @anotherscope:https://another.npm.registry/another/repo) none
    project-dir / NODE_PROJECT_DIR Node project root directory .
    source-dir / NODE_SOURCE_DIR Sources directory src
    install-extra-opts / NODE_INSTALL_EXTRA_OPTS Extra options to install project dependencies (either npm ci, yarn install or pnpm install) none

    Using scoped registries

    Scoped registries allow to pull and publish packages using multiple registries.

    Examples:

    • npm install foo installs foo package from https://www.npmjs.com/ by default,
    • npm install @angular/core installs @angular/core package from https://www.npmjs.com/ if no npm registry associated to scope @angular is declared,
    • npm install @acme-corp/bar installs @acme-corp/bar package from https://registry.acme.corp/npm if this registry url is associated to scope @acme-corp.

    First of all, be aware that the Node.js template automatically configures the GitLab's project-level npm packages registry associated to a scope corresponding to the root of the project (ex: project https://gitlab.example.com/my-org/engineering-group/team-amazing/analytics will have GitLab's project-level npm packages registry scope @my-org). Therefore, GitLab's project-level npm packages registry can freely be used both to install packages (with the right scope) or even to publish your own packages.

    You may configure additional scoped registries with the $NODE_CONFIG_SCOPED_REGISTRIES variable. The value is expected as a (whitespace-separated) list of @registry-scope:registry-url.

    The Node.js template also supports authentication for each, simply by defining the appropriate variable (as project or group secret variables) depending on the desired authentication method:

    • NODE_REGISTRY_<SCOPE>_AUTH_TOKEN: authentication token
    • NODE_REGISTRY_<SCOPE>_AUTH_BASIC: base64 authentication string (base64(username + ':' + password))

    ⚠️ The <SCOPE> part is the registry-scope transformed in SCREAMING_SNAKE_CASE (uppercase words separated by underscores).

    Example:

    variables:
      NODE_CONFIG_SCOPED_REGISTRIES: "@public-repo:https://public.npm.registry/some/repo @my-priv-repo:https://private.npm.registry/another/repo"
      # NODE_REGISTRY_MY_PRIV_REPO_AUTH set as a project secret variables

    Jobs

    node-lint job

    The Node template features a node-lint job that performs a code analysis with ESLint. This job is disabled by default. It can be activated by setting NODE_LINT_ENABLED.

    It is bound to the build stage, and uses the following variable:

    Input / Variable Description Default value
    lint-enabled / NODE_LINT_ENABLED Set to true to enable lint analysis none (disabled)
    lint-args / NODE_LINT_ARGS npm run script arguments to execute the lint analysis
    yarn run script arguments to execute the lint analysis
    pnpm run script arguments to execute the lint analysis
    run lint

    In addition to a textual report in the console, this job produces the following reports, kept for one day:

    Report Format Usage
    $NODE_PROJECT_DIR/reports/node-lint.gitlab.json GitLab GitLab integration
    $NODE_PROJECT_DIR/reports/node-lint.xslint.json JSON ESLint SonarQube integration
    Report Format Usage
    $NODE_PROJECT_DIR/reports/npm-audit.native.json JSON DefectDojo integration
    This report is generated only if DefectDojo template is detected, if needed, you can force it with $DEFECTDOJO_NPMAUDIT_REPORTS

    node-build job

    The Node template features a job node-build that performs build and tests all at once. You can disable the build using the variable NODE_BUILD_DISABLED

    Those stages are performed in a single job for optimization purpose (it saves time) and also for jobs dependency reasons (some jobs such as SONAR analysis have a dependency on test results).

    This job is bound to the build stage, and uses the following variables:

    Input / Variable Description Default value
    build-disabled / NODE_BUILD_DISABLED Set to true to disable build none (enabled)
    build-dir / NODE_BUILD_DIR Variable to define build directory dist
    build-args / NODE_BUILD_ARGS npm run script arguments
    yarn run script arguments
    pnpm run script arguments
    ⚠️ default value should be overridden for pnpm as --prod is not a valid option.
    run build --prod
    test-args / NODE_TEST_ARGS npm test arguments
    yarn test arguments
    pnpm test arguments
    test -- --coverage

    Unit Tests and Code Coverage reports

    This chapter details the required configuration (depending on the unit testing framework you're using) in order to integrate your unit tests reports and code coverage reports to GitLab.

    Additionally, if also using SonarQube, you'll have to enable some extra reporters.

    Unit testing with Jest

    Here is the required configuration if you're using Jest as unit testing framework.

    Reporter Needs npm install Expected report file Usage
    jest-junit Yes reports/node-test.xunit.xml GitLab unit tests integration (JUnit format)
    istanbul text No N/A (stdout) GitLab MR test coverage results (GitLab grabs coverage from stdout)
    istanbul cobertura No reports/cobertura-coverage.xml GitLab code coverage integration (Cobertura format)
    jest-sonar Yes reports/node-test.sonar.xml SonarQube unit tests integration (generic SonarQube format)
    istanbul lcovonly No reports/lcov.info SonarQube code coverage integration (JS/TS LCOV format)

    Here is an example of a jest.config.js configuration file with all the above reporters configured as expected:

      reporters: [
        "default",
        // 'jest-junit' to enable GitLab unit test report integration
        [
          "jest-junit",
          {
              outputDirectory: "reports",
              outputName: "node-test.xunit.xml",
          },
        ],
        // [OPTIONAL] only if using SonarQube
        // 'jest-sonar' to enable SonarQube unit test report integration
        [
          "jest-sonar",
          {
              outputDirectory: "reports",
              outputName: "node-test.sonar.xml",
          },
        ],
      ],
      coverageDirectory: "reports",
      coverageReporters: [
        // 'text' to let GitLab grab coverage from stdout
        "text",
        // 'cobertura' to enable GitLab test coverage visualization
        "cobertura",
        // [OPTIONAL] only if using SonarQube
        // 'lcovonly' to enable SonarQube test coverage reporting
        "lcovonly",
      ],

    Unit testing with Mocha

    Here is the required configuration if you're using Mocha as unit testing framework.

    Reporter Needs npm install Expected report file Usage
    mocha-junit-reporter Yes reports/node-test.xunit.xml GitLab unit tests integration (JUnit format)
    istanbul text Yes (in nyc package) N/A (stdout) GitLab MR test coverage results (GitLab grabs coverage from stdout)
    istanbul cobertura Yes (in nyc package) reports/cobertura-coverage.xml GitLab code coverage integration (Cobertura format)
    mocha-sonarqube-reporter Yes reports/node-test.sonar.xml SonarQube unit tests integration (generic SonarQube format)
    istanbul lcovonly Yes (in nyc package) reports/lcov.info SonarQube code coverage integration (JS/TS LCOV format)

    ⚠️ Remarks:

    1. By default - unlike Jest - Mocha doesn't provide code coverage. To do so you need to install Istanbul package (nyc):

      npm install --save-dev nyc
    2. the default xunit Mocha reporter doesn't produce a JUnit format supported by GitLab, that's why we recommend you to use mocha-junit-reporter instead.

    3. Mocha doesn't support multiple unit tests reporters. So unfortunaltely, if you're using SonarQube, you'll have to choose which report you want to generate. Another option is to use mocha-multi-reporters (see documentation)

    Mocha may be either configured with CLI options of using separate Mocha and nyc config files.

    Here is the required configuration with CLI options directly in the package.json file:

      "scripts": {
        "test": "npm run mocha",
        "mocha": "nyc --report-dir=reports --reporter=text --reporter=lcovonly --reporter=cobertura mocha --reporter mocha-junit-reporter --reporter-option mochaFile=reports/node-test.xunit.xml test/*.js",
        ...
      },
      ...

    Here is the equivalent using separate config files:

    • package.json:

        "scripts": {
          "test": "npm run mocha",
          "mocha": "nyc mocha test/*.js",
          ...
        },
        ...
    • .mocharc.json:

      1. with mocha-junit-reporter (for GitLab):

        {
          "reporter": "mocha-junit-reporter",
          "reporter-option": ["mochaFile=reports/node-test.xunit.xml"]
        }
      2. with mocha-sonarqube-reporter (for SonarQube):

        {
          "reporter": "mocha-sonarqube-reporter",
          "reporter-option": ["output=reports/node-test.sonar.xml"]
        }
      3. with both (using mocha-multi-reporters):

        {
          "reporter": "mocha-multi-reporters",
          "reporter-option": ["configFile=.mmr.json"]
        }

        With .mmr.json:

        {
          "reporterEnabled": "spec, mocha-junit-reporter, mocha-sonarqube-reporter",
          "mochaJunitReporterReporterOptions": {
            "mochaFile": "reports/node-test.xunit.xml"
          },
          "mochaSonarqubeReporterReporterOptions": {
            "output": "reports/node-test.sonar.xml"
          }
        }
    • .nycrc.json:

      {
        "reporter": ["text", "cobertura", "lcovonly"],
        "report-dir": "reports"
      }

    Unit testing with Jasmine

    Support of Jasmine as unit testing framework is not documented yet and will come soon in a further version of this template.

    SonarQube analysis

    If you're using the SonarQube template to analyse your Node code, here are 2 sample sonar-project.properties files.

    If using JavaScript language:

    # see: https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/test-coverage/javascript-typescript-test-coverage/
    # set your source directory(ies) here (relative to the sonar-project.properties file)
    sonar.sources=.
    # exclude unwanted directories and files from being analysed
    sonar.exclusions=node_modules/**,dist/**,**/*.test.js
    
    # set your tests directory(ies) here (relative to the sonar-project.properties file)
    sonar.tests=.
    sonar.test.inclusions=**/*.test.js
    
    # tests report: generic format
    sonar.testExecutionReportPaths=reports/node-test.sonar.xml
    # lint report: ESLint JSON
    sonar.eslint.reportPaths=reports/node-lint.xslint.json
    # coverage report: LCOV format
    sonar.javascript.lcov.reportPaths=reports/lcov.info

    If using TypeScript language:

    # see: https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/test-coverage/javascript-typescript-test-coverage/
    # set your source directory(ies) here (relative to the sonar-project.properties file)
    sonar.sources=src
    # exclude unwanted directories and files from being analysed
    sonar.exclusions=node_modules/**,dist/**,**/*.spec.ts
    
    # set your tests directory(ies) here (relative to the sonar-project.properties file)
    sonar.tests=src
    sonar.test.inclusions=**/*.spec.ts
    
    # tests report: generic format
    sonar.testExecutionReportPaths=reports/node-test.sonar.xml
    # lint report: TSLint JSON
    sonar.typescript.tslint.reportPaths=reports/node-lint.xslint.json
    # coverage report: LCOV format
    sonar.typescript.lcov.reportPaths=reports/lcov.info

    More info:

    node-audit job

    The Node template features a job node-audit that performs an audit (npm audit, yarn audit or pnpm audit) to find vulnerabilities (security).

    It is bound to the test stage.

    Input / Variable Description Default value
    audit-disabled / NODE_AUDIT_DISABLED Set to true to disable npm audit none (enabled)
    audit-args / NODE_AUDIT_ARGS npm audit arguments
    yarn audit arguments
    pnpm audit arguments
    --audit-level=low

    In addition to a textual report in the console, this job produces the following report, kept for one day and only available for download by users with the Developer role or higher:

    Report Format Usage
    $NODE_PROJECT_DIR/reports/npm-audit.native.json JSON DefectDojo integration
    This report is generated only if DefectDojo template is detected, if needed, you can force it with $DEFECTDOJO_NPMAUDIT_REPORTS

    node-outdated job

    The Node template features a job node-outdated that performs outdated analysis (npm outdated, yarn outdated or pnpm outdated to find dependencies that might be updated.

    It is bound to the test stage.

    Input / Variable Description Default value
    outdated-disabled / NODE_OUTDATED_DISABLED Set to true to disable npm outdated none (enabled)
    outdated-args / NODE_OUTDATED_ARGS npm outdated arguments
    yarn outdated arguments
    pnpm outdated arguments
    --long

    The job generates an outdated report that you will find here: NODE_PROJECT_DIR/reports/npm-outdated-report.json. This report is only available for download by users with the Developer role or higher

    node-semgrep job

    The Node template features a job node-semgrep that performs a Semgrep analysis.

    It is bound to the test stage, and uses the following variables:

    Input / Variable Description Default value
    semgrep-disabled / NODE_SEMGREP_DISABLED Set to true to disable this job none
    semgrep-image / NODE_SEMGREP_IMAGE The Docker image used to run Semgrep registry.hub.docker.com/semgrep/semgrep:latest
    semgrep-args / NODE_SEMGREP_ARGS Semgrep scan options --metrics off --disable-version-check --no-suppress-errors
    semgrep-rules / NODE_SEMGREP_RULES Space-separated list of Semgrep rules.
    Can be both local YAML files or remote rules from the Semgrep Registry (denoted by the p/ prefix).
    p/javascript p/eslint p/gitlab-eslint
    semgrep-registry-base-url / NODE_SEMGREP_REGISTRY_BASE_URL The Semgrep Registry base URL that is used to download the rules. No trailing slash. https://semgrep.dev/c
    semgrep-download-rules-enabled / NODE_SEMGREP_DOWNLOAD_RULES_ENABLED Download Semgrep remote rules true

    ℹ️ Semgrep may collect some metrics, especially when using rules from the Semgrep Registry. To protect your privacy and let you run Semgrep in air-gap environments, this template disables all Semgrep metrics by default:

    • rules from the Semgrep registry are pre-downloaded and passed to Semgrep as local rule files (can be disabled by setting semgrep-download-rules-enabled / NODE_SEMGREP_DOWNLOAD_RULES_ENABLED to false),
    • the --metrics option is set to off,
    • the --disable-version-check option is set.

    In addition to a textual report in the console, this job produces the following reports, kept for one week and only available for download by users with the Developer role or higher:

    Report Format Usage
    $NODE_PROJECT_DIR/reports/node-semgrep.gitlab.json GitLab's SAST format GitLab integration
    $NODE_PROJECT_DIR/reports/node-semgrep.native.json Semgrep's JSON format DefectDojo integration
    This report is generated only if DefectDojo template is detected

    node-sbom job

    This job generates a SBOM file listing installed packages using @cyclonedx/cyclonedx-npm.

    It is bound to the test stage, and uses the following variables:

    Input / Variable Description Default value
    sbom-disabled / NODE_SBOM_DISABLED Set to true to disable this job none
    TBC_SBOM_MODE Controls when SBOM reports are generated (onrelease: only on $INTEG_REF, $PROD_REF and $RELEASE_REF pipelines; always: any pipeline).
    ⚠️ sbom-disabled / NODE_SBOM_DISABLED takes precedence
    onrelease
    sbom-version / NODE_SBOM_VERSION The version of @cyclonedx/cyclonedx-npm used to emit SBOM none (uses latest)
    sbom-opts / NODE_SBOM_OPTS Options for @cyclonedx/cyclonedx-npm used for SBOM analysis --omit dev

    node-publish job

    This job publishes the project packages to a npm registry.

    This job is bound to the publish stage and is disabled by default. When enabled, it is executed on a Git tag with a semantic versioning pattern (v?[0-9]+\.[0-9]+\.[0-9]+, configurable).

    It uses the following variables:

    Input / Variable Description Default value
    publish-enabled / NODE_PUBLISH_ENABLED Set to true to enable the publish job none (disabled)
    publish-args / NODE_PUBLISH_ARGS npm publish extra arguments
    yarn publish extra arguments
    pnpm publish extra arguments
    none
    🔒 NODE_PUBLISH_TOKEN npm publication registry authentication token none

    Configure the target registry

    The target registry url for publication shall be configured in the publishConfig of your package.json file.
    If no registry is configured in publishConfig, it will publish to default target registry 'https://registry.npmjs.org/' only if access is set to 'public' in the publishConfig of your package.json file.
    Examples:

    • for an unscoped package:

      {
        "name": "my-package",
        // ...
        "publishConfig": {
          "registry": "https://registry.acme.corp/npm"
        }
        // ...
      }
    • for a scoped package:

      {
        "name": "@acme/my-package",
        // ...
        "publishConfig": {
          "@acme:registry": "https://registry.acme.corp/npm"
        }
        // ...
      }

    Then simply declare the registry authentication token with 🔒 NODE_PUBLISH_TOKEN.

    ℹ️ it is not mandatory to declare the registry if you wish to use the GitLab project-level npm packages registry (it is declared by default by the template, with the required credentials). All you have to do to is to make sure your npm package name uses the right scope. For example, if your project is https://gitlab.example.com/my-org/engineering-group/team-amazing/analytics, the root namespace is my-org, and your package name must have the @my-org scope (probable package fullname: @my-org/analytics).

    Exclude resources from package

    Don't forget to exclude undesired folders and files from the package resources (simply add them to your .gitignore or .npmignore file):

    • the .npm/, .yarn/ or .pnpm-store folder, that is used internally by the Node template to store npm, yarn or pnpm cache (depending on the package manager you're actually using),
    • the reports/ folder, that is used by most to be continuous to output all kind of reports,
    • the Node.js build output dir (if any),
    • any other undesired file & folder that you don't want to appear in your published package(s).

    Variants

    The Node template can be used in conjunction with template variants to cover specific cases.

    Vault variant

    This variant allows delegating your secrets management to a Vault server.

    Configuration

    In order to be able to communicate with the Vault server, the variant requires the additional configuration parameters:

    Input / Variable Description Default value
    TBC_VAULT_IMAGE The Vault Secrets Provider image to use (can be overridden) registry.gitlab.com/to-be-continuous/tools/vault-secrets-provider:latest
    vault-base-url / VAULT_BASE_URL The Vault server base API url must be defined
    vault-oidc-aud / VAULT_OIDC_AUD The aud claim for the JWT $CI_SERVER_URL
    🔒 VAULT_ROLE_ID The AppRole RoleID none
    🔒 VAULT_SECRET_ID The AppRole SecretID none

    By default, the variant will authentifacte using a JWT ID token. To use AppRole instead the VAULT_ROLE_ID and VAULT_SECRET_ID should be defined as secret project variables.

    Usage

    Then you may retrieve any of your secret(s) from Vault using the following syntax:

    @url@http://vault-secrets-provider/api/secrets/{secret_path}?field={field}

    With:

    Parameter Description
    secret_path (path parameter) this is your secret location in the Vault server
    field (query parameter) parameter to access a single basic field from the secret JSON payload

    Example

    include:
      # main template
      - component: $CI_SERVER_FQDN/to-be-continuous/node/gitlab-ci-node@4.2.1
      # Vault variant
      - component: $CI_SERVER_FQDN/to-be-continuous/node/gitlab-ci-node-vault@4.2.1
        inputs:
          # audience claim for JWT
          vault-oidc-aud: "https://vault.acme.host"
          vault-base-url: "https://vault.acme.host/v1"
    
    variables:
      NODE_CONFIG_SCOPED_REGISTRIES: "@public-repo:https://public.npm.registry/some/repo @my-priv-repo:https://private.npm.registry/another/repo"
      # retrieve private repo auth token from Vault
      NODE_REGISTRY_MY_PRIV_REPO_AUTH: "@url@http://vault-secrets-provider/api/secrets/b7ecb6ebabc231/node/priv-repo/creds?field=token"