|
| 1 | +# Routes npm package restore through the Central Feed Service (CFS), as required by |
| 2 | +# SFI Network Isolation. Consumed by every build pipeline in this directory. |
| 3 | +# |
| 4 | +# Pipelines must also include the companion variables template: |
| 5 | +# variables: |
| 6 | +# - template: /.azure-pipelines/npm-cfs-variables.yml@self |
| 7 | +# which declares the feed URL and the generated .npmrc path. The redirect itself is |
| 8 | +# carried by the npm_config_registry environment variable that template exports; see |
| 9 | +# its header for why the generated .npmrc alone is not enough. |
| 10 | +# |
| 11 | +# The .npmrc is generated at build time into the agent temp directory rather than |
| 12 | +# being committed to the repository, so that: |
| 13 | +# * open source contributors and the GitHub Actions workflows keep restoring from |
| 14 | +# the public npm registry -- npm rewrites the host of every `resolved` URL in |
| 15 | +# package-lock.json to the configured registry, so a single lockfile serves both; |
| 16 | +# * the credential that NpmAuthenticate injects never lands inside the workspace; |
| 17 | +# * the configuration does not depend on the repository being checked out, so |
| 18 | +# release jobs consuming a prebuilt artifact work the same way as build jobs. |
| 19 | +# |
| 20 | +# The registry is still written into that file because NpmAuthenticate discovers the |
| 21 | +# registries to authenticate by reading it. npm then takes the URL from the |
| 22 | +# environment and the matching credential from this file. |
| 23 | +# |
| 24 | +# The file is written with `npm config set` rather than a shell redirect because |
| 25 | +# these pipelines span both Linux and Windows pools. `script:` maps to CmdLine@2, |
| 26 | +# which runs on both, and the npm invocation itself is shell agnostic. PowerShell@2 |
| 27 | +# is avoided because it resolves `pwsh` before `powershell` and hard fails when |
| 28 | +# neither is on PATH, which is not guaranteed on a custom Linux image. |
| 29 | +# |
| 30 | +# This template must run after the Node install task, and before any step that |
| 31 | +# restores packages -- including `npx`, which resolves downloads through the |
| 32 | +# configured registry. |
| 33 | +# |
| 34 | +# Consumers must reference this file as `/.azure-pipelines/npm-cfs.yml@self`. A |
| 35 | +# relative path is resolved against the file doing the including, which for these |
| 36 | +# pipelines is the 1ES extends template in another repository, so the unqualified |
| 37 | +# form is looked up in 1ESPipelineTemplates and fails YAML compilation. |
| 38 | + |
| 39 | +steps: |
| 40 | + - script: npm config set registry $(npm_config_registry) --location=user --userconfig="$(npm_config_userconfig)" |
| 41 | + displayName: Configure CFS npm registry |
| 42 | + |
| 43 | + # Appends `//pkgs.dev.azure.com/.../registry/:_authToken=<token>` for every |
| 44 | + # registry it finds in the file above. `always-auth` is deliberately not written: |
| 45 | + # it is not read by this task and is rejected outright by the npm 10 shipped with |
| 46 | + # Node 20. |
| 47 | + - task: NpmAuthenticate@0 |
| 48 | + displayName: Authenticate to CFS feed |
| 49 | + inputs: |
| 50 | + workingFile: $(npm_config_userconfig) |
| 51 | + |
| 52 | + # Restore silently falling back to the public registry is the failure mode this |
| 53 | + # whole template exists to prevent, and it leaves no trace in the build log, so it |
| 54 | + # is asserted rather than assumed. Written in node, which the agent already |
| 55 | + # provides, to avoid shell differences between the Linux and Windows pools. |
| 56 | + - script: >- |
| 57 | + node -e "const cp=require('child_process');const r=cp.execSync('npm config get registry').toString().trim();console.log('npm registry -> '+r);if(!r.startsWith('https://pkgs.dev.azure.com/')){console.error('##vso[task.logissue type=error]npm is not configured against the CFS feed');process.exit(1);}" |
| 58 | + displayName: Verify CFS npm registry |
0 commit comments