Skip to content

Commit 5076da2

Browse files
Isolate npm .tgz in packages/ subfolder so ESRP skips 1ES SBOM _manifest (#1193)
The ESRP release job kept failing at "submitting request to Release Gateway" with "The first argument must be of type string... Received undefined". Root cause: 1ES injects an SBOM _manifest/ folder at the root of every published pipeline artifact, so ESRP's folderlocation contained the .tgz plus 10 non-.tgz _manifest files. With contenttype=npm ESRP tries to derive name@version from every file in the folder; the _manifest files yield undefined and crash the gateway request build. Fix: the build stages the tarball into an npm-packages/packages/ subfolder (the SBOM _manifest/ stays a sibling at the artifact root), and the release points ESRP folderlocation at $(Pipeline.Workspace)/npm-packages/packages so it only ever sees .tgz. Co-authored-by: Tarun Ramsinghani <tarunramsinghani@users.noreply.github.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: adeae005-934b-42dd-ae33-4ea3e7992002
1 parent b5ef8ae commit 5076da2

2 files changed

Lines changed: 29 additions & 9 deletions

File tree

.azure-pipelines/azure-pipelines-build.yml

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,20 +119,30 @@ extends:
119119
workingDirectory: node
120120
121121
# Produce the .tgz that ESRP will publish. ESRP does not pack; we
122-
# stage the tarball into $(Build.ArtifactStagingDirectory)/npm-packages
123-
# and publish it as the 'npm-packages' artifact (see outputs above).
122+
# stage the tarball into a `packages/` SUBFOLDER of the artifact
123+
# ($(Build.ArtifactStagingDirectory)/npm-packages/packages) and
124+
# publish the parent as the 'npm-packages' artifact (see outputs).
125+
#
126+
# WHY THE SUBFOLDER: 1ES injects an SBOM `_manifest/` folder at the
127+
# ROOT of every published pipeline artifact. If the .tgz sat at the
128+
# artifact root next to `_manifest/`, the release pipeline's ESRP
129+
# `folderlocation` would enumerate those non-.tgz SBOM files and
130+
# fail trying to derive npm name@version from them (ESRP crashes
131+
# with "...Received undefined" while submitting the release request).
132+
# Keeping the .tgz in `packages/` leaves `_manifest/` a sibling, so
133+
# the release points ESRP at `.../npm-packages/packages` (only .tgz).
124134
- script: |
125135
set -e
126-
mkdir -p "$(Build.ArtifactStagingDirectory)/npm-packages"
127-
npm pack --pack-destination "$(Build.ArtifactStagingDirectory)/npm-packages"
136+
mkdir -p "$(Build.ArtifactStagingDirectory)/npm-packages/packages"
137+
npm pack --pack-destination "$(Build.ArtifactStagingDirectory)/npm-packages/packages"
128138
echo "Packed contents:"
129-
ls -l "$(Build.ArtifactStagingDirectory)/npm-packages"
139+
ls -l "$(Build.ArtifactStagingDirectory)/npm-packages/packages"
130140
displayName: 'npm pack -> staging'
131141
workingDirectory: node/_build
132142
133143
# Fail the build if npm pack produced no package files.
134144
- script: |
135-
count=$(ls -1 "$(Build.ArtifactStagingDirectory)/npm-packages"/*.tgz 2>/dev/null | wc -l)
145+
count=$(ls -1 "$(Build.ArtifactStagingDirectory)/npm-packages/packages"/*.tgz 2>/dev/null | wc -l)
136146
echo "Found $count .tgz file(s)."
137147
if [ "$count" -eq 0 ]; then
138148
echo "ERROR: npm pack produced no .tgz files; nothing to release."
@@ -146,7 +156,7 @@ extends:
146156
# tarball, fail here rather than shipping a polluted npm package.
147157
- script: |
148158
set -e
149-
for tgz in "$(Build.ArtifactStagingDirectory)/npm-packages"/*.tgz; do
159+
for tgz in "$(Build.ArtifactStagingDirectory)/npm-packages/packages"/*.tgz; do
150160
echo "Inspecting $tgz for stray _manifest/ entries..."
151161
if tar -tzf "$tgz" | grep -E '(^|/)_manifest/' ; then
152162
echo "ERROR: '$tgz' contains an SBOM/_manifest folder; refusing to publish it inside the npm package."

.azure-pipelines/azure-pipelines-release.yml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,10 @@ extends:
108108
inputs:
109109
# Download the .tgz produced by the 'build' pipeline resource.
110110
# This is a declarative 1ES input (the template performs the
111-
# download), so the job body stays a single ESRP task.
111+
# download), so the job body stays a single ESRP task. The
112+
# artifact contains packages/<name>.tgz plus a 1ES-injected
113+
# SBOM `_manifest/` folder at its root; ESRP is pointed at the
114+
# `packages/` subfolder below so it only ever sees the .tgz.
112115
- input: pipelineArtifact
113116
pipeline: build
114117
artifactName: npm-packages
@@ -121,6 +124,13 @@ extends:
121124
# waitforreleasecompletion=true -> block until done
122125
# ESRP does NOT run npm pack; it distributes the .tgz downloaded
123126
# above. The dist-tag is inferred from publishConfig.tag (latest).
127+
#
128+
# folderlocation points at the `packages/` SUBFOLDER of the
129+
# downloaded artifact -- NOT its root. The build stages the .tgz
130+
# there so it is isolated from the 1ES-injected SBOM `_manifest/`
131+
# folder (which lands at the artifact root). ESRP must see ONLY
132+
# .tgz files here; any non-.tgz sibling makes it fail deriving npm
133+
# name@version ("...Received undefined" at release-request submit).
124134
# NOTE: EsrpRelease@12 also accepts `productstate: <tag>` to pin the
125135
# npm dist-tag explicitly (e.g. 'latest' or 'beta'); we intentionally
126136
# omit it and let publishConfig.tag drive the tag per requirements.
@@ -135,7 +145,7 @@ extends:
135145
intent: 'PackageDistribution'
136146
contenttype: 'npm'
137147
contentsource: 'Folder'
138-
folderlocation: '$(Pipeline.Workspace)/npm-packages'
148+
folderlocation: '$(Pipeline.Workspace)/npm-packages/packages'
139149
waitforreleasecompletion: true
140150
owners: '$(EsrpOwners)'
141151
approvers: '$(EsrpApprovers)'

0 commit comments

Comments
 (0)