From a2fa41ed7d6b1105928238d029fd212094b76391 Mon Sep 17 00:00:00 2001 From: Luke Karrys Date: Wed, 21 Jun 2023 14:11:09 -0700 Subject: [PATCH] chore: normalize line endings and symlinks This makes it possible to do a fresh clone of this repo in Windows, and be able to run the resetdeps command successfully and then have a clean git status. We now check for a clean git status in during CI in Windows which was previously excluded. The changes required were to: - Delete our workspace symlinks from node_modules and add a step to resetdeps that will do a platform dependent symlink before the initial reification - Add line ending normalization to our `.gitattributes` file and commit the result. Git will store text with LF line endings automatically, except for some files like `cmd` scripts that need to be `crlf` and shell scripts that need to be `lf`. - Update workflows to call `node scripts/resetdeps.js` directly since a fresh clone of the repo wont have any symlinks in place, so any `node .` command will fail due to missing workspaces. Ref: npm/statusboard#562 --- .gitattributes | 29 ++++- .github/workflows/audit.yml | 4 +- .github/workflows/ci-libnpmaccess.yml | 9 +- .github/workflows/ci-libnpmdiff.yml | 9 +- .github/workflows/ci-libnpmexec.yml | 9 +- .github/workflows/ci-libnpmfund.yml | 9 +- .github/workflows/ci-libnpmhook.yml | 9 +- .github/workflows/ci-libnpmorg.yml | 9 +- .github/workflows/ci-libnpmpack.yml | 9 +- .github/workflows/ci-libnpmpublish.yml | 9 +- .github/workflows/ci-libnpmsearch.yml | 9 +- .github/workflows/ci-libnpmteam.yml | 9 +- .github/workflows/ci-libnpmversion.yml | 9 +- .github/workflows/ci-npmcli-arborist.yml | 9 +- .github/workflows/ci-npmcli-config.yml | 9 +- .github/workflows/ci-npmcli-docs.yml | 15 ++- .github/workflows/ci-npmcli-mock-globals.yml | 9 +- .github/workflows/ci-npmcli-mock-registry.yml | 9 +- .github/workflows/ci-npmcli-smoke-tests.yml | 9 +- .github/workflows/ci-release.yml | 13 ++- .github/workflows/ci.yml | 17 ++- .github/workflows/create-node-pr.yml | 4 +- .github/workflows/node-integration.yml | 4 +- .github/workflows/pull-request.yml | 4 +- .github/workflows/release.yml | 8 +- bin/npm.cmd | 38 +++---- bin/npx.cmd | 40 +++---- node_modules/.gitignore | 15 +-- node_modules/@npmcli/arborist | 1 - node_modules/@npmcli/config | 1 - node_modules/libnpmaccess | 1 - node_modules/libnpmdiff | 1 - node_modules/libnpmexec | 1 - node_modules/libnpmfund | 1 - node_modules/libnpmhook | 1 - node_modules/libnpmorg | 1 - node_modules/libnpmpack | 1 - node_modules/libnpmpublish | 1 - node_modules/libnpmsearch | 1 - node_modules/libnpmteam | 1 - node_modules/libnpmversion | 1 - .../qrcode-terminal/example/basic.png | Bin 46426 -> 0 bytes scripts/bundle-and-gitignore-deps.js | 103 +++++++++--------- scripts/dependency-graph.js | 9 +- scripts/npm-cli-repos.txt | 4 - scripts/resetdeps.js | 22 ++-- scripts/template-oss/_step-deps.yml | 4 +- scripts/template-oss/_step-test.yml | 1 - scripts/template-oss/ci-npmcli-docs.yml | 2 +- scripts/template-oss/node-integration.yml | 4 +- scripts/update-authors.js | 4 +- scripts/util.js | 7 +- workspaces/arborist/test/fixtures/index.js | 15 ++- .../node_modules/json-schema/package.json | 62 +++++------ 54 files changed, 339 insertions(+), 246 deletions(-) delete mode 120000 node_modules/@npmcli/arborist delete mode 120000 node_modules/@npmcli/config delete mode 120000 node_modules/libnpmaccess delete mode 120000 node_modules/libnpmdiff delete mode 120000 node_modules/libnpmexec delete mode 120000 node_modules/libnpmfund delete mode 120000 node_modules/libnpmhook delete mode 120000 node_modules/libnpmorg delete mode 120000 node_modules/libnpmpack delete mode 120000 node_modules/libnpmpublish delete mode 120000 node_modules/libnpmsearch delete mode 120000 node_modules/libnpmteam delete mode 120000 node_modules/libnpmversion delete mode 100644 node_modules/qrcode-terminal/example/basic.png mode change 100755 => 100644 scripts/update-authors.js diff --git a/.gitattributes b/.gitattributes index ef4b94f9e45f9..5bfd3199c0181 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,27 @@ -/node_modules/** linguist-generated=false -/package-lock.json linguist-generated=false +# normalize all line endings by default +* text=auto + +# our shell/bin scripts always need to be LF +/bin/* text eol=lf +/workspaces/arborist/bin/index.js text eol=lf +/configure text eol=lf + +# our cmd scripts always need to be CRLF +/bin/*.cmd text eol=crlf + +# ignore all line endings in node_modules since we dont control that +/node_modules/** -text + +# the files we write should be LF so they can be generated cross platform +/node_modules/.gitignore text eol=lf +/workspaces/arborist/test/fixtures/.gitignore text eol=lf +/DEPENDENCIES.md text eol=lf +/AUTHORS text eol=lf + +# fixture tarballs should be treated as binary +/workspaces/*/test/fixtures/**/*.tgz binary + +# these hint to GitHub to show these files as not generated so they default to +# showing the full diff in pull requests +/node_modules/** linguist-generated=false +/package-lock.json linguist-generated=false diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index fa272ea63ee22..806706c2e6bff 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -28,8 +28,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps -- --package-lock + run: node scripts/resetdeps.js --package-lock - name: Run Production Audit run: node . audit --omit=dev - name: Run Full Audit diff --git a/.github/workflows/ci-libnpmaccess.yml b/.github/workflows/ci-libnpmaccess.yml index e73e76f6cf013..3e56273ade42b 100644 --- a/.github/workflows/ci-libnpmaccess.yml +++ b/.github/workflows/ci-libnpmaccess.yml @@ -37,8 +37,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts -w libnpmaccess - name: Post Lint @@ -83,12 +85,13 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts -w libnpmaccess - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js diff --git a/.github/workflows/ci-libnpmdiff.yml b/.github/workflows/ci-libnpmdiff.yml index 02dd24d48c718..6a74d24504739 100644 --- a/.github/workflows/ci-libnpmdiff.yml +++ b/.github/workflows/ci-libnpmdiff.yml @@ -37,8 +37,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts -w libnpmdiff - name: Post Lint @@ -83,12 +85,13 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts -w libnpmdiff - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js diff --git a/.github/workflows/ci-libnpmexec.yml b/.github/workflows/ci-libnpmexec.yml index 5f73f3bf05b9c..a75f741c7414e 100644 --- a/.github/workflows/ci-libnpmexec.yml +++ b/.github/workflows/ci-libnpmexec.yml @@ -37,8 +37,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts -w libnpmexec - name: Post Lint @@ -83,12 +85,13 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts -w libnpmexec - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js diff --git a/.github/workflows/ci-libnpmfund.yml b/.github/workflows/ci-libnpmfund.yml index 114446ace98fe..8f9dfb9a18b20 100644 --- a/.github/workflows/ci-libnpmfund.yml +++ b/.github/workflows/ci-libnpmfund.yml @@ -37,8 +37,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts -w libnpmfund - name: Post Lint @@ -83,12 +85,13 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts -w libnpmfund - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js diff --git a/.github/workflows/ci-libnpmhook.yml b/.github/workflows/ci-libnpmhook.yml index 414e122591cca..ff923dc266994 100644 --- a/.github/workflows/ci-libnpmhook.yml +++ b/.github/workflows/ci-libnpmhook.yml @@ -37,8 +37,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts -w libnpmhook - name: Post Lint @@ -83,12 +85,13 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts -w libnpmhook - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js diff --git a/.github/workflows/ci-libnpmorg.yml b/.github/workflows/ci-libnpmorg.yml index 89140eed3cd11..0b02427902ff1 100644 --- a/.github/workflows/ci-libnpmorg.yml +++ b/.github/workflows/ci-libnpmorg.yml @@ -37,8 +37,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts -w libnpmorg - name: Post Lint @@ -83,12 +85,13 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts -w libnpmorg - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js diff --git a/.github/workflows/ci-libnpmpack.yml b/.github/workflows/ci-libnpmpack.yml index 2f9e787941395..712a75df99f1c 100644 --- a/.github/workflows/ci-libnpmpack.yml +++ b/.github/workflows/ci-libnpmpack.yml @@ -37,8 +37,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts -w libnpmpack - name: Post Lint @@ -83,12 +85,13 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts -w libnpmpack - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js diff --git a/.github/workflows/ci-libnpmpublish.yml b/.github/workflows/ci-libnpmpublish.yml index cbd72f52d4f58..0fe5a8a2b5ebf 100644 --- a/.github/workflows/ci-libnpmpublish.yml +++ b/.github/workflows/ci-libnpmpublish.yml @@ -37,8 +37,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts -w libnpmpublish - name: Post Lint @@ -83,12 +85,13 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts -w libnpmpublish - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js diff --git a/.github/workflows/ci-libnpmsearch.yml b/.github/workflows/ci-libnpmsearch.yml index 7c11951b8c858..2ae995a683317 100644 --- a/.github/workflows/ci-libnpmsearch.yml +++ b/.github/workflows/ci-libnpmsearch.yml @@ -37,8 +37,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts -w libnpmsearch - name: Post Lint @@ -83,12 +85,13 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts -w libnpmsearch - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js diff --git a/.github/workflows/ci-libnpmteam.yml b/.github/workflows/ci-libnpmteam.yml index c89c09fcf12b1..6adb53c0c3e0f 100644 --- a/.github/workflows/ci-libnpmteam.yml +++ b/.github/workflows/ci-libnpmteam.yml @@ -37,8 +37,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts -w libnpmteam - name: Post Lint @@ -83,12 +85,13 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts -w libnpmteam - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js diff --git a/.github/workflows/ci-libnpmversion.yml b/.github/workflows/ci-libnpmversion.yml index 6fa4a45b4c4dd..0e502ff4329f2 100644 --- a/.github/workflows/ci-libnpmversion.yml +++ b/.github/workflows/ci-libnpmversion.yml @@ -37,8 +37,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts -w libnpmversion - name: Post Lint @@ -83,12 +85,13 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts -w libnpmversion - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js diff --git a/.github/workflows/ci-npmcli-arborist.yml b/.github/workflows/ci-npmcli-arborist.yml index e1a7f82a04549..cfd3d14bf3835 100644 --- a/.github/workflows/ci-npmcli-arborist.yml +++ b/.github/workflows/ci-npmcli-arborist.yml @@ -37,8 +37,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts -w @npmcli/arborist - name: Post Lint @@ -83,12 +85,13 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts -w @npmcli/arborist - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js diff --git a/.github/workflows/ci-npmcli-config.yml b/.github/workflows/ci-npmcli-config.yml index 72cc302e721ad..a7a4a49e9fe2b 100644 --- a/.github/workflows/ci-npmcli-config.yml +++ b/.github/workflows/ci-npmcli-config.yml @@ -37,8 +37,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts -w @npmcli/config - name: Post Lint @@ -83,12 +85,13 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts -w @npmcli/config - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js diff --git a/.github/workflows/ci-npmcli-docs.yml b/.github/workflows/ci-npmcli-docs.yml index 017d354a538fc..705bdb953b04e 100644 --- a/.github/workflows/ci-npmcli-docs.yml +++ b/.github/workflows/ci-npmcli-docs.yml @@ -37,8 +37,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts -w @npmcli/docs - name: Post Lint @@ -78,14 +80,15 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts -w @npmcli/docs - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js compare-docs: @@ -109,8 +112,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Build Docs run: | node . run build -w docs @@ -121,7 +126,7 @@ jobs: run: | git clean -fd git checkout ${{ github.event.pull_request.base.ref }} - node . run resetdeps + node scripts/resetdeps.js node . run build -w docs - name: Diff Man run: diff -r --color=always man/ man-update/ || true diff --git a/.github/workflows/ci-npmcli-mock-globals.yml b/.github/workflows/ci-npmcli-mock-globals.yml index 60f85f7c7795f..9ab65a816c35b 100644 --- a/.github/workflows/ci-npmcli-mock-globals.yml +++ b/.github/workflows/ci-npmcli-mock-globals.yml @@ -37,8 +37,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts -w @npmcli/mock-globals - name: Post Lint @@ -83,12 +85,13 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts -w @npmcli/mock-globals - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js diff --git a/.github/workflows/ci-npmcli-mock-registry.yml b/.github/workflows/ci-npmcli-mock-registry.yml index db394f789c9f8..01832e08fb35d 100644 --- a/.github/workflows/ci-npmcli-mock-registry.yml +++ b/.github/workflows/ci-npmcli-mock-registry.yml @@ -37,8 +37,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts -w @npmcli/mock-registry - name: Post Lint @@ -83,12 +85,13 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts -w @npmcli/mock-registry - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js diff --git a/.github/workflows/ci-npmcli-smoke-tests.yml b/.github/workflows/ci-npmcli-smoke-tests.yml index d6103908fcff7..68de458721e3c 100644 --- a/.github/workflows/ci-npmcli-smoke-tests.yml +++ b/.github/workflows/ci-npmcli-smoke-tests.yml @@ -37,8 +37,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts -w @npmcli/smoke-tests - name: Post Lint @@ -83,12 +85,13 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts -w @npmcli/smoke-tests - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js diff --git a/.github/workflows/ci-release.yml b/.github/workflows/ci-release.yml index 821d4a37368a3..5361cd8518b5d 100644 --- a/.github/workflows/ci-release.yml +++ b/.github/workflows/ci-release.yml @@ -83,8 +83,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts -ws -iwr --if-present - name: Post Lint @@ -181,14 +183,15 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts -ws -iwr --if-present - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js - name: Conclude Check uses: LouisBrunner/checks-action@v1.3.1 @@ -283,8 +286,10 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Pack env: SMOKE_PUBLISH_NPM: 1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 485b9bc9245c9..5a55044f70e9d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,8 +45,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Lint run: node . run lint --ignore-scripts - name: Post Lint @@ -91,14 +93,15 @@ jobs: with: node-version: ${{ matrix.node-version }} cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Add Problem Matcher run: echo "::add-matcher::.github/matchers/tap.json" - name: Test run: node . test --ignore-scripts - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js licenses: @@ -120,8 +123,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Check Licenses run: node . run licenses @@ -144,8 +149,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Run Smoke Tests run: node . test -w smoke-tests --ignore-scripts - name: Check Git Status diff --git a/.github/workflows/create-node-pr.yml b/.github/workflows/create-node-pr.yml index f5cb5e88c8c2a..2825623093183 100644 --- a/.github/workflows/create-node-pr.yml +++ b/.github/workflows/create-node-pr.yml @@ -38,8 +38,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Checkout Node uses: actions/checkout@v3 with: diff --git a/.github/workflows/node-integration.yml b/.github/workflows/node-integration.yml index 64d7894f4934d..49beea2115d6f 100644 --- a/.github/workflows/node-integration.yml +++ b/.github/workflows/node-integration.yml @@ -106,7 +106,7 @@ jobs: echo "::group::packing npm release $npmVersion" pushd "$npmDir" >/dev/null - node . run resetdeps + node scripts/resetdeps.js npmtarball="$(node . pack --loglevel=silent --json | jq -r .[0].filename)" tar czf "$npmFile" -C "$npmDir" . popd >/dev/null @@ -204,7 +204,7 @@ jobs: echo "::endgroup::" echo "::group::npm run resetdeps" - node . run resetdeps + node scripts/resetdeps.js echo "::endgroup::" echo "::group::npm link" diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index c0c46fc557a80..1d9fd2b13eb4b 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -32,8 +32,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Run Commitlint on Commits id: commit continue-on-error: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 35f09773b1ea0..1584672aa2b61 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -47,8 +47,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Release Please id: release env: @@ -157,8 +159,10 @@ jobs: with: node-version: 18.x cache: npm + - name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: node . run resetdeps + run: node scripts/resetdeps.js - name: Run Post Pull Request Actions env: RELEASE_PR_NUMBER: ${{ needs.release.outputs.pr-number }} diff --git a/bin/npm.cmd b/bin/npm.cmd index f111c59d1efb6..880554dcdd686 100755 --- a/bin/npm.cmd +++ b/bin/npm.cmd @@ -1,19 +1,19 @@ -:: Created by npm, please don't edit manually. -@ECHO OFF - -SETLOCAL - -SET "NODE_EXE=%~dp0\node.exe" -IF NOT EXIST "%NODE_EXE%" ( - SET "NODE_EXE=node" -) - -SET "NPM_CLI_JS=%~dp0\node_modules\npm\bin\npm-cli.js" -FOR /F "delims=" %%F IN ('CALL "%NODE_EXE%" "%NPM_CLI_JS%" prefix -g') DO ( - SET "NPM_PREFIX_NPM_CLI_JS=%%F\node_modules\npm\bin\npm-cli.js" -) -IF EXIST "%NPM_PREFIX_NPM_CLI_JS%" ( - SET "NPM_CLI_JS=%NPM_PREFIX_NPM_CLI_JS%" -) - -"%NODE_EXE%" "%NPM_CLI_JS%" %* +:: Created by npm, please don't edit manually. +@ECHO OFF + +SETLOCAL + +SET "NODE_EXE=%~dp0\node.exe" +IF NOT EXIST "%NODE_EXE%" ( + SET "NODE_EXE=node" +) + +SET "NPM_CLI_JS=%~dp0\node_modules\npm\bin\npm-cli.js" +FOR /F "delims=" %%F IN ('CALL "%NODE_EXE%" "%NPM_CLI_JS%" prefix -g') DO ( + SET "NPM_PREFIX_NPM_CLI_JS=%%F\node_modules\npm\bin\npm-cli.js" +) +IF EXIST "%NPM_PREFIX_NPM_CLI_JS%" ( + SET "NPM_CLI_JS=%NPM_PREFIX_NPM_CLI_JS%" +) + +"%NODE_EXE%" "%NPM_CLI_JS%" %* diff --git a/bin/npx.cmd b/bin/npx.cmd index b79518ec50540..9339ebd065282 100755 --- a/bin/npx.cmd +++ b/bin/npx.cmd @@ -1,20 +1,20 @@ -:: Created by npm, please don't edit manually. -@ECHO OFF - -SETLOCAL - -SET "NODE_EXE=%~dp0\node.exe" -IF NOT EXIST "%NODE_EXE%" ( - SET "NODE_EXE=node" -) - -SET "NPM_CLI_JS=%~dp0\node_modules\npm\bin\npm-cli.js" -SET "NPX_CLI_JS=%~dp0\node_modules\npm\bin\npx-cli.js" -FOR /F "delims=" %%F IN ('CALL "%NODE_EXE%" "%NPM_CLI_JS%" prefix -g') DO ( - SET "NPM_PREFIX_NPX_CLI_JS=%%F\node_modules\npm\bin\npx-cli.js" -) -IF EXIST "%NPM_PREFIX_NPX_CLI_JS%" ( - SET "NPX_CLI_JS=%NPM_PREFIX_NPX_CLI_JS%" -) - -"%NODE_EXE%" "%NPX_CLI_JS%" %* +:: Created by npm, please don't edit manually. +@ECHO OFF + +SETLOCAL + +SET "NODE_EXE=%~dp0\node.exe" +IF NOT EXIST "%NODE_EXE%" ( + SET "NODE_EXE=node" +) + +SET "NPM_CLI_JS=%~dp0\node_modules\npm\bin\npm-cli.js" +SET "NPX_CLI_JS=%~dp0\node_modules\npm\bin\npx-cli.js" +FOR /F "delims=" %%F IN ('CALL "%NODE_EXE%" "%NPM_CLI_JS%" prefix -g') DO ( + SET "NPM_PREFIX_NPX_CLI_JS=%%F\node_modules\npm\bin\npx-cli.js" +) +IF EXIST "%NPM_PREFIX_NPX_CLI_JS%" ( + SET "NPX_CLI_JS=%NPM_PREFIX_NPX_CLI_JS%" +) + +"%NODE_EXE%" "%NPX_CLI_JS%" %* diff --git a/node_modules/.gitignore b/node_modules/.gitignore index a32136b521357..2ae24fcf8a16f 100644 --- a/node_modules/.gitignore +++ b/node_modules/.gitignore @@ -18,8 +18,6 @@ !/@isaacs/string-locale-compare !/@npmcli/ /@npmcli/* -!/@npmcli/arborist -!/@npmcli/config !/@npmcli/disparity-colors !/@npmcli/fs !/@npmcli/git @@ -138,17 +136,6 @@ !/jsonparse !/just-diff-apply !/just-diff -!/libnpmaccess -!/libnpmdiff -!/libnpmexec -!/libnpmfund -!/libnpmhook -!/libnpmorg -!/libnpmpack -!/libnpmpublish -!/libnpmsearch -!/libnpmteam -!/libnpmversion !/lru-cache !/make-fetch-happen !/minimatch @@ -330,3 +317,5 @@ __pycache__ .gitkeep *.map *.ts +*.png +*.jpg diff --git a/node_modules/@npmcli/arborist b/node_modules/@npmcli/arborist deleted file mode 120000 index a2d3e8bbf4641..0000000000000 --- a/node_modules/@npmcli/arborist +++ /dev/null @@ -1 +0,0 @@ -../../workspaces/arborist \ No newline at end of file diff --git a/node_modules/@npmcli/config b/node_modules/@npmcli/config deleted file mode 120000 index bf09f370d87e3..0000000000000 --- a/node_modules/@npmcli/config +++ /dev/null @@ -1 +0,0 @@ -../../workspaces/config \ No newline at end of file diff --git a/node_modules/libnpmaccess b/node_modules/libnpmaccess deleted file mode 120000 index b3a138bb62b43..0000000000000 --- a/node_modules/libnpmaccess +++ /dev/null @@ -1 +0,0 @@ -../workspaces/libnpmaccess \ No newline at end of file diff --git a/node_modules/libnpmdiff b/node_modules/libnpmdiff deleted file mode 120000 index 70ab2f9c6bbee..0000000000000 --- a/node_modules/libnpmdiff +++ /dev/null @@ -1 +0,0 @@ -../workspaces/libnpmdiff \ No newline at end of file diff --git a/node_modules/libnpmexec b/node_modules/libnpmexec deleted file mode 120000 index 6fc0a19cf63a4..0000000000000 --- a/node_modules/libnpmexec +++ /dev/null @@ -1 +0,0 @@ -../workspaces/libnpmexec \ No newline at end of file diff --git a/node_modules/libnpmfund b/node_modules/libnpmfund deleted file mode 120000 index d82688b40a0f8..0000000000000 --- a/node_modules/libnpmfund +++ /dev/null @@ -1 +0,0 @@ -../workspaces/libnpmfund \ No newline at end of file diff --git a/node_modules/libnpmhook b/node_modules/libnpmhook deleted file mode 120000 index 2c01b4ad01384..0000000000000 --- a/node_modules/libnpmhook +++ /dev/null @@ -1 +0,0 @@ -../workspaces/libnpmhook \ No newline at end of file diff --git a/node_modules/libnpmorg b/node_modules/libnpmorg deleted file mode 120000 index 6b2e24155f1ab..0000000000000 --- a/node_modules/libnpmorg +++ /dev/null @@ -1 +0,0 @@ -../workspaces/libnpmorg \ No newline at end of file diff --git a/node_modules/libnpmpack b/node_modules/libnpmpack deleted file mode 120000 index e6c52f5106c6d..0000000000000 --- a/node_modules/libnpmpack +++ /dev/null @@ -1 +0,0 @@ -../workspaces/libnpmpack \ No newline at end of file diff --git a/node_modules/libnpmpublish b/node_modules/libnpmpublish deleted file mode 120000 index ed6ad89c30934..0000000000000 --- a/node_modules/libnpmpublish +++ /dev/null @@ -1 +0,0 @@ -../workspaces/libnpmpublish \ No newline at end of file diff --git a/node_modules/libnpmsearch b/node_modules/libnpmsearch deleted file mode 120000 index db3ba8d84df37..0000000000000 --- a/node_modules/libnpmsearch +++ /dev/null @@ -1 +0,0 @@ -../workspaces/libnpmsearch \ No newline at end of file diff --git a/node_modules/libnpmteam b/node_modules/libnpmteam deleted file mode 120000 index 3445d078310a9..0000000000000 --- a/node_modules/libnpmteam +++ /dev/null @@ -1 +0,0 @@ -../workspaces/libnpmteam \ No newline at end of file diff --git a/node_modules/libnpmversion b/node_modules/libnpmversion deleted file mode 120000 index 28738cfa6bcfc..0000000000000 --- a/node_modules/libnpmversion +++ /dev/null @@ -1 +0,0 @@ -../workspaces/libnpmversion \ No newline at end of file diff --git a/node_modules/qrcode-terminal/example/basic.png b/node_modules/qrcode-terminal/example/basic.png deleted file mode 100644 index 2ab5c226f4311f6892bd73a0f0f279257d5cafd5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46426 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 diff --git a/scripts/bundle-and-gitignore-deps.js b/scripts/bundle-and-gitignore-deps.js index 7e65064ceda3a..1b77f170ccdb8 100644 --- a/scripts/bundle-and-gitignore-deps.js +++ b/scripts/bundle-and-gitignore-deps.js @@ -3,43 +3,45 @@ const packlist = require('npm-packlist') const { join, relative } = require('path') const localeCompare = require('@isaacs/string-locale-compare')('en') const PackageJson = require('@npmcli/package-json') -const { run, CWD, git, fs } = require('./util') +const { run, CWD, git, fs, pkg: rootPkg, EOL } = require('./util') const npmGit = require('@npmcli/git') -const ALWAYS_IGNORE = ` -.bin/ -.cache/ -package-lock.json -CHANGELOG* -changelog* -ChangeLog* -Changelog* -README* -readme* -ReadMe* -Readme* -__pycache__ -.editorconfig -.idea/ -.npmignore -.eslintrc* -.travis* -.github -.jscsrc -.nycrc -.istanbul* -.eslintignore -.jshintrc* -.prettierrc* -.jscs.json -.dir-locals* -.coveralls* -.babelrc* -.nyc_output -.gitkeep -*.map -*.ts -` +const ALWAYS_IGNORE = [ + '.bin/', + '.cache/', + 'package-lock.json', + 'CHANGELOG*', + 'changelog*', + 'ChangeLog*', + 'Changelog*', + 'README*', + 'readme*', + 'ReadMe*', + 'Readme*', + '__pycache__', + '.editorconfig', + '.idea/', + '.npmignore', + '.eslintrc*', + '.travis*', + '.github', + '.jscsrc', + '.nycrc', + '.istanbul*', + '.eslintignore', + '.jshintrc*', + '.prettierrc*', + '.jscs.json', + '.dir-locals*', + '.coveralls*', + '.babelrc*', + '.nyc_output', + '.gitkeep', + '*.map', + '*.ts', + '*.png', + '*.jpg', +] const lsAndRmIgnored = async (dir) => { const files = await git( @@ -70,15 +72,6 @@ const lsAndRmIgnored = async (dir) => { } const getAllowedPaths = (files) => { - // Get all files within node_modules and remove - // the node_modules/ portion of the path for processing - // since this list will go inside a gitignore at the - // root of the node_modules dir - const nmFiles = files - .filter(f => f.startsWith('node_modules/')) - .map(f => f.replace(/^node_modules\//, '')) - .sort(localeCompare) - class AllowSegments { #segments #usedSegments @@ -177,7 +170,7 @@ const getAllowedPaths = (files) => { } const allowPaths = new Set() - for (const file of nmFiles) { + for (const file of files) { for (const allow of gatherAllows(file.split('/'))) { allowPaths.add(allow) } @@ -214,7 +207,19 @@ const main = async () => { await setBundleDeps() const arb = new Arborist({ path: CWD }) - const files = await arb.loadActual().then(packlist) + const allFiles = await arb.loadActual().then(packlist) + const workspaceNames = (await rootPkg.mapWorkspaces()).map(p => p.name) + const isWorkspace = (p) => workspaceNames.some(w => p.startsWith(w + '/')) + + // Get all files within node_modules and remove the node_modules/ portion of + // the path for processing since this list will go inside a gitignore at the + // root of the node_modules dir. It also removes workspaces since those are + // symlinks and should not be commited into source control. + const files = allFiles + .filter(f => f.startsWith('node_modules/')) + .map(f => f.replace(/^node_modules\//, '')) + .filter(f => !isWorkspace(f)) + .sort(localeCompare) const ignoreFile = [ '# Automatically generated to ignore everything except bundled deps', @@ -224,11 +229,11 @@ const main = async () => { '# Allow all bundled deps', ...getAllowedPaths(files), '# Always ignore some specific patterns within any allowed package', - ...ALWAYS_IGNORE.trim().split('\n'), + ...ALWAYS_IGNORE, ] const NODE_MODULES = join(CWD, 'node_modules') - const res = await fs.writeFile(join(NODE_MODULES, '.gitignore'), ignoreFile.join('\n')) + const res = await fs.writeFile(join(NODE_MODULES, '.gitignore'), ignoreFile.join(EOL)) if (!await npmGit.is({ cwd: CWD })) { // if we are not running in a git repo then write the files but we do not @@ -247,7 +252,7 @@ const main = async () => { 'The following files are checked in to git but will now be ignored.', `They could not be removed automatically and will need to be removed manually.`, ...trackedAndIgnored.map(p => relative(NODE_MODULES, p)), - ].join('\n') + ].join(EOL) throw new Error(message) } diff --git a/scripts/dependency-graph.js b/scripts/dependency-graph.js index f9c177968b848..8c5f9af50c6a2 100644 --- a/scripts/dependency-graph.js +++ b/scripts/dependency-graph.js @@ -1,14 +1,15 @@ const Arborist = require('@npmcli/arborist') +const os = require('os') const { readFileSync } = require('fs') const { join } = require('path') const log = require('proc-log') -const { run, CWD, pkg, fs } = require('./util.js') +const { run, CWD, pkg, fs, EOL } = require('./util.js') // Generates our dependency graph documents in DEPENDENCIES.md. // To re-create npm-cli-repos.txt run: // 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') +const repos = readFileSync(join(CWD, 'scripts', 'npm-cli-repos.txt'), 'utf-8').trim().split(os.EOL) // these have a different package name than the repo name, and are ours. const aliases = { @@ -110,10 +111,10 @@ const main = async function () { 'Each group depends on packages lower down the chain, nothing depends on', 'packages higher up the chain.', '', - ` - ${hierarchyOurs.reverse().join('\n - ')}`, + ` - ${hierarchyOurs.reverse().join(`${EOL} - `)}`, ] - return fs.writeFile(join(CWD, 'DEPENDENCIES.md'), out.join('\n')) + return fs.writeFile(join(CWD, 'DEPENDENCIES.md'), out.join(EOL)) } const walk = function (tree, onlyOurs) { diff --git a/scripts/npm-cli-repos.txt b/scripts/npm-cli-repos.txt index 118f1c2addc58..e69d02c7ec9bd 100644 --- a/scripts/npm-cli-repos.txt +++ b/scripts/npm-cli-repos.txt @@ -14,7 +14,6 @@ fs fs-minipass gauge git -graphec hosted-git-info ignore-walk ini @@ -28,7 +27,6 @@ minify-registry-metadata minipass-fetch mute-stream name-from-folder -node node-gyp node-semver node-which @@ -36,7 +34,6 @@ nopt normalize-package-data npm-audit-report npm-bundled -npm-cli-release-please npm-install-checks npm-install-script npm-normalize-package-bin @@ -59,7 +56,6 @@ read read-cmd-shim read-package-json read-package-json-fast -release-please rfcs run-script ssri diff --git a/scripts/resetdeps.js b/scripts/resetdeps.js index 083c57e11a693..afd19c38932c3 100644 --- a/scripts/resetdeps.js +++ b/scripts/resetdeps.js @@ -1,9 +1,17 @@ - const { join } = require('path') +const { symlink } = require('fs/promises') const { CWD, run, pkg, fs, git, npm } = require('./util.js') -const ciInfo = require('ci-info') -const checkout = () => git('checkout', 'node_modules/') +const cleanup = async () => { + await git('checkout', 'node_modules/') + for (const { name, path, pkg: wsPkg } of await pkg.mapWorkspaces()) { + if (!wsPkg.private) { + // add symlinks similar to how arborist does for our production + // workspaces, so they are in place before the initial install. + await symlink(path, join(CWD, 'node_modules', name), 'junction') + } + } +} const main = async ({ packageLock }) => { await fs.rimraf(join(CWD, 'node_modules')) @@ -11,12 +19,10 @@ const main = async ({ packageLock }) => { await fs.rimraf(join(path, 'node_modules')) } - await checkout() + await cleanup() await npm('i', '--ignore-scripts', '--no-audit', '--no-fund', packageLock && '--package-lock') await npm('rebuild', '--ignore-scripts') - if (!ciInfo.isCI) { - await npm('run', 'dependencies', '--ignore-scripts') - } + await npm('run', 'dependencies', '--ignore-scripts') } -run(main).catch(checkout) +run(main).catch(cleanup) diff --git a/scripts/template-oss/_step-deps.yml b/scripts/template-oss/_step-deps.yml index 22f8d00c7a6fd..c36f9a2f2fb8a 100644 --- a/scripts/template-oss/_step-deps.yml +++ b/scripts/template-oss/_step-deps.yml @@ -1,2 +1,4 @@ +- name: Check Git Status + run: node scripts/git-dirty.js - name: Reset Deps - run: {{rootNpmPath}} run resetdeps {{~#if jobDepFlags}} -- {{ jobDepFlags }}{{/if}} + run: node scripts/resetdeps.js {{~#if jobDepFlags}} {{ jobDepFlags }}{{/if}} diff --git a/scripts/template-oss/_step-test.yml b/scripts/template-oss/_step-test.yml index 9471e6a5a4f55..f46e11cdc39fd 100644 --- a/scripts/template-oss/_step-test.yml +++ b/scripts/template-oss/_step-test.yml @@ -1,4 +1,3 @@ {{> defaultStepTest }} - name: Check Git Status - if: matrix && matrix.platform.os != 'windows-latest' run: node scripts/git-dirty.js diff --git a/scripts/template-oss/ci-npmcli-docs.yml b/scripts/template-oss/ci-npmcli-docs.yml index 1e3cd054262d3..82397433e0671 100644 --- a/scripts/template-oss/ci-npmcli-docs.yml +++ b/scripts/template-oss/ci-npmcli-docs.yml @@ -12,7 +12,7 @@ run: | git clean -fd git checkout $\{{ github.event.pull_request.base.ref }} - node . run resetdeps + node scripts/resetdeps.js node . run build -w docs - name: Diff Man run: diff -r --color=always man/ man-update/ || true diff --git a/scripts/template-oss/node-integration.yml b/scripts/template-oss/node-integration.yml index 4513ab0e43d72..4632aae9aa98e 100644 --- a/scripts/template-oss/node-integration.yml +++ b/scripts/template-oss/node-integration.yml @@ -104,7 +104,7 @@ jobs: echo "::group::packing npm release $npmVersion" pushd "$npmDir" >/dev/null - node . run resetdeps + node scripts/resetdeps.js npmtarball="$(node . pack --loglevel=silent --json | jq -r .[0].filename)" tar czf "$npmFile" -C "$npmDir" . popd >/dev/null @@ -202,7 +202,7 @@ jobs: echo "::endgroup::" echo "::group::npm run resetdeps" - node . run resetdeps + node scripts/resetdeps.js echo "::endgroup::" echo "::group::npm link" diff --git a/scripts/update-authors.js b/scripts/update-authors.js old mode 100755 new mode 100644 index fc567b664825a..e95bb87bfc00a --- a/scripts/update-authors.js +++ b/scripts/update-authors.js @@ -1,5 +1,5 @@ const { join } = require('path') -const { CWD, run, git, fs } = require('./util.js') +const { CWD, run, git, fs, EOL } = require('./util.js') const main = async () => { const allAuthors = await git('log', '--use-mailmap', '--reverse', '--format=%aN <%aE>', { @@ -21,7 +21,7 @@ const main = async () => { return fs.writeFile(join(CWD, 'AUTHORS'), [ `# Authors sorted by whether or not they're me`, ...authors, - ].join('\n')) + ].join(EOL)) } run(main) diff --git a/scripts/util.js b/scripts/util.js index 93c52809e50bf..aab8551e0aebc 100644 --- a/scripts/util.js +++ b/scripts/util.js @@ -7,6 +7,9 @@ const npmGit = require('@npmcli/git') const promiseSpawn = require('@npmcli/promise-spawn') const mapWorkspaces = require('@npmcli/map-workspaces') +// always use LF newlines for generated files. these files +// are also set to use LF line endings in .gitattributes +const EOL = '\n' const CWD = resolve(__dirname, '..') const pkg = require(join(CWD, 'package.json')) @@ -24,7 +27,7 @@ const fs = { 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') + await fsp.writeFile(p, d.trim() + EOL, 'utf-8') return `Wrote to ${relative(CWD, p)}` }, } @@ -123,6 +126,7 @@ git.dirty = () => npmGit.isClean({ cwd: CWD }).then(async r => { return 'git clean' } await git('status', '--porcelain=v1', '-uno') + await git('diff') throw new Error('git dirty') }) @@ -201,4 +205,5 @@ module.exports = { gh, npm, git, + EOL, } diff --git a/workspaces/arborist/test/fixtures/index.js b/workspaces/arborist/test/fixtures/index.js index e80c74e4c8241..fdc5592c7dd8d 100644 --- a/workspaces/arborist/test/fixtures/index.js +++ b/workspaces/arborist/test/fixtures/index.js @@ -165,14 +165,17 @@ const setup = () => { } }) if (didSomething) { + const start = '### BEGIN IGNORED SYMLINKS ###' + const end = '### END IGNORED SYMLINKS ###' const gifile = resolve(__dirname, './.gitignore') const gitignore = readFileSync(gifile, 'utf8') - .replace(/### BEGIN IGNORED SYMLINKS ###[\s\S]*### END IGNORED SYMLINKS ###/, - `### BEGIN IGNORED SYMLINKS ### -### this list is generated automatically, do not edit directly -### update it by running \`node test/fixtures/index.js\` -${links.sort(localeCompare).join('\n')} -### END IGNORED SYMLINKS ###`) + .replace(new RegExp(`${start}[\\s\\S]*${end}`), [ + start, + '### this list is generated automatically, do not edit directly', + '### update it by running `node test/fixtures/index.js`', + ...links.sort(localeCompare), + end, + ].join('\n')) writeFileSync(gifile, gitignore) } } diff --git a/workspaces/arborist/test/fixtures/tap-with-yarn-lock/node_modules/json-schema/package.json b/workspaces/arborist/test/fixtures/tap-with-yarn-lock/node_modules/json-schema/package.json index b9b7bac836bce..b010571dd952c 100644 --- a/workspaces/arborist/test/fixtures/tap-with-yarn-lock/node_modules/json-schema/package.json +++ b/workspaces/arborist/test/fixtures/tap-with-yarn-lock/node_modules/json-schema/package.json @@ -1,31 +1,31 @@ -{ - "name": "json-schema", - "version": "0.2.3", - "author": "Kris Zyp", - "description": "JSON Schema validation and specifications", - "maintainers":[ - {"name": "Kris Zyp", "email": "kriszyp@gmail.com"}], - "keywords": [ - "json", - "schema" - ], - "licenses": [ - { - "type": "AFLv2.1", - "url": "http://trac.dojotoolkit.org/browser/dojo/trunk/LICENSE#L43" - }, - { - "type": "BSD", - "url": "http://trac.dojotoolkit.org/browser/dojo/trunk/LICENSE#L13" - } - ], - "repository": { - "type":"git", - "url":"http://github.com/kriszyp/json-schema" - }, - "directories": { "lib": "./lib" }, - "main": "./lib/validate.js", - "devDependencies": { "vows": "*" }, - "scripts": { "test": "echo TESTS DISABLED vows --spec test/*.js" } -} - +{ + "name": "json-schema", + "version": "0.2.3", + "author": "Kris Zyp", + "description": "JSON Schema validation and specifications", + "maintainers":[ + {"name": "Kris Zyp", "email": "kriszyp@gmail.com"}], + "keywords": [ + "json", + "schema" + ], + "licenses": [ + { + "type": "AFLv2.1", + "url": "http://trac.dojotoolkit.org/browser/dojo/trunk/LICENSE#L43" + }, + { + "type": "BSD", + "url": "http://trac.dojotoolkit.org/browser/dojo/trunk/LICENSE#L13" + } + ], + "repository": { + "type":"git", + "url":"http://github.com/kriszyp/json-schema" + }, + "directories": { "lib": "./lib" }, + "main": "./lib/validate.js", + "devDependencies": { "vows": "*" }, + "scripts": { "test": "echo TESTS DISABLED vows --spec test/*.js" } +} +