Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.eslintrc.local.json6
-rw-r--r--.github/workflows/ci-libnpmaccess.yml5
-rw-r--r--.github/workflows/ci-libnpmdiff.yml5
-rw-r--r--.github/workflows/ci-libnpmexec.yml5
-rw-r--r--.github/workflows/ci-libnpmfund.yml5
-rw-r--r--.github/workflows/ci-libnpmhook.yml5
-rw-r--r--.github/workflows/ci-libnpmorg.yml5
-rw-r--r--.github/workflows/ci-libnpmpack.yml5
-rw-r--r--.github/workflows/ci-libnpmpublish.yml5
-rw-r--r--.github/workflows/ci-libnpmsearch.yml5
-rw-r--r--.github/workflows/ci-libnpmteam.yml5
-rw-r--r--.github/workflows/ci-libnpmversion.yml5
-rw-r--r--.github/workflows/ci-npmcli-arborist.yml5
-rw-r--r--.github/workflows/ci-npmcli-docs.yml5
-rw-r--r--.github/workflows/ci-release.yml21
-rw-r--r--.github/workflows/ci-smoke-tests.yml5
-rw-r--r--.github/workflows/ci.yml5
-rw-r--r--.github/workflows/create-cli-deps-pr.yml96
-rw-r--r--.github/workflows/create-node-pr.yml49
-rw-r--r--.gitignore3
-rw-r--r--DEPENDENCIES.md4
-rw-r--r--Makefile37
-rwxr-xr-xbin/npx-cli.js2
-rw-r--r--docs/package.json5
-rw-r--r--package-lock.json4
-rw-r--r--package.json13
-rw-r--r--scripts/bundle-and-gitignore-deps.js56
-rw-r--r--scripts/create-node-pr.js124
-rw-r--r--scripts/dependency-graph.js46
-rw-r--r--scripts/git-dirty.js20
-rw-r--r--scripts/publish-tag.js3
-rw-r--r--scripts/publish.js110
-rw-r--r--scripts/rebuild.js20
-rw-r--r--scripts/release.sh43
-rw-r--r--scripts/remove-files.js11
-rw-r--r--scripts/resetdeps.js25
-rwxr-xr-xscripts/resetdeps.sh17
-rw-r--r--scripts/template-oss/_step-audit.yml2
-rw-r--r--scripts/template-oss/_step-test.yml5
-rw-r--r--scripts/template-oss/audit.yml13
-rw-r--r--scripts/template-oss/ci-release.yml16
-rw-r--r--scripts/template-oss/create-node-pr.yml28
-rw-r--r--scripts/template-oss/root.js15
-rwxr-xr-xscripts/update-authors.js26
-rwxr-xr-xscripts/update-authors.sh9
-rw-r--r--scripts/util.js200
46 files changed, 668 insertions, 436 deletions
diff --git a/.eslintrc.local.json b/.eslintrc.local.json
index beb4581f4..e953021f7 100644
--- a/.eslintrc.local.json
+++ b/.eslintrc.local.json
@@ -1,16 +1,10 @@
{
- "ignorePatterns": [
- "docs/",
- "workspaces/*"
- ],
"rules": {
"no-shadow": "off",
"no-console": "error"
},
"overrides": [{
"files": [
- "scripts/**",
- "bin/**",
"test/**"
],
"rules": {
diff --git a/.github/workflows/ci-libnpmaccess.yml b/.github/workflows/ci-libnpmaccess.yml
index 8455f2b2a..80c6c2c37 100644
--- a/.github/workflows/ci-libnpmaccess.yml
+++ b/.github/workflows/ci-libnpmaccess.yml
@@ -118,11 +118,6 @@ jobs:
cache: npm
- name: Reset Deps
run: node . run resetdeps
- - name: Link
- if: matrix
- run: node . link -f --ignore-scripts
- - name: Rebuild cmark-gfm
- run: node . rebuild cmark-gfm
- name: Add Problem Matcher
run: echo "::add-matcher::.github/matchers/tap.json"
- name: Test
diff --git a/.github/workflows/ci-libnpmdiff.yml b/.github/workflows/ci-libnpmdiff.yml
index 10bd7c90f..a12b2bbe4 100644
--- a/.github/workflows/ci-libnpmdiff.yml
+++ b/.github/workflows/ci-libnpmdiff.yml
@@ -118,11 +118,6 @@ jobs:
cache: npm
- name: Reset Deps
run: node . run resetdeps
- - name: Link
- if: matrix
- run: node . link -f --ignore-scripts
- - name: Rebuild cmark-gfm
- run: node . rebuild cmark-gfm
- name: Add Problem Matcher
run: echo "::add-matcher::.github/matchers/tap.json"
- name: Test
diff --git a/.github/workflows/ci-libnpmexec.yml b/.github/workflows/ci-libnpmexec.yml
index 037c344c2..0ecdbe591 100644
--- a/.github/workflows/ci-libnpmexec.yml
+++ b/.github/workflows/ci-libnpmexec.yml
@@ -118,11 +118,6 @@ jobs:
cache: npm
- name: Reset Deps
run: node . run resetdeps
- - name: Link
- if: matrix
- run: node . link -f --ignore-scripts
- - name: Rebuild cmark-gfm
- run: node . rebuild cmark-gfm
- name: Add Problem Matcher
run: echo "::add-matcher::.github/matchers/tap.json"
- name: Test
diff --git a/.github/workflows/ci-libnpmfund.yml b/.github/workflows/ci-libnpmfund.yml
index 78b79f530..8c8000329 100644
--- a/.github/workflows/ci-libnpmfund.yml
+++ b/.github/workflows/ci-libnpmfund.yml
@@ -118,11 +118,6 @@ jobs:
cache: npm
- name: Reset Deps
run: node . run resetdeps
- - name: Link
- if: matrix
- run: node . link -f --ignore-scripts
- - name: Rebuild cmark-gfm
- run: node . rebuild cmark-gfm
- name: Add Problem Matcher
run: echo "::add-matcher::.github/matchers/tap.json"
- name: Test
diff --git a/.github/workflows/ci-libnpmhook.yml b/.github/workflows/ci-libnpmhook.yml
index 997a2401b..635d04b93 100644
--- a/.github/workflows/ci-libnpmhook.yml
+++ b/.github/workflows/ci-libnpmhook.yml
@@ -118,11 +118,6 @@ jobs:
cache: npm
- name: Reset Deps
run: node . run resetdeps
- - name: Link
- if: matrix
- run: node . link -f --ignore-scripts
- - name: Rebuild cmark-gfm
- run: node . rebuild cmark-gfm
- name: Add Problem Matcher
run: echo "::add-matcher::.github/matchers/tap.json"
- name: Test
diff --git a/.github/workflows/ci-libnpmorg.yml b/.github/workflows/ci-libnpmorg.yml
index aac1cbc9b..2b195927c 100644
--- a/.github/workflows/ci-libnpmorg.yml
+++ b/.github/workflows/ci-libnpmorg.yml
@@ -118,11 +118,6 @@ jobs:
cache: npm
- name: Reset Deps
run: node . run resetdeps
- - name: Link
- if: matrix
- run: node . link -f --ignore-scripts
- - name: Rebuild cmark-gfm
- run: node . rebuild cmark-gfm
- name: Add Problem Matcher
run: echo "::add-matcher::.github/matchers/tap.json"
- name: Test
diff --git a/.github/workflows/ci-libnpmpack.yml b/.github/workflows/ci-libnpmpack.yml
index 533bcd813..09a768ee9 100644
--- a/.github/workflows/ci-libnpmpack.yml
+++ b/.github/workflows/ci-libnpmpack.yml
@@ -118,11 +118,6 @@ jobs:
cache: npm
- name: Reset Deps
run: node . run resetdeps
- - name: Link
- if: matrix
- run: node . link -f --ignore-scripts
- - name: Rebuild cmark-gfm
- run: node . rebuild cmark-gfm
- name: Add Problem Matcher
run: echo "::add-matcher::.github/matchers/tap.json"
- name: Test
diff --git a/.github/workflows/ci-libnpmpublish.yml b/.github/workflows/ci-libnpmpublish.yml
index 7ecab7a4e..71b5342c5 100644
--- a/.github/workflows/ci-libnpmpublish.yml
+++ b/.github/workflows/ci-libnpmpublish.yml
@@ -118,11 +118,6 @@ jobs:
cache: npm
- name: Reset Deps
run: node . run resetdeps
- - name: Link
- if: matrix
- run: node . link -f --ignore-scripts
- - name: Rebuild cmark-gfm
- run: node . rebuild cmark-gfm
- name: Add Problem Matcher
run: echo "::add-matcher::.github/matchers/tap.json"
- name: Test
diff --git a/.github/workflows/ci-libnpmsearch.yml b/.github/workflows/ci-libnpmsearch.yml
index 42e8f4f83..9fdf040bc 100644
--- a/.github/workflows/ci-libnpmsearch.yml
+++ b/.github/workflows/ci-libnpmsearch.yml
@@ -118,11 +118,6 @@ jobs:
cache: npm
- name: Reset Deps
run: node . run resetdeps
- - name: Link
- if: matrix
- run: node . link -f --ignore-scripts
- - name: Rebuild cmark-gfm
- run: node . rebuild cmark-gfm
- name: Add Problem Matcher
run: echo "::add-matcher::.github/matchers/tap.json"
- name: Test
diff --git a/.github/workflows/ci-libnpmteam.yml b/.github/workflows/ci-libnpmteam.yml
index ec00a20c2..937f5967e 100644
--- a/.github/workflows/ci-libnpmteam.yml
+++ b/.github/workflows/ci-libnpmteam.yml
@@ -118,11 +118,6 @@ jobs:
cache: npm
- name: Reset Deps
run: node . run resetdeps
- - name: Link
- if: matrix
- run: node . link -f --ignore-scripts
- - name: Rebuild cmark-gfm
- run: node . rebuild cmark-gfm
- name: Add Problem Matcher
run: echo "::add-matcher::.github/matchers/tap.json"
- name: Test
diff --git a/.github/workflows/ci-libnpmversion.yml b/.github/workflows/ci-libnpmversion.yml
index 567e85eba..8d2eabd99 100644
--- a/.github/workflows/ci-libnpmversion.yml
+++ b/.github/workflows/ci-libnpmversion.yml
@@ -118,11 +118,6 @@ jobs:
cache: npm
- name: Reset Deps
run: node . run resetdeps
- - name: Link
- if: matrix
- run: node . link -f --ignore-scripts
- - name: Rebuild cmark-gfm
- run: node . rebuild cmark-gfm
- name: Add Problem Matcher
run: echo "::add-matcher::.github/matchers/tap.json"
- name: Test
diff --git a/.github/workflows/ci-npmcli-arborist.yml b/.github/workflows/ci-npmcli-arborist.yml
index 86a4be73b..495f7eebb 100644
--- a/.github/workflows/ci-npmcli-arborist.yml
+++ b/.github/workflows/ci-npmcli-arborist.yml
@@ -118,11 +118,6 @@ jobs:
cache: npm
- name: Reset Deps
run: node . run resetdeps
- - name: Link
- if: matrix
- run: node . link -f --ignore-scripts
- - name: Rebuild cmark-gfm
- run: node . rebuild cmark-gfm
- name: Add Problem Matcher
run: echo "::add-matcher::.github/matchers/tap.json"
- name: Test
diff --git a/.github/workflows/ci-npmcli-docs.yml b/.github/workflows/ci-npmcli-docs.yml
index 9906b3bb7..ea4d5366d 100644
--- a/.github/workflows/ci-npmcli-docs.yml
+++ b/.github/workflows/ci-npmcli-docs.yml
@@ -111,11 +111,6 @@ jobs:
cache: npm
- name: Reset Deps
run: node . run resetdeps
- - name: Link
- if: matrix
- run: node . link -f --ignore-scripts
- - name: Rebuild cmark-gfm
- run: node . rebuild cmark-gfm
- name: Add Problem Matcher
run: echo "::add-matcher::.github/matchers/tap.json"
- name: Test
diff --git a/.github/workflows/ci-release.yml b/.github/workflows/ci-release.yml
index 0958704ce..aaeba4b10 100644
--- a/.github/workflows/ci-release.yml
+++ b/.github/workflows/ci-release.yml
@@ -177,11 +177,6 @@ jobs:
cache: npm
- name: Reset Deps
run: node . run resetdeps
- - name: Link
- if: matrix
- run: node . link -f --ignore-scripts
- - name: Rebuild cmark-gfm
- run: node . rebuild cmark-gfm
- name: Add Problem Matcher
run: echo "::add-matcher::.github/matchers/tap.json"
- name: Test
@@ -284,18 +279,12 @@ jobs:
run: |
NPM_VERSION="$(node . --version)-$GITHUB_SHA.0"
node . version $NPM_VERSION --ignore-scripts
- node . run resetdeps
- git clean -fd
- node . ls --omit=dev >/dev/null
- node . prune --omit=dev --no-save --no-audit --no-fund
- node scripts/git-dirty.js
- node . pack --pack-destination=$RUNNER_TEMP
- node . install -g $RUNNER_TEMP/npm-$NPM_VERSION.tgz
+ node scripts/publish.js --pack-destination=$RUNNER_TEMP
+ node . install --global $RUNNER_TEMP/npm-$NPM_VERSION.tgz
node . install -w smoke-tests --ignore-scripts --no-audit --no-fund
- rm -rf {lib,bin,index.js}
- # this one should be npm since we explicitly installed our packed
- # tarball globally and the next test will make sure our the new
- # globally installed version contains the git sha
+ node scripts/remove-files.js
+ # call installed npm instead of local source since we are testing
+ # the packed tarball that we just installed globally
SMOKE_PUBLISH_NPM=1 npm test -w smoke-tests --ignore-scripts
- name: Conclude Check
uses: LouisBrunner/checks-action@v1.3.1
diff --git a/.github/workflows/ci-smoke-tests.yml b/.github/workflows/ci-smoke-tests.yml
index 549785c4e..e69a3224c 100644
--- a/.github/workflows/ci-smoke-tests.yml
+++ b/.github/workflows/ci-smoke-tests.yml
@@ -118,11 +118,6 @@ jobs:
cache: npm
- name: Reset Deps
run: node . run resetdeps
- - name: Link
- if: matrix
- run: node . link -f --ignore-scripts
- - name: Rebuild cmark-gfm
- run: node . rebuild cmark-gfm
- name: Add Problem Matcher
run: echo "::add-matcher::.github/matchers/tap.json"
- name: Test
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 57ea1212b..0cc934215 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -122,11 +122,6 @@ jobs:
cache: npm
- name: Reset Deps
run: node . run resetdeps
- - name: Link
- if: matrix
- run: node . link -f --ignore-scripts
- - name: Rebuild cmark-gfm
- run: node . rebuild cmark-gfm
- name: Add Problem Matcher
run: echo "::add-matcher::.github/matchers/tap.json"
- name: Test
diff --git a/.github/workflows/create-cli-deps-pr.yml b/.github/workflows/create-cli-deps-pr.yml
deleted file mode 100644
index e5bd2ccdd..000000000
--- a/.github/workflows/create-cli-deps-pr.yml
+++ /dev/null
@@ -1,96 +0,0 @@
-name: "Create CLI Deps PR"
-
-on:
- workflow_dispatch:
- inputs:
- npmVersion:
- description: "6.x.x or latest"
- required: true
- default: 'latest'
- dryRun:
- description: "Do a dry run?"
- default: ''
-
-jobs:
- create-pull-request:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout npm/node
- uses: actions/checkout@v3
- with:
- fetch-depth: 0
- ref: main
- repository: npm/node
- token: ${{ secrets.NODE_PULL_REQUEST_TOKEN }}
- - name: Setup git user
- run: |
- git config --global user.email "npm CLI robot"
- git config --global user.name "npm-cli+bot@github.com"
- - name: Sync upstream changes
- uses: aormsby/Fork-Sync-With-Upstream-action@v3.2
- with:
- target_sync_branch: main
- target_repo_token: ${{ secrets.NODE_PULL_REQUEST_TOKEN }}
- upstream_sync_branch: main
- upstream_sync_repo: nodejs/node
- upstream_pull_args: --ff-only
- - name: Run dependency updates and create PR
- env:
- GITHUB_TOKEN: ${{ secrets.NODE_PULL_REQUEST_TOKEN }}
- run: |
- base_dir="$( pwd )"/
- dry_run="${{ github.event.inputs.dryRun }}"
- npm_version="${{ github.event.inputs.npmVersion }}"
- npm_tag=""
- base_branch=""
-
- if [ "$npm_version" == "latest" ]; then
- npm_tag=`npm view npm@latest version`
- base_branch="main"
- else
- npm_tag="$npm_version"
- base_branch="v14.x-staging"
- fi
-
- npm_vtag="v$npm_tag"
- npm_branch="npm-$npm_tag"
- message="deps: upgrade npm to $npm_tag"
-
- git checkout -b "$npm_branch"
-
- echo "Cloning CLI repo"
- gh repo clone npm/cli
-
- echo "Prepping CLI repo for release"
- cd cli
- git checkout "$npm_vtag"
- make release
-
- echo "Removing old npm"
- deps_dir="$base_dir"deps/
- cd "$deps_dir"
- rm -rf npm/
-
- echo "Copying new npm"
- tar zxf "$base_dir"cli/release/"$npm_branch".tgz
-
- echo "Removing CLI workspace"
- cd "$base_dir"
- rm -rf cli
-
- git add -A deps/npm
- git commit -m "$message"
- git rebase --whitespace=fix main
-
- if [[ "$dry_run" == "true" ]]; then
- git status
- git show --summary
- echo $message
- echo $npm_branch
- echo $base_branch
- echo $npm_vtag
- else
- git push origin "$npm_branch"
- gh release view "$npm_vtag" -R npm/cli --json body -q ".body" | \
- gh pr create -R nodejs/node -B "$base_branch" -H "npm:$npm_branch" -t "$message" -F -
- fi
diff --git a/.github/workflows/create-node-pr.yml b/.github/workflows/create-node-pr.yml
new file mode 100644
index 000000000..f7bf18d80
--- /dev/null
+++ b/.github/workflows/create-node-pr.yml
@@ -0,0 +1,49 @@
+# This file is automatically added by @npmcli/template-oss. Do not edit.
+
+name: "Create Node PR"
+
+on:
+ workflow_dispatch:
+ inputs:
+ spec:
+ description: "The npm spec to create the PR from"
+ required: true
+ default: 'latest'
+ dryRun:
+ description: "Setting this to anything will run all the steps except opening the PR"
+
+jobs:
+ create-pull-request:
+ name: Create Node PR
+ if: github.repository_owner == 'npm'
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ shell: bash
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ - name: Setup Git User
+ run: |
+ git config --global user.email "npm-cli+bot@github.com"
+ git config --global user.name "npm CLI robot"
+ - name: Setup Node
+ uses: actions/setup-node@v3
+ with:
+ node-version: 18.x
+ cache: npm
+ - name: Reset Deps
+ run: node . run resetdeps
+ - name: Checkout Node
+ uses: actions/checkout@v3
+ with:
+ token: ${{ secrets.NODE_PULL_REQUEST_TOKEN }}
+ repository: nodejs/node
+ fetch-depth: 0
+ path: node
+ - name: Create Node Pull Request
+ env:
+ GITHUB_TOKEN: ${{ secrets.NODE_PULL_REQUEST_TOKEN }}
+ run: |
+ DRY_RUN=$([ -z "${{ inputs.dryRun }}" ] && echo "" || echo "--dry-run")
+ node scripts/create-node-pr.js "${{ inputs.spec }}" "$DRY_RUN"
diff --git a/.gitignore b/.gitignore
index 370f45df4..c857a68a6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,7 +18,6 @@
!/AUTHORS
!/bin/
!/CHANGELOG*
-!/changelogs/
!/CODE_OF_CONDUCT.md
!/configure
!/CONTRIBUTING.md
@@ -27,8 +26,6 @@
!/index.js
!/lib/
!/LICENSE*
-!/make.bat
-!/Makefile
!/map.js
!/node_modules/
/node_modules/.bin/
diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md
index 97808f4a4..c6fed355f 100644
--- a/DEPENDENCIES.md
+++ b/DEPENDENCIES.md
@@ -119,6 +119,7 @@ graph LR;
npm-->npmcli-config["@npmcli/config"];
npm-->npmcli-docs["@npmcli/docs"];
npm-->npmcli-eslint-config["@npmcli/eslint-config"];
+ npm-->npmcli-fs["@npmcli/fs"];
npm-->npmcli-git["@npmcli/git"];
npm-->npmcli-map-workspaces["@npmcli/map-workspaces"];
npm-->npmcli-package-json["@npmcli/package-json"];
@@ -735,6 +736,7 @@ graph LR;
npm-->npmcli-config["@npmcli/config"];
npm-->npmcli-docs["@npmcli/docs"];
npm-->npmcli-eslint-config["@npmcli/eslint-config"];
+ npm-->npmcli-fs["@npmcli/fs"];
npm-->npmcli-git["@npmcli/git"];
npm-->npmcli-map-workspaces["@npmcli/map-workspaces"];
npm-->npmcli-package-json["@npmcli/package-json"];
@@ -1103,4 +1105,4 @@ packages higher up the chain.
- @npmcli/git, make-fetch-happen, @npmcli/config, init-package-json
- @npmcli/installed-package-contents, @npmcli/map-workspaces, cacache, npm-pick-manifest, @npmcli/run-script, read-package-json, readdir-scoped-modules, promzard
- @npmcli/docs, npm-bundled, read-package-json-fast, @npmcli/fs, unique-filename, npm-install-checks, npm-package-arg, npm-packlist, normalize-package-data, @npmcli/package-json, bin-links, nopt, npmlog, parse-conflict-json, dezalgo, read
- - ignore-walk, @npmcli/eslint-config, @npmcli/template-oss, npm-normalize-package-bin, @npmcli/name-from-folder, json-parse-even-better-errors, semver, @npmcli/move-file, fs-minipass, ssri, unique-slug, @npmcli/promise-spawn, hosted-git-info, proc-log, validate-npm-package-name, @npmcli/node-gyp, minipass-fetch, @npmcli/query, cmd-shim, read-cmd-shim, write-file-atomic, abbrev, are-we-there-yet, gauge, wrappy, treeverse, minify-registry-metadata, @npmcli/disparity-colors, @npmcli/ci-detect, mute-stream, ini, npm-audit-report, npm-user-validate \ No newline at end of file
+ - ignore-walk, @npmcli/eslint-config, @npmcli/template-oss, npm-normalize-package-bin, @npmcli/name-from-folder, json-parse-even-better-errors, semver, @npmcli/move-file, fs-minipass, ssri, unique-slug, @npmcli/promise-spawn, hosted-git-info, proc-log, validate-npm-package-name, @npmcli/node-gyp, minipass-fetch, @npmcli/query, cmd-shim, read-cmd-shim, write-file-atomic, abbrev, are-we-there-yet, gauge, wrappy, treeverse, minify-registry-metadata, @npmcli/disparity-colors, @npmcli/ci-detect, mute-stream, ini, npm-audit-report, npm-user-validate
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 997a09506..000000000
--- a/Makefile
+++ /dev/null
@@ -1,37 +0,0 @@
-# vim: set softtabstop=2 shiftwidth=2:
-SHELL = bash
-
-PUBLISHTAG = $(shell node scripts/publish-tag.js)
-
-deps:
- node bin/npm-cli.js run resetdeps
-
-lint-all: deps
- node bin/npm-cli.js run lint-all
-
-test-all: deps
- node bin/npm-cli.js run test-all
-
-ls-ok:
- node bin/npm-cli.js ls --omit=dev >/dev/null
-
-gitclean:
- git clean -fd
-
-uninstall:
- node bin/npm-cli.js rm -g -f npm
-
-link: uninstall
- node bin/npm-cli.js link -f --ignore-scripts
-
-prune: deps
- node bin/npm-cli.js prune --omit=dev --no-save --no-audit --no-fund
- node scripts/git-dirty.js
-
-publish: gitclean ls-ok link lint-all test-all prune
- node bin/npm-cli.js publish --tag=$(PUBLISHTAG)
-
-release: gitclean ls-ok prune
- @bash scripts/release.sh
-
-.PHONY: link gitclean uninstall lint-all test-all release ls-ok deps prune
diff --git a/bin/npx-cli.js b/bin/npx-cli.js
index cb05e1cb7..75090aed4 100755
--- a/bin/npx-cli.js
+++ b/bin/npx-cli.js
@@ -98,6 +98,7 @@ for (i = 3; i < process.argv.length; i++) {
}
if (removed.has(key)) {
+ // eslint-disable-next-line no-console
console.error(`npx: the --${key} argument has been removed.`)
sawRemovedFlags = true
process.argv.splice(i, 1)
@@ -122,6 +123,7 @@ for (i = 3; i < process.argv.length; i++) {
}
if (sawRemovedFlags) {
+ // eslint-disable-next-line no-console
console.error('See `npm help exec` for more information')
}
diff --git a/docs/package.json b/docs/package.json
index 18220d139..d92f558a3 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -11,8 +11,11 @@
"lintfix": "node .. run lint -- --fix",
"snap": "tap",
"test": "tap",
+ "pretest": "node .. run rebuild-cmark",
"posttest": "node .. run lint",
- "build": "node bin/build.js"
+ "build": "node bin/build.js",
+ "prebuild": "node .. run rebuild-cmark",
+ "rebuild-cmark": "node ../scripts/rebuild.js cmark-gfm"
},
"repository": {
"type": "git",
diff --git a/package-lock.json b/package-lock.json
index 0f44f87fb..16a7fe067 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -164,6 +164,7 @@
"devDependencies": {
"@npmcli/docs": "^1.0.0",
"@npmcli/eslint-config": "^4.0.0",
+ "@npmcli/fs": "^3.0.0",
"@npmcli/git": "^4.0.1",
"@npmcli/promise-spawn": "^5.0.0",
"@npmcli/template-oss": "4.6.2",
@@ -5688,8 +5689,9 @@
},
"node_modules/glob": {
"version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz",
+ "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==",
"inBundle": true,
- "license": "ISC",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
diff --git a/package.json b/package.json
index c86f062aa..de24066ed 100644
--- a/package.json
+++ b/package.json
@@ -11,9 +11,9 @@
"bin/",
"lib/",
"index.js",
- "docs/content/**/*.md",
- "docs/output/**/*.html",
- "man"
+ "docs/content/",
+ "docs/output/",
+ "man/"
],
"keywords": [
"install",
@@ -201,6 +201,7 @@
"devDependencies": {
"@npmcli/docs": "^1.0.0",
"@npmcli/eslint-config": "^4.0.0",
+ "@npmcli/fs": "^3.0.0",
"@npmcli/git": "^4.0.1",
"@npmcli/promise-spawn": "^5.0.0",
"@npmcli/template-oss": "4.6.2",
@@ -213,8 +214,8 @@
"scripts": {
"dependencies": "node scripts/bundle-and-gitignore-deps.js && node scripts/dependency-graph.js",
"dumpconf": "env | grep npm | sort | uniq",
- "authors": "bash scripts/update-authors.sh",
"licenses": "licensee --production --errors-only",
+ "pretest": "node scripts/rebuild.js cmark-gfm",
"test": "tap",
"test-all": "node . run test -ws -iwr --if-present",
"snap": "tap",
@@ -227,8 +228,8 @@
"lintfix": "node . run lint -- --fix",
"lint-all": "node . run lint -ws -iwr --if-present",
"prelint": "rimraf test/npm_cache*",
- "resetdeps": "bash scripts/resetdeps.sh",
- "rp-pull-request": "node . run authors",
+ "resetdeps": "node scripts/resetdeps.js",
+ "rp-pull-request": "node scripts/update-authors.js",
"postlint": "template-oss-check",
"template-oss-apply": "template-oss-apply --force"
},
diff --git a/scripts/bundle-and-gitignore-deps.js b/scripts/bundle-and-gitignore-deps.js
index bbe08a783..e19721dad 100644
--- a/scripts/bundle-and-gitignore-deps.js
+++ b/scripts/bundle-and-gitignore-deps.js
@@ -1,14 +1,10 @@
-#!/usr/bin/env node
-
const Arborist = require('@npmcli/arborist')
const packlist = require('npm-packlist')
-const git = require('@npmcli/git')
-const { resolve, join, relative } = require('path')
+const { join, relative } = require('path')
const localeCompare = require('@isaacs/string-locale-compare')('en')
-const fs = require('fs/promises')
const PackageJson = require('@npmcli/package-json')
+const { run, CWD, git, fs } = require('./util')
-const RM_FLAG = '--remove-ignored-files'
const ALWAYS_IGNORE = `
.bin/
.cache/
@@ -42,24 +38,19 @@ __pycache__
.gitkeep
`
-const lsIgnored = async ({ cwd, dir }) => {
- const { stdout } = await git.spawn([
+const lsIgnored = async (dir, { removeIgnoredFiles }) => {
+ const files = await git(
'ls-files',
'--cached',
'--ignored',
`--exclude-standard`,
dir,
- ], { cwd })
-
- const files = stdout
- .trim()
- .split('\n')
- .map(l => l.trim())
- .filter(Boolean)
+ { lines: true }
+ )
- if (process.argv.includes(RM_FLAG)) {
+ if (removeIgnoredFiles) {
for (const file of files) {
- await git.spawn(['rm', file], { cwd })
+ await git('rm', file)
}
return []
}
@@ -184,8 +175,8 @@ const getAllowedPaths = (files) => {
return [...allowPaths]
}
-const setBundleDeps = async (dir) => {
- const pkg = await PackageJson.load(dir)
+const setBundleDeps = async () => {
+ const pkg = await PackageJson.load(CWD)
pkg.update({
bundleDependencies: Object.keys(pkg.content.dependencies).sort(localeCompare),
@@ -208,13 +199,10 @@ deps source. We have to do this since everything is ignored by default, and git
will not allow a nested path if its parent has not also been allowed. BUT! We
also have to ignore other things in those directories.
*/
-const main = async (path) => {
- await setBundleDeps(path)
+const main = async ({ removeIgnoredFiles }) => {
+ await setBundleDeps()
- const nodeModules = resolve(path, 'node_modules')
- const gitIgnore = join(nodeModules, '.gitignore')
-
- const arb = new Arborist({ path })
+ const arb = new Arborist({ path: CWD })
const files = await arb.loadActual().then(packlist)
const ignoreFile = [
@@ -228,28 +216,24 @@ const main = async (path) => {
...ALWAYS_IGNORE.trim().split('\n'),
]
- await fs.writeFile(gitIgnore, ignoreFile.join('\n') + '\n')
+ const NODE_MODULES = join(CWD, 'node_modules')
+ const res = await fs.writeFile(join(NODE_MODULES, '.gitignore'), ignoreFile.join('\n'))
// After we write the file we have to check if any of the paths already checked in
// inside node_modules are now going to be ignored. If we find any then fail with
// a list of paths that will need to have `git rm` run on them.
- const trackedAndIgnored = await lsIgnored({ cwd: path, dir: nodeModules })
+ const trackedAndIgnored = await lsIgnored(NODE_MODULES, { removeIgnoredFiles })
if (trackedAndIgnored.length) {
const message = [
'The following files are checked in to git but will now be ignored.',
- `Rerun this script with \`${RM_FLAG}\` to remove them.`,
- ...trackedAndIgnored.map(p => relative(nodeModules, p)),
+ `Rerun this script with \`--remove-ignored-files\` to remove them.`,
+ ...trackedAndIgnored.map(p => relative(NODE_MODULES, p)),
].join('\n')
throw new Error(message)
}
- return `Wrote to ${relative(process.cwd(), gitIgnore)}`
+ return res
}
-main(resolve(__dirname, '..'))
- .then((res) => console.log(res))
- .catch((err) => {
- console.error(err)
- return process.exit(1)
- })
+run(main)
diff --git a/scripts/create-node-pr.js b/scripts/create-node-pr.js
new file mode 100644
index 000000000..26d4c07a7
--- /dev/null
+++ b/scripts/create-node-pr.js
@@ -0,0 +1,124 @@
+const { join } = require('path')
+const fsp = require('fs/promises')
+const hgi = require('hosted-git-info')
+const semver = require('semver')
+const pacote = require('pacote')
+const log = require('proc-log')
+const tar = require('tar')
+const { cp, withTempDir } = require('@npmcli/fs')
+const { CWD, run, spawn, git, fs, gh } = require('./util.js')
+
+// this script expects node to already be cloned to a directory at the cli root named "node"
+const NODE_DIR = join(CWD, 'node')
+const gitNode = spawn.create('git', { cwd: NODE_DIR })
+
+const createNodeTarball = async ({ mani, registryOnly, tag, dir: extractDir }) => {
+ const tarball = join(extractDir, 'npm-node.tgz')
+ await pacote.tarball.file(mani._from, tarball, { resolved: mani._resolved })
+
+ if (registryOnly) {
+ // a future goal is to only need files from the published tarball for
+ // inclusion in node. in that case, we'd be able to remove everything after
+ // this line since we have already fetched the tarball
+ return tarball
+ }
+
+ // extract tarball to current dir and delete original tarball
+ await tar.x({ strip: 1, file: tarball, cwd: extractDir })
+ await fs.rimraf(tarball)
+
+ // checkout the tag since we need to get files from source.
+ await git.dirty()
+ tag && await git('checkout', tag)
+ for (const path of ['.npmrc', 'tap-snapshots/', 'test/']) {
+ await cp(join(CWD, path), join(extractDir, path), { recursive: true })
+ }
+
+ await tar.c({
+ ...pacote.DirFetcher.tarCreateOptions(mani),
+ cwd: extractDir,
+ file: tarball,
+ }, ['.'])
+
+ return tarball
+}
+
+const main = async (spec, opts) => withTempDir(CWD, async (tmpDir) => {
+ const { dryRun, registryOnly, skipCheckout } = opts
+
+ const mani = await pacote.manifest(`npm@${spec}`, { preferOnline: true })
+
+ const head = {
+ tag: `v${mani.version}`,
+ branch: `npm-v${mani.version}`,
+ host: hgi.fromUrl('npm/node'),
+ message: `deps: upgrade npm to ${mani.version}`,
+ }
+ log.silly(head)
+
+ const tarball = await createNodeTarball({
+ mani,
+ dir: tmpDir,
+ registryOnly,
+ // the only reason this is optional is for testing when updating this script.
+ // if we checkout an older tag, it won't have the updates we are testing.
+ tag: skipCheckout ? null : head.tag,
+ })
+
+ await fsp.access(NODE_DIR, fsp.constants.F_OK).catch(() => {
+ throw new Error(`node repo must be checked out to \`${NODE_DIR}\` to continue`)
+ })
+
+ const base = {
+ // we used to send PRs sometimes for old versions to the 14.x staging
+ // branch. this might not be needed anymore, but this is how we
+ // would do it, if we needed to send a PR for backport fixes
+ branch: semver.major(mani.version) <= 8 ? '14.x-staging' : 'main',
+ remote: 'origin',
+ host: hgi.fromUrl(await gitNode('remote', 'get-url', 'origin', { out: true })),
+ }
+ log.silly(base)
+
+ await gh('repo', 'fork', base.host.path(), '--org', head.host.user, { quiet: true, ok: true })
+ await gitNode('fetch', base.remote)
+ await gitNode('checkout', base.branch)
+ await gitNode('reset', '--hard', `${base.remote}/${base.branch}`)
+ await gitNode('branch', '-D', head.branch, { ok: true })
+ await gitNode('checkout', '-b', head.branch)
+
+ const npmPath = join('deps', 'npm')
+ const npmDir = join(NODE_DIR, npmPath)
+ await fs.clean(npmDir)
+ await tar.x({ strip: 1, file: tarball, cwd: npmDir })
+
+ await gitNode('add', '-A', npmPath)
+ await gitNode('commit', '-m', head.message)
+ await gitNode('rebase', '--whitespace', 'fix', base.branch)
+
+ await gitNode('remote', 'add', head.host.user, head.host.ssh(), { ok: true })
+ await gitNode('push', head.host.user, head.branch, '--force')
+
+ const notes = await gh.json('release', 'view', head.tag, 'body')
+ log.silly('body', notes)
+
+ const prArgs = [
+ 'pr', 'create',
+ '-R', base.host.path(),
+ '-B', base.branch,
+ '-H', `${head.host.user}:${head.branch}`,
+ '-t', head.message,
+ ]
+
+ if (dryRun) {
+ log.info(`gh ${prArgs.join(' ')}`)
+ const url = new URL(base.host.browse())
+ const compare = `${base.branch}...${head.host.user}:${head.host.project}:${head.branch}`
+ url.pathname += `/compare/${compare}`
+ url.searchParams.set('expand', '1')
+ return url.toString()
+ }
+
+ return gh(...prArgs, '-F', '-', { cwd: NODE_DIR, input: notes, out: true })
+})
+
+run(({ argv, ...opts }) => main(argv.remain[0], opts))
diff --git a/scripts/dependency-graph.js b/scripts/dependency-graph.js
index 41beb302d..e292ce448 100644
--- a/scripts/dependency-graph.js
+++ b/scripts/dependency-graph.js
@@ -1,22 +1,14 @@
-#!/usr/bin/env node
-
-'use strict'
-
-// Generates our dependency graph documents in DEPENDENCIES.md.
-
const Arborist = require('@npmcli/arborist')
-const mapWorkspaces = require('@npmcli/map-workspaces')
-const fs = require('fs')
+const { readFileSync } = require('fs')
+const { join } = require('path')
const log = require('proc-log')
+const { run, CWD, pkg, fs } = require('./util.js')
-if (process.argv.includes('--debug')) {
- process.on('log', console.error)
-}
+// Generates our dependency graph documents in DEPENDENCIES.md.
// To re-create npm-cli-repos.txt run:
-/* eslint-disable-next-line max-len */
-// npx --package=@npmcli/stafftools@latest gh repos --json | json -a name | sort > scripts/npm-cli-repos.txt
-const repos = fs.readFileSync('./scripts/npm-cli-repos.txt', 'utf8').trim().split('\n')
+// npx -p @npmcli/stafftools gh repos --json | json -a name | sort > scripts/npm-cli-repos.txt
+const repos = readFileSync(join(CWD, 'scripts', 'npm-cli-repos.txt'), 'utf-8').trim().split('\n')
// these have a different package name than the repo name, and are ours.
const aliases = {
@@ -85,18 +77,14 @@ function stripName (name) {
const main = async function () {
// add all of the cli's public workspaces as package names
- const workspaces = await mapWorkspaces({ pkg: require('../package.json') })
- for (const [key, value] of workspaces.entries()) {
- if (!require(value + '/package.json').private) {
- repos.push(key)
+ for (const { name, pkg: ws } of await pkg.mapWorkspaces()) {
+ if (!ws.private) {
+ repos.push(name)
}
}
- const arborist = new Arborist({
- prefix: process.cwd(),
- path: process.cwd(),
- })
- const tree = await arborist.loadVirtual({ path: process.cwd(), name: 'npm' })
+ const arborist = new Arborist({ prefix: CWD, path: CWD })
+ const tree = await arborist.loadVirtual({ path: CWD, name: 'npm' })
tree.name = 'npm'
const [annotationsOurs, heirarchyOurs] = walk(tree, true)
@@ -125,8 +113,8 @@ const main = async function () {
'',
` - ${heirarchyOurs.reverse().join('\n - ')}`,
]
- fs.writeFileSync('DEPENDENCIES.md', out.join('\n'))
- console.log('wrote to DEPENDENCIES.md')
+
+ return fs.writeFile(join(CWD, 'DEPENDENCIES.md'), out.join('\n'))
}
const walk = function (tree, onlyOurs) {
@@ -179,6 +167,7 @@ const walk = function (tree, onlyOurs) {
return [annotations, heirarchy]
}
+
const iterate = function (node, dependedBy, annotations, onlyOurs) {
if (!dependedBy[node.packageName]) {
dependedBy[node.packageName] = new Set()
@@ -198,9 +187,4 @@ const iterate = function (node, dependedBy, annotations, onlyOurs) {
}
}
-main().then(() => {
- return process.exit(0)
-}).catch(err => {
- console.error(err)
- return process.exit(1)
-})
+run(main)
diff --git a/scripts/git-dirty.js b/scripts/git-dirty.js
index 5730ed900..1c8648569 100644
--- a/scripts/git-dirty.js
+++ b/scripts/git-dirty.js
@@ -1,17 +1,3 @@
-#!/usr/bin/env node
-const { spawnSync } = require('child_process')
-const changes = spawnSync('git', ['status', '--porcelain', '-uall'])
-const stdout = changes.stdout.toString('utf8')
-const stderr = changes.stderr.toString('utf8')
-const { status, signal } = changes
-console.log(stdout)
-console.error(stderr)
-if (status || signal) {
- console.error({ status, signal })
- process.exitCode = status || 1
-}
-if (stdout.trim() !== '') {
- throw new Error('git dirty')
-} else {
- console.log('git clean')
-}
+const { run, git } = require('./util.js')
+
+run(git.dirty)
diff --git a/scripts/publish-tag.js b/scripts/publish-tag.js
deleted file mode 100644
index fb8a48233..000000000
--- a/scripts/publish-tag.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var semver = require('semver')
-var version = semver.parse(require('../package.json').version)
-console.log('next-%s', version.major)
diff --git a/scripts/publish.js b/scripts/publish.js
new file mode 100644
index 000000000..536c5d764
--- /dev/null
+++ b/scripts/publish.js
@@ -0,0 +1,110 @@
+const semver = require('semver')
+const log = require('proc-log')
+const pacote = require('pacote')
+const { run, git, npm, pkg, spawn } = require('./util.js')
+
+const resetdeps = () => npm('run', 'resetdeps')
+
+const op = () => spawn('op', 'item', 'get', 'npm', '--otp', { out: true, ok: true })
+
+const TAGS = {
+ // cli is always published to next-MAJOR
+ root: (v) => ({ tag: `next-${semver.major(v)}` }),
+ // workspaces are always published to latest, except prereleases
+ workspace: () => ({ tag: 'latest', preTag: 'prerelease' }),
+}
+
+const needsPublish = async ({ pkg: { private, name, version }, force, tags: getTags }) => {
+ if (private) {
+ return
+ }
+
+ const tags = getTags(version)
+ const tag = semver.parse(version).prerelease.length && tags.preTag
+ ? tags.preTag
+ : tags.tag
+
+ if (force) {
+ return tag
+ }
+
+ const mani = await pacote.manifest(`${name}@${tag}`, { preferOnline: true })
+ if (version !== mani.version) {
+ return tag
+ }
+}
+
+const getPublishes = async ({ force }) => {
+ const publish = []
+
+ for (const { name, pkg: ws } of await pkg.mapWorkspaces()) {
+ publish.push({
+ workspace: name,
+ tag: await needsPublish({
+ force,
+ pkg: ws,
+ tags: TAGS.workspace,
+ }),
+ })
+ }
+
+ publish.push({
+ tag: await needsPublish({
+ force,
+ pkg,
+ tags: TAGS.root,
+ }),
+ })
+
+ return publish.filter(p => p.tag)
+}
+
+const main = async (opts) => {
+ const packOnly = opts.pack || opts.packDestination
+ const publishes = await getPublishes({ force: packOnly })
+
+ if (!publishes.length) {
+ throw new Error(
+ 'Nothing to publish, exiting. ' +
+ 'All packages to publish should have their version bumped before running this script.'
+ )
+ }
+
+ log.info('publish', '\n' + publishes.map(JSON.stringify).join('\n'))
+
+ await git('clean', '-fd')
+ await resetdeps()
+ await npm('ls', '--omit=dev', { quiet: true })
+ await npm('rm', '--global', '--force', 'npm')
+ await npm('link', '--force', '--ignore-scripts')
+
+ if (opts.test) {
+ await npm('run', 'lint-all', '--ignore-scripts')
+ await npm('run', 'postlint', '--ignore-scripts')
+ await npm('run', 'test-all', '--ignore-scripts')
+ }
+
+ await npm('prune', '--omit=dev', '--no-save', '--no-audit', '--no-fund')
+ await git.dirty()
+
+ for (const p of publishes) {
+ const workspace = p.workspace && `--workspace=${p.workspace}`
+ if (packOnly) {
+ await npm(
+ 'pack',
+ workspace,
+ opts.packDestination && `--pack-destination=${opts.packDestination}`
+ )
+ } else {
+ await npm(
+ 'publish',
+ workspace,
+ `--tag=${p.tag}`,
+ opts.dryRun && '--dry-run',
+ opts.otp && `--otp=${opts.otp === 'op' ? await op() : opts.otp}`
+ )
+ }
+ }
+}
+
+run(main).catch(resetdeps)
diff --git a/scripts/rebuild.js b/scripts/rebuild.js
new file mode 100644
index 000000000..f3f75090c
--- /dev/null
+++ b/scripts/rebuild.js
@@ -0,0 +1,20 @@
+const { join } = require('path')
+const { promisify } = require('util')
+const glob = promisify(require('glob'))
+const log = require('proc-log')
+const { npm, run } = require('./util')
+
+const main = async (pkgNames) => {
+ for (const name of pkgNames) {
+ const { path } = await npm.query(`#${name}`).then(r => r[0])
+ const binding = await glob(join(path, '**', 'binding.node'))
+ log.info(name, binding)
+ if (!binding.length) {
+ await npm('rebuild', name)
+ } else {
+ log.info(`skipping ${name}, already built`)
+ }
+ }
+}
+
+run(({ argv }) => main(argv.remain))
diff --git a/scripts/release.sh b/scripts/release.sh
deleted file mode 100644
index a3c1356b0..000000000
--- a/scripts/release.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env bash
-
-# script for creating a zip and tarball for inclusion in node
-
-unset CDPATH
-
-set -e
-
-rm -rf release *.tgz || true
-rm node_modules/node-gyp/gyp/pylib/gyp/__pycache__/*.pyc || true
-rm node_modules/node-gyp/gyp/pylib/gyp/generator/__pycache__/*.pyc || true
-mkdir release
-node ./bin/npm-cli.js pack --loglevel error >/dev/null
-mv *.tgz release
-cd release
-tar xzf *.tgz
-cp ../.npmrc package/
-cp -r ../tap-snapshots package/
-cp -r ../test package/
-
-mkdir node_modules
-mv package node_modules/npm
-
-# make the zip for windows users
-cp node_modules/npm/bin/*.cmd .
-zipname=npm-$(node ../bin/npm-cli.js -v).zip
-zip -q -9 -r -X "$zipname" *.cmd node_modules
-
-# make the tar for node's deps
-cd node_modules
-tarname=npm-$(node ../../bin/npm-cli.js -v).tgz
-tar czf "$tarname" npm
-
-cd ..
-mv "node_modules/$tarname" .
-
-rm -rf *.cmd
-rm -rf node_modules
-
-cd ..
-
-echo "release/$tarname"
-echo "release/$zipname"
diff --git a/scripts/remove-files.js b/scripts/remove-files.js
new file mode 100644
index 000000000..75b438522
--- /dev/null
+++ b/scripts/remove-files.js
@@ -0,0 +1,11 @@
+const { join } = require('path')
+const { CWD, run, pkg, fs, git } = require('./util.js')
+
+const main = async () => {
+ await git.dirty()
+ for (const p of pkg.files) {
+ await fs.rimraf(join(CWD, p))
+ }
+}
+
+run(main)
diff --git a/scripts/resetdeps.js b/scripts/resetdeps.js
new file mode 100644
index 000000000..f0aad9753
--- /dev/null
+++ b/scripts/resetdeps.js
@@ -0,0 +1,25 @@
+
+const { join } = require('path')
+const { CWD, run, pkg, fs, spawn, git, npm } = require('./util.js')
+
+const checkout = () => git('checkout', 'node_modules/')
+
+const main = async ({ packageLock }) => {
+ await fs.rimraf(join(CWD, 'node_modules'))
+ for (const { path } of await pkg.mapWorkspaces()) {
+ await fs.rimraf(join(path, 'node_modules'))
+ }
+
+ await checkout()
+ await npm('i', '--ignore-scripts', '--no-audit', '--no-fund', packageLock && '--package-lock')
+ await npm('rebuild', '--ignore-scripts')
+ await npm('run', 'dependencies', '--ignore-scripts')
+ if (process.env.CI) {
+ // this script can take awhile to rebuild the cmark-gfm bindings
+ // so we only run it in CI. locally this is handled by pretest and
+ // prebuild scripts, which don't run in CI due to --ignore-scripts
+ await spawn('node', join('scripts', 'rebuild.js'), 'cmark-gfm')
+ }
+}
+
+run(main).catch(checkout)
diff --git a/scripts/resetdeps.sh b/scripts/resetdeps.sh
deleted file mode 100755
index 3172f8c86..000000000
--- a/scripts/resetdeps.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-set -e
-set -x
-rm -rf node_modules
-rm -rf docs/node_modules
-rm -rf smoke-tests/node_modules
-rm -rf "workspaces/*/node_modules"
-git checkout node_modules
-node . i --ignore-scripts --no-audit --no-fund "$@"
-node . rebuild --ignore-scripts
-node . run dependencies --ignore-scripts
-# check for cmark-gfm bindings
-cmarkbinding=$(find `node . ls cmark-gfm --parseable \
-| head -n 1` -name binding.node)
-if [[ ! $cmarkbinding ]]; then
- node . rebuild cmark-gfm
-fi
diff --git a/scripts/template-oss/_step-audit.yml b/scripts/template-oss/_step-audit.yml
new file mode 100644
index 000000000..c8002e305
--- /dev/null
+++ b/scripts/template-oss/_step-audit.yml
@@ -0,0 +1,2 @@
+- name: Run Audit
+ run: {{ rootNpmPath }} audit -iwr -w workspaces
diff --git a/scripts/template-oss/_step-test.yml b/scripts/template-oss/_step-test.yml
index 3eb0aa897..9471e6a5a 100644
--- a/scripts/template-oss/_step-test.yml
+++ b/scripts/template-oss/_step-test.yml
@@ -1,8 +1,3 @@
-- name: Link
- if: matrix
- run: {{ rootNpmPath }} link -f --ignore-scripts
-- name: Rebuild cmark-gfm
- run: {{ rootNpmPath }} rebuild cmark-gfm
{{> defaultStepTest }}
- name: Check Git Status
if: matrix && matrix.platform.os != 'windows-latest'
diff --git a/scripts/template-oss/audit.yml b/scripts/template-oss/audit.yml
deleted file mode 100644
index 3859c5e3d..000000000
--- a/scripts/template-oss/audit.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-name: Audit
-
-on:
- workflow_dispatch:
- schedule:
- # "At 08:00 UTC (01:00 PT) on Monday" https://crontab.guru/#0_8_*_*_1
- - cron: "0 8 * * 1"
-
-jobs:
- audit:
- {{> job jobName="Audit Dependencies" jobDepFlags="--package-lock" }}
- - name: Run Audit
- run: {{ rootNpmPath }} audit -iwr -w workspaces
diff --git a/scripts/template-oss/ci-release.yml b/scripts/template-oss/ci-release.yml
index 6d3095371..b571511c4 100644
--- a/scripts/template-oss/ci-release.yml
+++ b/scripts/template-oss/ci-release.yml
@@ -11,17 +11,11 @@
run: |
NPM_VERSION="$({{ rootNpmPath }} --version)-$GITHUB_SHA.0"
{{ rootNpmPath }} version $NPM_VERSION --ignore-scripts
- {{ rootNpmPath }} run resetdeps
- git clean -fd
- {{ rootNpmPath }} ls --omit=dev >/dev/null
- {{ rootNpmPath }} prune --omit=dev --no-save --no-audit --no-fund
- node scripts/git-dirty.js
- {{ rootNpmPath }} pack --pack-destination=$RUNNER_TEMP
- {{ rootNpmPath }} install -g $RUNNER_TEMP/npm-$NPM_VERSION.tgz
+ node scripts/publish.js --pack-destination=$RUNNER_TEMP
+ {{ rootNpmPath }} install --global $RUNNER_TEMP/npm-$NPM_VERSION.tgz
{{ rootNpmPath }} install -w smoke-tests --ignore-scripts --no-audit --no-fund
- rm -rf {lib,bin,index.js}
- # this one should be npm since we explicitly installed our packed
- # tarball globally and the next test will make sure our the new
- # globally installed version contains the git sha
+ node scripts/remove-files.js
+ # call installed npm instead of local source since we are testing
+ # the packed tarball that we just installed globally
SMOKE_PUBLISH_NPM=1 npm test -w smoke-tests --ignore-scripts
{{> stepChecks jobCheck=true }}
diff --git a/scripts/template-oss/create-node-pr.yml b/scripts/template-oss/create-node-pr.yml
new file mode 100644
index 000000000..23b267d58
--- /dev/null
+++ b/scripts/template-oss/create-node-pr.yml
@@ -0,0 +1,28 @@
+name: "Create Node PR"
+
+on:
+ workflow_dispatch:
+ inputs:
+ spec:
+ description: "The npm spec to create the PR from"
+ required: true
+ default: 'latest'
+ dryRun:
+ description: "Setting this to anything will run all the steps except opening the PR"
+
+jobs:
+ create-pull-request:
+ {{> job jobName="Create Node PR" }}
+ - name: Checkout Node
+ uses: actions/checkout@v3
+ with:
+ token: $\{{ secrets.NODE_PULL_REQUEST_TOKEN }}
+ repository: nodejs/node
+ fetch-depth: 0
+ path: node
+ - name: Create Node Pull Request
+ env:
+ GITHUB_TOKEN: $\{{ secrets.NODE_PULL_REQUEST_TOKEN }}
+ run: |
+ DRY_RUN=$([ -z "$\{{ inputs.dryRun }}" ] && echo "" || echo "--dry-run")
+ node scripts/create-node-pr.js "$\{{ inputs.spec }}" "$DRY_RUN"
diff --git a/scripts/template-oss/root.js b/scripts/template-oss/root.js
index 13bd4c5fa..cb59c473e 100644
--- a/scripts/template-oss/root.js
+++ b/scripts/template-oss/root.js
@@ -1,13 +1,13 @@
module.exports = {
rootRepo: {
add: {
- '.github/ISSUE_TEMPLATE/config.yml': false,
- '.github/ISSUE_TEMPLATE/bug.yml': false,
'.github/workflows/ci.yml': 'ci.yml',
'.github/workflows/ci-release.yml': 'ci-release.yml',
+ '.github/workflows/create-node-pr.yml': 'create-node-pr.yml',
+ '.github/ISSUE_TEMPLATE/bug.yml': false,
+ '.github/ISSUE_TEMPLATE/config.yml': false,
'.github/dependabot.yml': false,
'.github/workflows/post-dependabot.yml': false,
- '.github/workflows/audit.yml': 'audit.yml',
},
},
workspaceRepo: {
@@ -23,19 +23,16 @@ module.exports = {
defaultBranch: 'latest',
distPaths: [
'index.js',
- 'docs/content/**/*.md',
- 'docs/output/**/*.html',
- 'man',
+ 'docs/content/',
+ 'docs/output/',
+ 'man/',
],
allowPaths: [
'/node_modules/',
'/index.js',
- '/Makefile',
- '/make.bat',
'/DEPENDENCIES.md',
'/CONTRIBUTING.md',
'/configure',
- '/changelogs/',
'/AUTHORS',
'/.mailmap',
'/.licensee.json',
diff --git a/scripts/update-authors.js b/scripts/update-authors.js
new file mode 100755
index 000000000..23c443057
--- /dev/null
+++ b/scripts/update-authors.js
@@ -0,0 +1,26 @@
+const { join } = require('path')
+const { CWD, run, git, fs } = require('./util.js')
+
+const main = async () => {
+ const allAuthors = await git('log', '--use-mailmap', '--reverse', '--format=%aN <%aE>', {
+ lines: true,
+ })
+
+ const authors = new Set()
+ for (const author of allAuthors) {
+ if (
+ !author.includes('[bot]') &&
+ !author.startsWith('npm team') &&
+ !author.startsWith('npm CLI robot')
+ ) {
+ authors.add(author)
+ }
+ }
+
+ return fs.writeFile(join(CWD, 'AUTHORS'), [
+ `# Authors sorted by whether or not they're me`,
+ ...authors,
+ ].join('\n'))
+}
+
+run(main)
diff --git a/scripts/update-authors.sh b/scripts/update-authors.sh
deleted file mode 100755
index a9c9a665a..000000000
--- a/scripts/update-authors.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-git log --use-mailmap --reverse --format='%aN <%aE>' | grep -v -e "\[bot\]" -e "^npm team" -e "^npm CLI robot" | perl -wnE '
-BEGIN {
- say "# Authors sorted by whether or not they\x27re me";
-}
-
-print $seen{$_} = $_ unless $seen{$_}
-' > AUTHORS
diff --git a/scripts/util.js b/scripts/util.js
new file mode 100644
index 000000000..91611bcf9
--- /dev/null
+++ b/scripts/util.js
@@ -0,0 +1,200 @@
+const fsp = require('fs/promises')
+const { resolve, join, relative } = require('path')
+const { formatWithOptions } = require('util')
+const log = require('proc-log')
+const nopt = require('nopt')
+const npmGit = require('@npmcli/git')
+const promiseSpawn = require('@npmcli/promise-spawn')
+const mapWorkspaces = require('@npmcli/map-workspaces')
+
+const CWD = resolve(__dirname, '..')
+
+const pkg = require(join(CWD, 'package.json'))
+pkg.mapWorkspaces = async () => {
+ const ws = []
+ for (const [name, path] of await mapWorkspaces({ pkg })) {
+ ws.push({ name, path, pkg: require(join(path, 'package.json')) })
+ }
+ return ws
+}
+
+const fs = {
+ rimraf: (p) => fsp.rm(p, { recursive: true, force: true }),
+ mkdirp: (p) => fsp.mkdir(p, { recursive: true }),
+ clean: (p) => fs.rimraf(p).then(() => fs.mkdirp(p)),
+ rmAll: (p) => Promise.all(p.map(fs.rimraf)),
+ writeFile: async (p, d) => {
+ await fsp.writeFile(p, d.trim() + '\n', 'utf-8')
+ return `Wrote to ${relative(CWD, p)}`
+ },
+}
+
+// for spawn, allow a flat array of arguments where the
+// the last arg can optionall be an options object
+const getArgs = (allArgs) => {
+ let args = allArgs.flat().filter(Boolean)
+ let opts = {}
+
+ const last = args[args.length - 1]
+ if (typeof last === 'object') {
+ args = args.slice(0, -1)
+ opts = last
+ }
+
+ return { args, opts }
+}
+
+const spawn = async (cmd, ...allArgs) => {
+ const {
+ args,
+ opts: { ok, input, out, lines, quiet, ...opts },
+ } = getArgs(allArgs)
+
+ log.info('spawn', `${cmd} ${args.join(' ')}`)
+
+ let res = null
+ try {
+ const spawnOpts = {
+ stdioString: true,
+ stdio: quiet || out || lines ? 'pipe' : 'inherit',
+ cwd: CWD,
+ ...opts,
+ }
+ const proc = cmd === 'git' ? npmGit.spawn(args, spawnOpts) : promiseSpawn(cmd, args, spawnOpts)
+ if (input && proc.stdin) {
+ proc.stdin.write(input)
+ proc.stdin.end()
+ }
+ res = await proc
+ } catch (err) {
+ if (!ok) {
+ throw err
+ }
+ log.info('suppressed error', err.message)
+ }
+
+ if (res?.stdout) {
+ res.stdout = res.stdout.toString().trim()
+ if (res.stdout) {
+ log.silly('stdout', res.stdout)
+ }
+ }
+
+ if (res?.stderr) {
+ res.stderr = res.stderr.toString().trim()
+ if (res.stderr) {
+ log.silly('stderr', res.stderr)
+ }
+ }
+
+ if (lines) {
+ return (res?.stdout || '')
+ .split('\n')
+ .map(l => l.trim())
+ .filter(Boolean)
+ }
+
+ if (out) {
+ return res?.stdout || ''
+ }
+
+ return res
+}
+
+// allows for creating spawn functions with a prefilled
+// command and checking if the last arg is an options obj
+spawn.create = (cmd, ...prefillArgs) => (...cmdArgs) => {
+ const prefill = getArgs(prefillArgs)
+ const command = getArgs(cmdArgs)
+ return spawn(
+ cmd,
+ [...prefill.args, ...command.args],
+ { ...prefill.opts, ...command.opts }
+ )
+}
+
+const npm = spawn.create('node', '.')
+npm.query = (...args) => npm('query', ...args, { out: true }).then(JSON.parse)
+
+const git = spawn.create('git')
+git.dirty = () => npmGit.isClean({ cwd: CWD }).then(async r => {
+ if (r) {
+ return 'git clean'
+ }
+ await git('status', '--porcelain=v1', '-uno')
+ throw new Error('git dirty')
+})
+
+const gh = spawn.create('gh')
+gh.json = async (...args) => {
+ const keys = args.pop()
+ let data = await gh(...args, '--json', keys, { out: true }).then(JSON.parse)
+ if (keys.split(',').length === 1) {
+ data = data[keys]
+ }
+ return data
+}
+
+const run = async (main) => {
+ const argv = {}
+ for (const [k, v] of Object.entries(nopt({}, {}, process.argv))) {
+ argv[k] = v
+ // create camelcase key too
+ argv[k.replace(/-([a-z])/g, (_, c) => c.toUpperCase())] = v
+ }
+
+ process.on('log', (l, ...args) => {
+ if (argv.debug || process.env.CI || l === 'error') {
+ for (const line of formatWithOptions({ colors: true }, ...args).split('\n')) {
+ // eslint-disable-next-line no-console
+ console.error(l.slice(0, 4).toUpperCase(), line)
+ }
+ }
+ })
+
+ log.silly('argv', argv)
+
+ try {
+ const res = await main(argv)
+ if (res) {
+ // eslint-disable-next-line no-console
+ console.log(res)
+ }
+ } catch (err) {
+ process.exitCode = err.status || 1
+
+ const messages = []
+ if (err.args) {
+ // its an error from promise-spawn
+ for (const [name, value] of Object.entries(err)) {
+ if (value) {
+ let msg = Array.isArray(value) ? value.join(' ') : value.toString()
+ let sep = ' '
+ if (msg.includes('\n')) {
+ msg = ' ' + msg.split('\n').map(l => l.trim()).join('\n ').trim()
+ sep = '\n'
+ }
+ messages.push(`${name}:${sep}${msg}`)
+ }
+ // delete from error object so we can log them separately
+ delete err[name]
+ }
+ }
+
+ log.error(err)
+ if (messages.length) {
+ log.error(messages.join('\n'))
+ }
+ }
+}
+
+module.exports = {
+ CWD,
+ pkg,
+ run,
+ fs,
+ spawn,
+ gh,
+ npm,
+ git,
+}