feat(plugin): add registry name handling and release age exclusion for pnpm workspace
CI / python runtime / release-shaped Linux x64 (push) Has been skipped
CI / node 24 / static (push) Has been cancelled
CI / node 24 / coverage (push) Has been cancelled
CI / node 24 / snapshots and artifacts (push) Has been cancelled
CI / node 22.19 (push) Has been cancelled
CI / node 26 (push) Has been cancelled
CI / python 3.10 / keyless SDK (push) Has been cancelled
CI / windows node 24 / wine blocking (push) Has been cancelled
CI / wine apt cache (push) Has been cancelled
CI / windows node 24 / native complete (push) Has been cancelled
CI / serial / linux (push) Has been cancelled
CI / serial / linux (self-hosted standby) (push) Has been cancelled
CI / serial / macos (push) Has been cancelled
CI / serial / windows (self-hosted standby) (push) Has been cancelled
CI / larger-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (16, windows, dsh-windows-2025-16core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (32, windows, dsh-windows-2025-32core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (4, windows, dsh-windows-2025-4core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (64, windows, dsh-windows-2025-64core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (8, windows, dsh-windows-2025-8core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (96, windows, dsh-windows-2025-96core, production-site) (push) Has been cancelled
CI / consolidated-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, 16) (push) Has been cancelled
CI / consolidated-runner-benchmark (16, windows, dsh-windows-2025-16core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (32, windows, dsh-windows-2025-32core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, 4) (push) Has been cancelled
CI / consolidated-runner-benchmark (4, windows, dsh-windows-2025-4core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (64, windows, dsh-windows-2025-64core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, 8) (push) Has been cancelled
CI / consolidated-runner-benchmark (8, windows, dsh-windows-2025-8core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (96, windows, dsh-windows-2025-96core, 2) (push) Has been cancelled
E2E (real DeepSeek API) / e2e (push) Has been cancelled
Release (vendor) / Pack npm tarballs (push) Has been cancelled
Release (dsh) / Pack npm tarballs (push) Has been cancelled
Sandbox / sandbox e2e (seatbelt, macos-latest) (push) Has been cancelled
Sandbox / sandbox e2e (landlock, ubuntu-24.04) (push) Has been cancelled
Sandbox / sandbox e2e (landlock, ubuntu-24.04-arm) (push) Has been cancelled
Sandbox / sandbox e2e (bwrap, ubuntu-latest) (push) Has been cancelled
CI / all checks passed (push) Has been cancelled
Release (vendor) / Publish to npm (push) Has been cancelled
Release (dsh) / Publish to npm (push) Has been cancelled
CI / python runtime / release-shaped Linux x64 (push) Has been skipped
CI / node 24 / static (push) Has been cancelled
CI / node 24 / coverage (push) Has been cancelled
CI / node 24 / snapshots and artifacts (push) Has been cancelled
CI / node 22.19 (push) Has been cancelled
CI / node 26 (push) Has been cancelled
CI / python 3.10 / keyless SDK (push) Has been cancelled
CI / windows node 24 / wine blocking (push) Has been cancelled
CI / wine apt cache (push) Has been cancelled
CI / windows node 24 / native complete (push) Has been cancelled
CI / serial / linux (push) Has been cancelled
CI / serial / linux (self-hosted standby) (push) Has been cancelled
CI / serial / macos (push) Has been cancelled
CI / serial / windows (self-hosted standby) (push) Has been cancelled
CI / larger-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (16, windows, dsh-windows-2025-16core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (32, windows, dsh-windows-2025-32core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (4, windows, dsh-windows-2025-4core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (64, windows, dsh-windows-2025-64core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (8, windows, dsh-windows-2025-8core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (96, windows, dsh-windows-2025-96core, production-site) (push) Has been cancelled
CI / consolidated-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, 16) (push) Has been cancelled
CI / consolidated-runner-benchmark (16, windows, dsh-windows-2025-16core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (32, windows, dsh-windows-2025-32core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, 4) (push) Has been cancelled
CI / consolidated-runner-benchmark (4, windows, dsh-windows-2025-4core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (64, windows, dsh-windows-2025-64core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, 8) (push) Has been cancelled
CI / consolidated-runner-benchmark (8, windows, dsh-windows-2025-8core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (96, windows, dsh-windows-2025-96core, 2) (push) Has been cancelled
E2E (real DeepSeek API) / e2e (push) Has been cancelled
Release (vendor) / Pack npm tarballs (push) Has been cancelled
Release (dsh) / Pack npm tarballs (push) Has been cancelled
Sandbox / sandbox e2e (seatbelt, macos-latest) (push) Has been cancelled
Sandbox / sandbox e2e (landlock, ubuntu-24.04) (push) Has been cancelled
Sandbox / sandbox e2e (landlock, ubuntu-24.04-arm) (push) Has been cancelled
Sandbox / sandbox e2e (bwrap, ubuntu-latest) (push) Has been cancelled
CI / all checks passed (push) Has been cancelled
Release (vendor) / Publish to npm (push) Has been cancelled
Release (dsh) / Publish to npm (push) Has been cancelled
This commit is contained in:
+54
-1
@@ -11,8 +11,9 @@
|
||||
*/
|
||||
|
||||
import { spawnSync } from 'node:child_process'
|
||||
import { existsSync } from 'node:fs'
|
||||
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
|
||||
import { join, resolve } from 'node:path'
|
||||
import { dump, load } from 'js-yaml'
|
||||
import {
|
||||
DEFAULT_PROFILE_BUNDLES,
|
||||
initProfile,
|
||||
@@ -26,6 +27,52 @@ import { INSTALL_ANCHOR } from './profile-boot.ts'
|
||||
|
||||
const NAME = 'dsh'
|
||||
|
||||
/**
|
||||
* The bare package name when `spec` is a registry specifier, else undefined —
|
||||
* the same shape the in-app install uses to decide registry participation.
|
||||
* Everything pnpm treats as a non-registry source (paths, `file:`/`link:`/
|
||||
* `github:`/`git+`, tarballs, http(s) repo URLs, `.git` markers) is not a
|
||||
* registry spec.
|
||||
* @param spec - the pnpm specifier verbatim.
|
||||
*/
|
||||
export function registryNameOf(spec: string): string | undefined {
|
||||
const trimmed = spec.trim()
|
||||
if (trimmed.length === 0) return undefined
|
||||
if (/^(?:file:|link:|github:|gitlab:|bitbucket:|git\+|git@)/.test(trimmed)) return undefined
|
||||
if (/^(?:\.{1,2}|~|[/\\])/.test(trimmed) || /^[a-zA-Z]:[\\/]/.test(trimmed)) return undefined
|
||||
if (/\.(?:tgz|tar\.gz)(?:[?#]|$)/.test(trimmed)) return undefined
|
||||
if (/^https?:\/\//.test(trimmed) && trimmed.replace(/^https?:\/\//, '').split('/').length > 1) return undefined
|
||||
if (/\.git(?:[#@]|$)/.test(trimmed)) return undefined
|
||||
return trimmed.replace(/@[^/@]+$/, '')
|
||||
}
|
||||
|
||||
/**
|
||||
* Exempt registry package names from pnpm's `minimumReleaseAge` check by writing
|
||||
* the `minimumReleaseAgeExclude` setting into the profile's `pnpm-workspace.yaml`
|
||||
* (honored by pnpm ≥10.16; an older pnpm ignores the key rather than aborting,
|
||||
* unlike the `--minimum-release-age-exclude` CLI flag). This mirrors the in-app
|
||||
* install so an external `dsh plugin add <name>` gets the same latest-version
|
||||
* behavior as the desktop's install, not a stale age-blocked fallback.
|
||||
* @param profileDir - the profile directory.
|
||||
* @param names - the registry package names to exempt.
|
||||
*/
|
||||
export function writeReleaseAgeExclude(profileDir: string, names: readonly string[]): void {
|
||||
const workspacePath = join(profileDir, 'pnpm-workspace.yaml')
|
||||
let doc: Record<string, unknown>
|
||||
try {
|
||||
const parsed = load(readFileSync(workspacePath, 'utf8'))
|
||||
doc = parsed !== null && typeof parsed === 'object'
|
||||
? parsed as Record<string, unknown>
|
||||
: {}
|
||||
} catch {
|
||||
doc = {}
|
||||
}
|
||||
const excluded = new Set<string>((doc.minimumReleaseAgeExclude ?? []) as string[])
|
||||
for (const name of names) excluded.add(name)
|
||||
if (excluded.size > 0) doc.minimumReleaseAgeExclude = [...excluded]
|
||||
writeFileSync(workspacePath, dump(doc))
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrite relative filesystem specs against the user's invoking directory.
|
||||
* pnpm runs with cwd = the profile directory, so a bare `.` or `../plugin`
|
||||
@@ -66,6 +113,12 @@ export function runPlugin(profile: string, args: readonly string[]): number {
|
||||
// its .cmd shim, which spawn() refuses without a shell since the
|
||||
// CVE-2024-27980 hardening; the vendored path runs node against pnpm.cjs.
|
||||
const anchored = args.map(argument => anchorPathSpec(argument, process.cwd()))
|
||||
// An external `add <registry-name>` gets the same minimum-release-age exemption
|
||||
// the in-app install applies, so a just-published plugin installs at latest.
|
||||
if (args[0] === 'add') {
|
||||
const registryNames = args.slice(1).map(registryNameOf).filter((name): name is string => name !== undefined)
|
||||
if (registryNames.length > 0) writeReleaseAgeExclude(dir, registryNames)
|
||||
}
|
||||
const vendored = resolvePnpm(process.execPath)
|
||||
const result = vendored === undefined
|
||||
? spawnSync('pnpm', anchored, { cwd: dir, stdio: 'inherit', shell: process.platform === 'win32' })
|
||||
|
||||
Reference in New Issue
Block a user