ci: pin install to lockfile in remaining install paths
Followup to 152fe8d. Three more sites still called naked `bun install` / `npm install`, which honour caret ranges in package.json and can pull a fresh minor/patch of a transitive dep from the registry on the next run. studio/setup.ps1 (4 sites): the Windows end-user installer. bun install -> bun install --frozen-lockfile (both initial and the cache-clear retry); the npm fallback and the OXC validator npm install both -> npm ci. Error messages updated to reference the new command. studio/setup.sh: the OXC validator runtime install for the Unix path was still naked `npm install`. Now `npm ci`. github/workflows/release-desktop.yml: the desktop release build's frontend install was still naked `npm install`. Now `npm ci` so a published .app/.dmg/.AppImage/.msi can never have shipped with a registry-resolved transitive that drifted from the committed lockfile. The pinned Tauri CLI install in the same workflow stays as `npm install --save-dev @tauri-apps/cli@2.10.1` because that line is intentionally adding a specific package to package.json, not syncing from the lockfile. Verified `npm ci --no-fund --no-audit --dry-run` exits 0 against both the studio/frontend and studio/backend/core/data_recipe/ oxc-validator lockfiles.
This commit is contained in:
parent
53c0d8c477
commit
883f26a2a4
3 changed files with 24 additions and 9 deletions
6
.github/workflows/release-desktop.yml
vendored
6
.github/workflows/release-desktop.yml
vendored
|
|
@ -443,13 +443,17 @@ jobs:
|
|||
|
||||
- name: Install frontend dependencies
|
||||
working-directory: studio/frontend
|
||||
# `npm ci` so a release build can never pull a fresh minor/patch
|
||||
# of a transitive dep from the registry via caret-range resolution;
|
||||
# the tree is exactly what the committed lockfile pins.
|
||||
#
|
||||
# Lifecycle scripts (esbuild native-binary postinstall, etc.) are
|
||||
# required for `vite build`. The pre-install lockfile structural
|
||||
# audit (lockfile_supply_chain_audit.py) is the practical defence
|
||||
# against the npm postinstall-dropper class -- it fires BEFORE any
|
||||
# tarball runs, on the injection pattern itself rather than an
|
||||
# advisory-DB lookup.
|
||||
run: npm install --no-fund --no-audit
|
||||
run: npm ci --no-fund --no-audit
|
||||
|
||||
# ── Rust ──
|
||||
- name: Install Rust stable
|
||||
|
|
|
|||
|
|
@ -1333,9 +1333,13 @@ if ($NeedFrontendBuild -and -not $IsPipInstall) {
|
|||
# metadata but no actual content (bin/, lib/). When this happens bun install
|
||||
# exits 0 but leaves binaries missing. We validate after install and clear
|
||||
# the cache + retry once before falling back to npm.
|
||||
#
|
||||
# --frozen-lockfile so a Windows end-user install can never pull a fresh
|
||||
# minor/patch of a transitive dep from the registry via caret-range
|
||||
# resolution; the tree is exactly what the committed lockfile pins.
|
||||
if ($UseBun) {
|
||||
Write-Host " Using bun for package install (faster)" -ForegroundColor DarkGray
|
||||
$bunExit = Invoke-SetupCommand { bun install }
|
||||
$bunExit = Invoke-SetupCommand { bun install --frozen-lockfile }
|
||||
# On Windows, .bin/ entries vary by package manager:
|
||||
# npm → tsc, tsc.cmd, tsc.ps1
|
||||
# bun → tsc.exe, tsc.bunx
|
||||
|
|
@ -1349,7 +1353,7 @@ if ($NeedFrontendBuild -and -not $IsPipInstall) {
|
|||
Remove-Item "node_modules" -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
Invoke-SetupCommand { bun pm cache rm } | Out-Null
|
||||
$bunExit = Invoke-SetupCommand { bun install }
|
||||
$bunExit = Invoke-SetupCommand { bun install --frozen-lockfile }
|
||||
$hasTsc = (Test-Path "node_modules\.bin\tsc") -or (Test-Path "node_modules\.bin\tsc.cmd") -or (Test-Path "node_modules\.bin\tsc.exe") -or (Test-Path "node_modules\.bin\tsc.bunx")
|
||||
$hasVite = (Test-Path "node_modules\.bin\vite") -or (Test-Path "node_modules\.bin\vite.cmd") -or (Test-Path "node_modules\.bin\vite.exe") -or (Test-Path "node_modules\.bin\vite.bunx")
|
||||
if ($bunExit -ne 0 -or -not $hasTsc -or -not $hasVite) {
|
||||
|
|
@ -1368,13 +1372,16 @@ if ($NeedFrontendBuild -and -not $IsPipInstall) {
|
|||
}
|
||||
}
|
||||
if (-not $UseBun) {
|
||||
$npmExit = Invoke-SetupCommand { npm install }
|
||||
# npm ci (not npm install) so the install is pinned to the committed
|
||||
# lockfile -- a hijacked transitive cannot land via caret-range
|
||||
# resolution. Fails fast if package.json and the lockfile have drifted.
|
||||
$npmExit = Invoke-SetupCommand { npm ci }
|
||||
if ($npmExit -ne 0) {
|
||||
Pop-Location
|
||||
$ErrorActionPreference = $prevEAP_npm
|
||||
foreach ($gi in $HiddenGitignores) { Rename-Item -Path "$gi._twbuild" -NewName (Split-Path $gi -Leaf) -Force -ErrorAction SilentlyContinue }
|
||||
Write-Host "[ERROR] npm install failed (exit code $npmExit)" -ForegroundColor Red
|
||||
Write-Host " Try running 'npm install' manually in frontend/ to see errors" -ForegroundColor Yellow
|
||||
Write-Host "[ERROR] npm ci failed (exit code $npmExit)" -ForegroundColor Red
|
||||
Write-Host " Try running 'npm ci' manually in frontend/ to see errors" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
|
@ -1411,11 +1418,13 @@ if (Test-Path $OxcValidatorDir) {
|
|||
$prevEAP_oxc = $ErrorActionPreference
|
||||
$ErrorActionPreference = "Continue"
|
||||
Push-Location $OxcValidatorDir
|
||||
$oxcInstallExit = Invoke-SetupCommand { npm install }
|
||||
# npm ci pins the oxc validator install to its committed lockfile so a
|
||||
# hijacked transitive cannot land via caret-range resolution.
|
||||
$oxcInstallExit = Invoke-SetupCommand { npm ci }
|
||||
if ($oxcInstallExit -ne 0) {
|
||||
Pop-Location
|
||||
$ErrorActionPreference = $prevEAP_oxc
|
||||
Write-Host "[ERROR] OXC validator npm install failed (exit code $oxcInstallExit)" -ForegroundColor Red
|
||||
Write-Host "[ERROR] OXC validator npm ci failed (exit code $oxcInstallExit)" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
Pop-Location
|
||||
|
|
|
|||
|
|
@ -417,7 +417,9 @@ fi # end frontend build check
|
|||
# ── oxc-validator runtime ──
|
||||
if [ -d "$SCRIPT_DIR/backend/core/data_recipe/oxc-validator" ] && command -v npm &>/dev/null; then
|
||||
cd "$SCRIPT_DIR/backend/core/data_recipe/oxc-validator"
|
||||
run_quiet_no_exit "npm install (oxc validator runtime)" npm install --no-fund --no-audit --loglevel=error
|
||||
# npm ci pins the oxc validator install to its committed lockfile so a
|
||||
# hijacked transitive cannot land via caret-range resolution.
|
||||
run_quiet_no_exit "npm ci (oxc validator runtime)" npm ci --no-fund --no-audit --loglevel=error
|
||||
_oxc_install_rc=$?
|
||||
if [ "$_oxc_install_rc" -ne 0 ]; then
|
||||
exit "$_oxc_install_rc"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue