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:
authorLuke Karrys <luke@lukekarrys.com>2022-10-21 20:41:40 +0300
committerGar <wraithgar@github.com>2022-11-01 20:19:36 +0300
commit9709ae60b780410526ab2117519eba6f97d5972c (patch)
treebc3b6bbc8f61b6798d194b0e0ebd370959df355a
parent0c5834ed635833ef49fe10cc888025a5debebe21 (diff)
chore: rewrite `scripts/` with javascript
Goals of this rewrite: - Better portability of scripts to anywhere we can run `node` and no reliance on `make` or other tools - More code inside `scripts/` and less inside of CI workflows to allow for easier local testing - Reuse the same scripts for similar workflows (eg `publish` and `smoke-publish`) Future goals: - Allow testing of `scripts` Some highlights of the new scripts: `scripts/create-node-pr.js` - This now operates on cloned copy of the base repo that is pushed to our fork, so we no longer need to manually sync our fork. - Uses the published registry tarball for as much of the PR as possible, falling back to including local files from source. This will enable for easier migration to eventually only using the tarball contents. `scripts/publish.js` - Replaces `make publish` - Will publish all workspaces that need to be published, before publishing the CLI. - Makes running tests an optional part of the script, since CI now runs the tests. - Can optionally only pack the tarball, for use in CI to test installing the tarball. `scripts/util.js` - Shared utilities for spawning commands including helpers for `npm` and `gh`. - Common interface for running, parsing args, logging, and debugging of scripts.
-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,
+}