Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,20 @@ updates:
labels:
- "Dependencies"
open-pull-requests-limit: 10
- package-ecosystem: npm
directory: /
schedule:
interval: daily
target-branch: "release/v6"
allow:
- dependency-type: direct
dependency-name: "@npmcli/template-oss"
versioning-strategy: increase-if-necessary
commit-message:
prefix: deps
prefix-development: chore
labels:
- "Dependencies"
- "Backport"
- "release/v6"
open-pull-requests-limit: 10
14 changes: 14 additions & 0 deletions .github/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,17 @@ branches:
apps: []
users: []
teams: [ "cli-team" ]
- name: release/v6
protection:
required_status_checks: null
enforce_admins: true
block_creations: true
required_pull_request_reviews:
required_approving_review_count: 1
require_code_owner_reviews: true
require_last_push_approval: true
dismiss_stale_reviews: true
restrictions:
apps: []
users: []
teams: [ "cli-team" ]
4 changes: 0 additions & 4 deletions .github/workflows/audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@ jobs:
with:
node-version: 22.x
check-latest: contains('22.x', '.x')
- name: Install Latest npm
uses: ./.github/actions/install-latest-npm
with:
node: ${{ steps.node.outputs.node-version }}
- name: Install Dependencies
run: npm i --ignore-scripts --no-audit --no-fund --package-lock
- name: Run Production Audit
Expand Down
18 changes: 5 additions & 13 deletions .github/workflows/ci-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,6 @@ jobs:
with:
node-version: 22.x
check-latest: contains('22.x', '.x')
- name: Install Latest npm
uses: ./.github/actions/install-latest-npm
with:
node: ${{ steps.node.outputs.node-version }}
- name: Install Dependencies
run: npm i --ignore-scripts --no-audit --no-fund
- name: Lint
Expand Down Expand Up @@ -85,21 +81,21 @@ jobs:
os: macos-latest
shell: bash
- name: macOS
os: macos-13
os: macos-15-intel
shell: bash
node-version:
- 20.17.0
- 20.x
- 22.9.0
- 22.x
exclude:
- platform: { name: macOS, os: macos-13, shell: bash }
- platform: { name: macOS, os: macos-15-intel, shell: bash }
node-version: 20.17.0
- platform: { name: macOS, os: macos-13, shell: bash }
- platform: { name: macOS, os: macos-15-intel, shell: bash }
node-version: 20.x
- platform: { name: macOS, os: macos-13, shell: bash }
- platform: { name: macOS, os: macos-15-intel, shell: bash }
node-version: 22.9.0
- platform: { name: macOS, os: macos-13, shell: bash }
- platform: { name: macOS, os: macos-15-intel, shell: bash }
node-version: 22.x
runs-on: ${{ matrix.platform.os }}
defaults:
Expand Down Expand Up @@ -128,10 +124,6 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
check-latest: contains(matrix.node-version, '.x')
- name: Install Latest npm
uses: ./.github/actions/install-latest-npm
with:
node: ${{ steps.node.outputs.node-version }}
- name: Install Dependencies
run: npm i --ignore-scripts --no-audit --no-fund
- name: Add Problem Matcher
Expand Down
19 changes: 6 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
push:
branches:
- main
- release/v*
schedule:
# "At 09:00 UTC (02:00 PT) on Monday" https://crontab.guru/#0_9_*_*_1
- cron: "0 9 * * 1"
Expand Down Expand Up @@ -36,10 +37,6 @@ jobs:
with:
node-version: 22.x
check-latest: contains('22.x', '.x')
- name: Install Latest npm
uses: ./.github/actions/install-latest-npm
with:
node: ${{ steps.node.outputs.node-version }}
- name: Install Dependencies
run: npm i --ignore-scripts --no-audit --no-fund
- name: Lint
Expand All @@ -61,21 +58,21 @@ jobs:
os: macos-latest
shell: bash
- name: macOS
os: macos-13
os: macos-15-intel
shell: bash
node-version:
- 20.17.0
- 20.x
- 22.9.0
- 22.x
exclude:
- platform: { name: macOS, os: macos-13, shell: bash }
- platform: { name: macOS, os: macos-15-intel, shell: bash }
node-version: 20.17.0
- platform: { name: macOS, os: macos-13, shell: bash }
- platform: { name: macOS, os: macos-15-intel, shell: bash }
node-version: 20.x
- platform: { name: macOS, os: macos-13, shell: bash }
- platform: { name: macOS, os: macos-15-intel, shell: bash }
node-version: 22.9.0
- platform: { name: macOS, os: macos-13, shell: bash }
- platform: { name: macOS, os: macos-15-intel, shell: bash }
node-version: 22.x
runs-on: ${{ matrix.platform.os }}
defaults:
Expand All @@ -94,10 +91,6 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
check-latest: contains(matrix.node-version, '.x')
- name: Install Latest npm
uses: ./.github/actions/install-latest-npm
with:
node: ${{ steps.node.outputs.node-version }}
- name: Install Dependencies
run: npm i --ignore-scripts --no-audit --no-fund
- name: Add Problem Matcher
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ on:
push:
branches:
- main
- release/v*
pull_request:
branches:
- main
- release/v*
schedule:
# "At 10:00 UTC (03:00 PT) on Monday" https://crontab.guru/#0_10_*_*_1
- cron: "0 10 * * 1"
Expand Down
4 changes: 0 additions & 4 deletions .github/workflows/post-dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ jobs:
with:
node-version: 22.x
check-latest: contains('22.x', '.x')
- name: Install Latest npm
uses: ./.github/actions/install-latest-npm
with:
node: ${{ steps.node.outputs.node-version }}
- name: Install Dependencies
run: npm i --ignore-scripts --no-audit --no-fund
- name: Fetch Dependabot Metadata
Expand Down
4 changes: 0 additions & 4 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@ jobs:
with:
node-version: 22.x
check-latest: contains('22.x', '.x')
- name: Install Latest npm
uses: ./.github/actions/install-latest-npm
with:
node: ${{ steps.node.outputs.node-version }}
- name: Install Dependencies
run: npm i --ignore-scripts --no-audit --no-fund
- name: Run Commitlint on Commits
Expand Down
4 changes: 0 additions & 4 deletions .github/workflows/release-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,6 @@ jobs:
with:
node-version: 22.x
check-latest: contains('22.x', '.x')
- name: Install Latest npm
uses: ./.github/actions/install-latest-npm
with:
node: ${{ steps.node.outputs.node-version }}
- name: Install Dependencies
run: npm i --ignore-scripts --no-audit --no-fund
- name: Set npm authToken
Expand Down
9 changes: 1 addition & 8 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
push:
branches:
- main
- release/v*

permissions:
contents: write
Expand Down Expand Up @@ -41,10 +42,6 @@ jobs:
with:
node-version: 22.x
check-latest: contains('22.x', '.x')
- name: Install Latest npm
uses: ./.github/actions/install-latest-npm
with:
node: ${{ steps.node.outputs.node-version }}
- name: Install Dependencies
run: npm i --ignore-scripts --no-audit --no-fund
- name: Release Please
Expand Down Expand Up @@ -121,10 +118,6 @@ jobs:
with:
node-version: 22.x
check-latest: contains('22.x', '.x')
- name: Install Latest npm
uses: ./.github/actions/install-latest-npm
with:
node: ${{ steps.node.outputs.node-version }}
- name: Install Dependencies
run: npm i --ignore-scripts --no-audit --no-fund
- name: Create Release Manager Checklist Text
Expand Down
10 changes: 7 additions & 3 deletions lib/check-bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// either rejects or resolves to nothing. return value not relevant.
const isWindows = require('./is-windows.js')
const binTarget = require('./bin-target.js')
const { resolve, dirname } = require('path')
const { resolve, dirname, sep } = require('path')
const readCmdShim = require('read-cmd-shim')
const { readlink } = require('fs/promises')

Expand Down Expand Up @@ -34,7 +34,9 @@ const checkLink = async ({ target, path }) => {

const resolved = resolve(dirname(target), current)

if (resolved.toLowerCase().indexOf(path.toLowerCase()) !== 0) {
const resolvedLower = resolved.toLowerCase()
const pathLower = path.toLowerCase()
if (resolvedLower !== pathLower && !resolvedLower.startsWith(pathLower + sep)) {
return failEEXIST({ target })
}
}
Expand Down Expand Up @@ -65,7 +67,9 @@ const checkShim = async ({ target, path }) => {

const resolved = resolve(dirname(shim), current.replace(/\\/g, '/'))

if (resolved.toLowerCase().indexOf(path.toLowerCase()) !== 0) {
const resolvedLower = resolved.toLowerCase()
const pathLower = path.toLowerCase()
if (resolvedLower !== pathLower && !resolvedLower.startsWith(pathLower + sep)) {
return failEEXIST({ target: shim })
}
}))
Expand Down
4 changes: 2 additions & 2 deletions lib/link-gently.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// if there's a symlink already, pointing into our pkg, remove it first
// then create the symlink

const { resolve, dirname } = require('path')
const { resolve, dirname, sep } = require('path')
const { lstat, mkdir, readlink, rm, symlink } = require('fs/promises')
const { log } = require('proc-log')
const throwSignificant = er => {
Expand Down Expand Up @@ -63,7 +63,7 @@ const linkGently = async ({ path, to, from, absFrom, force }) => {
} // skip it, already set up like we want it.

target = resolve(dirname(to), target)
if (target.indexOf(path) === 0 || force) {
if (target === path || target.startsWith(path + sep) || force) {
return rm(to, rmOpts).then(() => CLOBBER)
}
// neither skip nor clobber
Expand Down
5 changes: 3 additions & 2 deletions lib/shim-bin.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { resolve, dirname } = require('path')
const { resolve, dirname, sep } = require('path')
const { lstat } = require('fs/promises')
const throwNonEnoent = er => {
if (er.code !== 'ENOENT') {
Expand Down Expand Up @@ -64,7 +64,8 @@ const shimBin = ({ path, to, from, absFrom, force }) => {
return readCmdShim(s)
.then(target => {
target = resolve(dirname(to), target)
if (target.indexOf(resolve(path)) !== 0) {
const base = resolve(path)
if (target !== base && !target.startsWith(base + sep)) {
return failEEXIST({ from, to, path })
}
return false
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
},
"devDependencies": {
"@npmcli/eslint-config": "^5.0.0",
"@npmcli/template-oss": "4.27.1",
"@npmcli/template-oss": "4.30.0",
"require-inject": "^1.4.4",
"tap": "^16.0.1"
},
Expand All @@ -55,7 +55,8 @@
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
"windowsCI": false,
"version": "4.27.1",
"publish": true
"version": "4.30.0",
"publish": true,
"updateNpm": false
}
}
8 changes: 8 additions & 0 deletions test/check-bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,12 @@ t.test('not windows', async t => {
top: true,
path: `${dir}/lib/node_modules/foo`,
}))

// prefix collision: "fo" should NOT be treated as owner of "foo"'s symlink
t.rejects(checkBin({
bin: 'foo',
global: true,
top: true,
path: `${dir}/lib/node_modules/fo`,
}), { code: 'EEXIST' }, 'rejects prefix-colliding package name')
})
21 changes: 21 additions & 0 deletions test/link-gently.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ t.test('make links gently', async t => {
pkg: {
'hello.js': `#!/usr/bin/env node\nconsole.log('hello')`,
},
pk: {
'hello.js': `#!/usr/bin/env node\nconsole.log('prefix collision')`,
},
otherpkg: {
'hello.js': `#!/usr/bin/env node\nconsole.log('other hello')`,
},
Expand Down Expand Up @@ -86,6 +89,24 @@ t.test('make links gently', async t => {
})
t.throws(() => fs.readlinkSync(`${dir}/bin/missing`), { code: 'ENOENT' })
linkGently.resetSeen()

// prefix collision: "pk" should NOT clobber a symlink owned by "pkg"
linkResult = await linkGently({
path: `${dir}/pkg`,
to: `${dir}/bin/collide`,
from: `../pkg/hello.js`,
absFrom: `${dir}/pkg/hello.js`,
})
t.equal(linkResult, true, 'legitimate link created')
linkGently.resetSeen()
await t.rejects(linkGently({
path: `${dir}/pk`,
to: `${dir}/bin/collide`,
from: `../pk/hello.js`,
absFrom: `${dir}/pk/hello.js`,
}), { code: 'EEXIST' }, 'rejects prefix-colliding package name')
t.equal(fs.readlinkSync(`${dir}/bin/collide`), '../pkg/hello.js', 'original symlink preserved')
linkGently.resetSeen()
})

t.test('handles link errors', async t => {
Expand Down
12 changes: 12 additions & 0 deletions test/shim-bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ t.test('basic shim bin', async t => {
pkg: {
'hello.js': `#!/usr/bin/env node\r\nconsole.log('hello')`,
},
pk: {
'hello.js': `#!/usr/bin/env node\r\nconsole.log('prefix collision')`,
},
otherpkg: {
'hello.js': `#!/usr/bin/env node\r\nconsole.log('hello')`,
},
Expand Down Expand Up @@ -52,6 +55,15 @@ t.test('basic shim bin', async t => {
force: true,
})
statSync(`${dir}/notashim.cmd`)
// prefix collision: "pk" should NOT be treated as owner of "pkg"'s shims
shimBin.resetSeen()
await t.rejects(shimBin({
path: `${dir}/pk`,
to: `${dir}/bin/hello`,
from: `../pk/hello.js`,
absFrom: `${dir}/pk/hello.js`,
}), { code: 'EEXIST' }, 'rejects prefix-colliding package name')

shimBin.resetSeen()
await shimBin({
path: `${dir}/pkg`,
Expand Down
Loading