Skip to content

Commit eea7cc4

Browse files
committed
fix(ci): pnpm sbom generation (argoproj#27337)
Signed-off-by: Michael Crenshaw <350466+crenshaw-dev@users.noreply.github.com>
1 parent b2a8bc9 commit eea7cc4

4 files changed

Lines changed: 158 additions & 12 deletions

File tree

.github/workflows/release.yaml

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -243,28 +243,37 @@ jobs:
243243
SPDX_GEN_VERSION: v0.0.13
244244
# defines the sigs.k8s.io/bom version to use.
245245
SIGS_BOM_VERSION: v0.2.1
246-
# comma delimited list of project relative folders to inspect for package
247-
# managers (gomod, pnpm, npm).
248-
PROJECT_FOLDERS: '.,./ui'
249246
# full qualified name of the docker image to be inspected
250247
DOCKER_IMAGE: ${{ needs.setup-variables.outputs.quay_image_name }}
251248
run: |
249+
set -euo pipefail
252250
pnpm install --dir ./ui --frozen-lockfile
253251
go install github.com/spdx/spdx-sbom-generator/cmd/generator@$SPDX_GEN_VERSION
254252
go install sigs.k8s.io/bom/cmd/bom@$SIGS_BOM_VERSION
255253
256-
# Generate SPDX for project dependencies analyzing package managers
257-
for folder in $(echo $PROJECT_FOLDERS | sed "s/,/ /g")
258-
do
259-
generator -p $folder -o /tmp
260-
done
254+
generator -p . -o /tmp
255+
256+
# When ui/ should use in-repo pnpm for `pnpm sbom` (11+):
257+
# 1. In ui/package.json set "packageManager" to a pnpm 11+ release (e.g. pnpm@11.0.0), then from ./ui run
258+
# `pnpm install` and commit the resulting ui/pnpm-lock.yaml so release CI's pnpm/action-setup matches.
259+
# 2. Delete hack/generate-ui-pnpm-sbom.sh and remove the ./hack/generate-ui-pnpm-sbom.sh line below.
260+
# 3. Uncomment:
261+
# pnpm --dir ./ui sbom --sbom-format spdx --prod > /tmp/bom-ui-pnpm.spdx.json
262+
./hack/generate-ui-pnpm-sbom.sh --write /tmp/bom-ui-pnpm.spdx.json
261263
262-
# Generate SPDX for binaries analyzing the docker image
263-
if [[ ! -z $DOCKER_IMAGE ]]; then
264-
bom generate -o /tmp/bom-docker-image.spdx -i $DOCKER_IMAGE
264+
if [[ -n "${DOCKER_IMAGE:-}" ]]; then
265+
bom generate -o /tmp/bom-docker-image.spdx -i "${DOCKER_IMAGE}"
265266
fi
266267
267-
cd /tmp && tar -zcf sbom.tar.gz *.spdx
268+
cd /tmp
269+
shopt -s nullglob
270+
spdx_files=( *.spdx )
271+
shopt -u nullglob
272+
if [[ ${#spdx_files[@]} -eq 0 ]]; then
273+
echo "No .spdx files produced under /tmp"
274+
exit 1
275+
fi
276+
tar -zcf sbom.tar.gz "${spdx_files[@]}" bom-ui-pnpm.spdx.json
268277
269278
- name: Generate SBOM hash
270279
shell: bash

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ coverage.out
1616
test-results
1717
.scannerwork
1818
.scratch
19+
# pnpm SBOM helper (hack/generate-ui-pnpm-sbom.sh) download cache — remove this line when that script is deleted.
20+
hack/.cache/
1921
node_modules/
2022
.kube/
2123
./test/cmp/*.sock

docs/operator-manual/upgrading/3.4-3.5.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,11 @@ No action is required for users who do not have impersonation enabled.
3838
## Helm Upgraded
3939

4040
## Custom Healthchecks Added
41+
42+
## Other Changes
43+
44+
### Release `sbom.tar.gz` contents
45+
46+
For normal GitHub releases, **`sbom.tar.gz`** still includes **`bom-go-mod.spdx`** (Go dependencies, tag-value SPDX from `spdx-sbom-generator`) and **`bom-docker-image.spdx`** (the published release image, tag-value SPDX from `sigs.k8s.io/bom`). The UI dependency list is now **`bom-ui-pnpm.spdx.json`**: **SPDX 2.3 JSON** from **`pnpm sbom`**, replacing the old tag-value **`./ui`** output from `spdx-sbom-generator`.
47+
48+
If you consume this archive with tooling that only looked at **`*.spdx`** files, extend it to handle **`bom-ui-pnpm.spdx.json`** as well, or verify **`sbom.tar.gz`** using **`argocd-sbom.intoto.jsonl`** without depending on a fixed internal file list.

hack/generate-ui-pnpm-sbom.sh

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#!/usr/bin/env bash
2+
# Generate SPDX 2.3 JSON for ui/ using a pinned pnpm standalone that includes `pnpm sbom`.
3+
# Supports Linux (amd64, arm64) and macOS (Intel, Apple Silicon). Used locally and in
4+
# .github/workflows/release.yaml (see --write for CI output path).
5+
#
6+
# CLEANUP once ui/package.json `packageManager` is pnpm 11+ and ui/pnpm-lock.yaml is refreshed (`pnpm install` in ./ui):
7+
# - Delete this script; in .github/workflows/release.yaml use `pnpm sbom` (see comments there). The export of
8+
# COREPACK_ENABLE_STRICT=0 below goes away with this file.
9+
# =============================================================================
10+
set -euo pipefail
11+
12+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
13+
readonly PNPM_SBOM_RELEASE_TAG='v11.0.0-rc.0'
14+
CACHE_ROOT="${ROOT}/hack/.cache/pnpm-sbom"
15+
16+
# ui/package.json pins pnpm 10.x; standalone pnpm 11 otherwise exec-switches to that version (no `sbom`).
17+
export COREPACK_ENABLE_STRICT=0
18+
19+
write_out=""
20+
sbom_args=()
21+
while [[ $# -gt 0 ]]; do
22+
case "$1" in
23+
-o|--write|--output)
24+
if [[ $# -lt 2 ]]; then
25+
echo "usage: $0 [--write PATH] [extra args for pnpm sbom...]" >&2
26+
exit 1
27+
fi
28+
write_out="$2"
29+
shift 2
30+
;;
31+
-h|--help)
32+
echo "usage: $0 [--write PATH] [extra args for pnpm sbom...]" >&2
33+
echo " Default: write SPDX JSON to stdout." >&2
34+
echo " --write PATH: write SPDX JSON to PATH (for CI)." >&2
35+
exit 0
36+
;;
37+
*)
38+
sbom_args+=("$1")
39+
shift
40+
;;
41+
esac
42+
done
43+
44+
os="$(uname -s | tr '[:upper:]' '[:lower:]')"
45+
arch="$(uname -m)"
46+
tarball=""
47+
expected_sha=""
48+
case "${os}-${arch}" in
49+
darwin-arm64)
50+
tarball="pnpm-macos-arm64.tar.gz"
51+
# https://github.com/pnpm/pnpm/releases/download/v11.0.0-rc.0/pnpm-macos-arm64.tar.gz
52+
expected_sha='ff7e95be75a27c793fbcdf49c4f9e0c8adfc54e214c7aea4b1306445f31e5391'
53+
;;
54+
darwin-x86_64)
55+
tarball="pnpm-macos-x64.tar.gz"
56+
# https://github.com/pnpm/pnpm/releases/download/v11.0.0-rc.0/pnpm-macos-x64.tar.gz
57+
expected_sha='13fa24a2e0e25af7837acf13d84515fd5a4daab582ac271b01c0b574388ce0bd'
58+
;;
59+
linux-x86_64)
60+
tarball="pnpm-linux-x64.tar.gz"
61+
# https://github.com/pnpm/pnpm/releases/download/v11.0.0-rc.0/pnpm-linux-x64.tar.gz
62+
expected_sha='fe82b94125a6b743456b869e823611a8837b545f2535e4602578e4c9fdb5742a'
63+
;;
64+
linux-aarch64|linux-arm64)
65+
tarball="pnpm-linux-arm64.tar.gz"
66+
# https://github.com/pnpm/pnpm/releases/download/v11.0.0-rc.0/pnpm-linux-arm64.tar.gz
67+
expected_sha='69ad2d528f4a2c00fd42541a80c13491c57e66b2765b2d9d89829aeb0f6482be'
68+
;;
69+
*)
70+
echo "Unsupported OS/arch for pinned pnpm SBOM helper: ${os}-${arch}" >&2
71+
exit 1
72+
;;
73+
esac
74+
75+
sha256_file() {
76+
local f="$1"
77+
if command -v sha256sum >/dev/null 2>&1; then
78+
sha256sum "${f}" | awk '{print $1}'
79+
else
80+
shasum -a 256 "${f}" | awk '{print $1}'
81+
fi
82+
}
83+
84+
CACHE="${CACHE_ROOT}/${PNPM_SBOM_RELEASE_TAG}"
85+
mkdir -p "${CACHE}"
86+
TAR_PATH="${CACHE}/${tarball}"
87+
88+
if [[ ! -f "${TAR_PATH}" ]]; then
89+
echo "Downloading ${PNPM_SBOM_RELEASE_TAG}/${tarball} ..." >&2
90+
curl -fsSL "https://github.com/pnpm/pnpm/releases/download/${PNPM_SBOM_RELEASE_TAG}/${tarball}" \
91+
-o "${TAR_PATH}.part"
92+
actual="$(sha256_file "${TAR_PATH}.part")"
93+
if [[ "${actual}" != "${expected_sha}" ]]; then
94+
echo "SHA256 mismatch for ${tarball}: expected ${expected_sha}, got ${actual}" >&2
95+
exit 1
96+
fi
97+
mv "${TAR_PATH}.part" "${TAR_PATH}"
98+
fi
99+
100+
actual="$(sha256_file "${TAR_PATH}")"
101+
if [[ "${actual}" != "${expected_sha}" ]]; then
102+
echo "SHA256 mismatch for cached ${tarball}: expected ${expected_sha}, got ${actual}" >&2
103+
exit 1
104+
fi
105+
106+
if [[ ! -x "${CACHE}/pnpm" ]]; then
107+
tar -xzf "${TAR_PATH}" -C "${CACHE}"
108+
chmod +x "${CACHE}/pnpm"
109+
fi
110+
111+
echo "Using ${CACHE}/pnpm ($("${CACHE}/pnpm" --version))" >&2
112+
113+
run_sbom() {
114+
# With `set -u`, expanding an empty "${sbom_args[@]}" is an error on some bash builds.
115+
if [[ ${#sbom_args[@]} -gt 0 ]]; then
116+
(cd "${ROOT}" && "${CACHE}/pnpm" --dir ./ui sbom --sbom-format spdx --prod "${sbom_args[@]}")
117+
else
118+
(cd "${ROOT}" && "${CACHE}/pnpm" --dir ./ui sbom --sbom-format spdx --prod)
119+
fi
120+
}
121+
122+
if [[ -n "${write_out}" ]]; then
123+
run_sbom >"${write_out}"
124+
test -s "${write_out}"
125+
else
126+
run_sbom
127+
fi

0 commit comments

Comments
 (0)