Skip to content

Commit

Permalink
💚 Update old Corepack that throw ENOTEMPTY or EPERM errors (#198)
Browse files Browse the repository at this point in the history
Old Corepack throws ENOTEMPTY errors (or EPERM errors on Windows) when running package managers in parallel.
To fix this, update the old Corepack when it is detected.
see nodejs/corepack#110
see nodejs/corepack#84

---------

* 💚 [Debug] Try to switch package managers using Corepack in all Node.js

* 💚 [Debug] Run the package manager multiple times

* 💚 [Debug] Using the Package Manager in Test

* 💚 [Debug] Run package managers in parallel

* 💚 Update old Corepack that throws ENOTEMPTY error

    Old Corepack throws ENOTEMPTY error when running package managers in parallel.
    This has been fixed in Corepack v0.11, so if the old Corepack is detected, this will be updated.

* 💚 Include "XXXXXXXXXXXXX" in the argument of the `mktemp` command

    The `mktemp` command on GitHub Actions seems to require the specification of the X's.

* 💚 Also detects EPERM errors thrown by Corepack

    On Windows, the old Corepack seems to throw EPERM errors instead of ENOTEMPTY errors.

* 💚 Modify comments in shell scripts

* 💚 Allow updated Corepack to be used on Windows

    > ```yaml
    > # Windows installs global packages to a directory that has lower priority than
    > # the default node install so we also need to edit $PATH
    > ```
    > Source: https://github.com/vercel/turbo/pull/1632/files#diff-b92a3120126a9ffe46d7d5ec3a8496ef1eac951db09e1972fac7c78438e36c42R62-R63

    > ```bash
    > npm config get prefix >> $GITHUB_PATH
    > ```
    > Source: https://github.com/vercel/turbo/pull/1632/files#diff-b92a3120126a9ffe46d7d5ec3a8496ef1eac951db09e1972fac7c78438e36c42R69

* 💚 Update npm without using npm-windows-upgrade

    This step was added with #185.
    However, perhaps if we run `npm config get prefix >> "${GITHUB_PATH}"`, we can update npm with the `npm install --global npm` command.

* 💚 [Debug] Try updating npm on Windows without updating the environment variable `$PATH`

* ⏪ Revert "💚 [Debug] Try to switch package managers using Corepack in all Node.js"

    This reverts commit 5b4ec7c, 3a62968, 977b430, and 281b88a.

* ✅ [Debug] Verify npm version

* ⏪ Revert "✅ [Debug] Verify npm version"

    This reverts commit c9ddd9d.

* ✅ [Debug] Verify npm version

* ⏪ Revert "💚 [Debug] Try updating npm on Windows without updating the environment variable `$PATH`"

    This reverts commit 919029c.

* 💚 Modify the display content of "Enable Corepack" job

* 💚 Use the prefix "[command]" together with the command `sleep 1`

* 💚 Use the `node -e 'setTimeout(()=>0,10)'` command instead of the `sleep 1` command

    Waiting two seconds just to correct a display shift is a waste of time.
    Note: The POSIX-compliant `sleep` command has a minimum of one second, so we use the `node` command instead.

* 💚 [Debug] Try updating npm on Windows without updating the environment variable `$PATH`

* ⏪ Revert "💚 [Debug] Try updating npm on Windows without updating the environment variable `$PATH`"

    This reverts commit 96914e1.

* ⏪ Revert "✅ [Debug] Verify npm version"

    This reverts commit 70250e2.

* 💚 Modify the display content of "Enable Corepack" job

* 💚 Rewrite `exec_with_debug` function from Bash to Node.js

* 💚 Fix the bash here-document

* 💚 [Debug] Try updating npm on Windows without updating the environment variable `$PATH`

* ⏪ Revert "💚 [Debug] Try updating npm on Windows without updating the environment variable `$PATH`"

    This reverts commit 481b3a0.

* 💚 Wrap complex code that detects old Corepack in a function

* 💚 [Debug] Try to switch package managers using Corepack in all Node.js

* 💚 [Debug] Try without updating old Corepack

* ⏪ Revert "💚 [Debug] Try without updating old Corepack"

    This reverts commit 1631259.

* ⏪ Revert "💚 [Debug] Try to switch package managers using Corepack in all Node.js"

    This reverts commit 6fd6ece.

* 📝 Update CHANGELOG
  • Loading branch information
sounisi5011 authored Mar 13, 2023
1 parent 5a43fb7 commit a15e687
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 31 deletions.
120 changes: 89 additions & 31 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,77 @@ jobs:
- name: Enable Corepack (Automatically setup a package manager for Node.js)
shell: bash
run: |
if type corepack >/dev/null 2>&1; then
echo '::group::$' corepack enable
corepack enable
echo '::endgroup::'
exec_with_debug() {
node - "$@" << 'EOS'
// These characters cannot be wrapped in double quotes:
// - !
// - $
// - \
// - `
const cannotInQuotChars = /!$\\`/;
const quotedArgs = process.argv.slice(2)
.map(arg => {
const wrapApos = `'${arg.replace(new RegExp(`'[^"${cannotInQuotChars.source}]*`, 'g'), `'"$&"'`)}'`.replace(/^''|''$/g, ``);
const wrapQuot = `"${arg.replace(/"[^']*/g, `"'$&'"`)}"`.replace(/^""|""$/g, ``);
return arg === `` || /[ !"$&'()*;<>?[\]\\`{|}~]/.test(arg) ? (
new RegExp(`[${cannotInQuotChars.source}]`).test(arg) || wrapApos.length <= wrapQuot.length
? wrapApos
: wrapQuot
) : arg
})
.join(' ');
// The "[command]" prefix may cause the display to shift, so use it with the "setTimeout" function.
setTimeout(() => {
process.stderr.write(`[command]${quotedArgs}`);
setTimeout(() => process.stderr.write("\n"), 1);
}, 1);
EOS
"$@"
}
# On Windows we can't use the CLI we installed just by running the "npm install --global ..." command.
# This function allows use of the installed CLI.
npm_install_global() {
exec_with_debug npm install --global --force "$1"
if [[ '${{ runner.os }}' == 'Windows' ]]; then
# Windows installs global packages to a directory that has lower priority than the default node install so we also need to edit $PATH
# see https://github.com/vercel/turbo/pull/1632/files#diff-b92a3120126a9ffe46d7d5ec3a8496ef1eac951db09e1972fac7c78438e36c42R69
echo "[command]npm config get prefix >> \$GITHUB_PATH"
npm config get prefix >> "${GITHUB_PATH}"
fi
}
# Old Corepack throws ENOTEMPTY errors (or EPERM errors on Windows) when running package managers in parallel.
# This function detects such old Corepack.
# see https://github.com/nodejs/corepack/issues/110
# see https://github.com/nodejs/corepack/pull/84
is_old_corepack() {
local -r TEST_COREPACK_DIRPATH="$(mktemp -dt test-corepack-ENOTEMPTY-error-XXXXXXXXXX)"
echo '{"packageManager":"yarn@1.22.19"}' > "${TEST_COREPACK_DIRPATH}/package.json"
# see https://github.com/nodejs/corepack/pull/84/files#diff-12cd00a89af03f1fc6f74460b886289151edce062c60319b0c58fb8465558ed6
(
cd "${TEST_COREPACK_DIRPATH}" && \
{
yarn --version 2>&1 &
yarn --version 2>&1 &
yarn --version 2>&1 &
wait
} | grep -Eq '\b(ENOTEMPTY: directory not empty|EPERM: operation not permitted), rename\b'
)
local -r exitCode="${?}"
rm -rf "${TEST_COREPACK_DIRPATH}" || true
return "${exitCode}"
}
echo '::group::$' corepack enable npm
corepack enable npm
if type corepack >/dev/null 2>&1; then
echo '::group::Enable Corepack'
exec_with_debug corepack enable
exec_with_debug corepack enable npm
echo '::endgroup::'
fi
Expand All @@ -146,45 +210,39 @@ jobs:
# You can see what I did here: https://github.com/sounisi5011/package-version-git-tag/compare/24791b6ddab5cd2b8fdc735855556640746cc863~1...349c11acb35cfc0096bc6e9324bd9748e429ca17~1
packageManager="$(< "${GITHUB_WORKSPACE}/package.json" jq --raw-output '.packageManager')"
if [[ "${packageManager}" == 'npm@'* && "npm@$(npm --version)" != "${packageManager%%+*}" ]]; then
echo '::warning::Failed to enable Corepack'
echo '::group::Install the specified npm manually'
# Disable the built-in Corepack in GitHub Actions.
# If enabled, problems will occur when the yarn command is executed.
if type corepack >/dev/null 2>&1; then
echo '::group::$' corepack disable
corepack disable
echo '::endgroup::'
exec_with_debug corepack disable
fi
readonly npmSemver="${packageManager##npm@}"
echo "required-npm-version=${npmSemver%%+*}" >> "${GITHUB_ENV}"
npm_install_global "${packageManager%%+*}"
echo '::endgroup::'
elif type corepack >/dev/null 2>&1; then
# Old Corepack throws ENOTEMPTY errors (or EPERM errors on Windows) when running package managers in parallel.
# This has been fixed in Corepack v0.11, so if the old Corepack is detected, this will be updated.
# see https://github.com/nodejs/corepack/issues/110
# see https://github.com/nodejs/corepack/pull/84
if is_old_corepack; then
echo "::group::Old Corepack is detected ( corepack@$(corepack --version 2>/dev/null || echo '[Execution failed; Unknown version]') ). Update this"
npm_install_global 'corepack@0.11.2'
echo '::endgroup::'
fi
fi
# If yarn is not available, install it
if type yarn >/dev/null 2>&1; then
:
else
echo '::group::' Install yarn
npm install --global --force 'yarn@1.x'
echo '::group::Install yarn'
npm_install_global 'yarn@1.x'
echo '::endgroup::'
fi
- name: Update to the specified npm (Using "npx npm-windows-upgrade")
if: ${{ env.required-npm-version && runner.os == 'Windows' }}
# On Windows, the "npm install --global npm" command does not properly overwrite npm.
# Instead of the "npm install --global npm" command, "npx npm-windows-upgrade" can be used to correctly overwrite npm.
# see https://stackoverflow.com/a/31520672
# Note: The referenced answer says that the "npm install --global npm" command is available for Node.js v16 or later.
# However, when I tried, this problem occurred in all versions of Node.js v14 or later.
shell: pwsh
run: |
Set-ExecutionPolicy Unrestricted -Scope CurrentUser -Force
npx npm-windows-upgrade --npm-version '${{ env.required-npm-version }}'
# see https://github.com/orgs/community/discussions/26641
echo 'required-npm-version=' >> $Env:GITHUB_ENV
- name: Update to the specified npm (Using "npm install --global npm")
if: ${{ env.required-npm-version }}
run: npm install --global --force 'npm@${{ env.required-npm-version }}'

- name: Show node and npm version
shell: bash
run: |
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ This project will support Node.js 14.0.0 or later from now on.

* `@types/node`
* [#186] - `12.x` -> `14.x`
* [#195] - `14.x` -> `14.18.37`
* `@typescript-eslint/eslint-plugin`
* [#185] - `2.34.0` -> `5.54.1`
* `@typescript-eslint/parser`
Expand Down Expand Up @@ -122,6 +123,7 @@ This project will support Node.js 14.0.0 or later from now on.
* [#193] - Update `.renovaterc.json` file
* [#194] - Ignore `.node-version` files
* [#196] - Auto-check if CHANGELOG is updated
* [#198] - Update old Corepack that throw ENOTEMPTY or EPERM errors

[#182]: https://github.com/sounisi5011/package-version-git-tag/pull/182
[#183]: https://github.com/sounisi5011/package-version-git-tag/pull/183
Expand All @@ -133,7 +135,9 @@ This project will support Node.js 14.0.0 or later from now on.
[#193]: https://github.com/sounisi5011/package-version-git-tag/pull/193
[#194]: https://github.com/sounisi5011/package-version-git-tag/pull/194
[#171]: https://github.com/sounisi5011/package-version-git-tag/pull/171
[#195]: https://github.com/sounisi5011/package-version-git-tag/pull/195
[#196]: https://github.com/sounisi5011/package-version-git-tag/pull/196
[#198]: https://github.com/sounisi5011/package-version-git-tag/pull/198

## [3.0.0] (2020-06-02 UTC)

Expand Down

0 comments on commit a15e687

Please sign in to comment.