Compare commits

...
2 Commits
Author SHA1 Message Date
Jordan Harband 6798d1dbc9 [actions] release.yml: provide GH_TOKEN so release-notes PR lookup can run
Tests: installation_node / installation_node (bash) (push) Canceled after 0s
Tests: installation_node / installation_node (bash, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (dash) (push) Canceled after 0s
Tests: installation_node / installation_node (dash, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (sh) (push) Canceled after 0s
Tests: installation_node / installation_node (sh, without curl) (push) Canceled after 0s
Tests: installation_node / installation_node (zsh) (push) Canceled after 0s
Tests: installation_node / installation_node (zsh, without curl) (push) Canceled after 0s
Tests: xenial / xenial (bash) (push) Canceled after 0s
Tests: xenial / xenial (dash) (push) Canceled after 0s
Tests: xenial / xenial (sh) (push) Canceled after 0s
Tests: xenial / xenial (zsh) (push) Canceled after 0s
urchin tests / tests (bash, install_script) (push) Canceled after 0s
urchin tests / tests (bash, installation_iojs) (push) Canceled after 0s
urchin tests / tests (bash, slow) (push) Canceled after 0s
urchin tests / tests (bash, sourcing) (push) Canceled after 0s
urchin tests / tests (dash, installation_iojs) (push) Canceled after 0s
urchin tests / tests (dash, slow) (push) Canceled after 0s
urchin tests / tests (dash, sourcing) (push) Canceled after 0s
urchin tests / tests (sh, installation_iojs) (push) Canceled after 0s
urchin tests / tests (sh, slow) (push) Canceled after 0s
urchin tests / tests (sh, sourcing) (push) Canceled after 0s
urchin tests / tests (zsh, installation_iojs) (push) Canceled after 0s
urchin tests / tests (zsh, slow) (push) Canceled after 0s
urchin tests / tests (zsh, sourcing) (push) Canceled after 0s
update readme TOC / update readme TOC (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS fail prefix nvm install (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--default 12) (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--lts) (push) Canceled after 0s
Tests on Windows: `nvm install` / MSYS nvm install (--no-progress 10) (push) Canceled after 0s
Tests on Windows: `nvm install` / Cygwin nvm install (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Debian) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3, node v24.9.0) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Ubuntu-20.04) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3, node v22.12.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.10, node v10.24.1) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Debian) (push) Canceled after 0s
Code scanning - action / CodeQL-Build (push) Canceled after 0s
Tests: `nvm install-latest-npm` / matrix (push) Canceled after 0s
Tests: linting / eclint (push) Canceled after 0s
Tests: linting / dockerfile_lint (push) Canceled after 0s
Tests: linting / doctoc (push) Canceled after 0s
Tests: linting / test_naming (push) Canceled after 0s
Tests: linting / check_exec (push) Canceled after 0s
Tests: release process / release (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (bash_completion, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (install.sh, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm-exec, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, bash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, dash) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, ksh) (push) Canceled after 0s
Tests: shellcheck / shellcheck_matrix (nvm.sh, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, bash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3, zsh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, bash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.15, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.15, zsh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, bash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, dash) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, sh) (push) Canceled after 0s
Tests: alpine / fast arm64 (alpine 3.19, zsh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, bash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, dash) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, sh) (push) Canceled after 0s
Tests: alpine / fast x64 (alpine 3.19, zsh) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3, node v22.21.1) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.10, node v8.17.0) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.12, node v12.22.12) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.15, node v14.21.3) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.16, node v16.20.2) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.18, node v18.20.4) (push) Canceled after 0s
Tests: alpine / musl-binary arm64 (alpine 3.20, node v20.20.1) (push) Canceled after 0s
Tests: alpine / musl-binary x64 (alpine 3.20, node v20.18.1) (push) Canceled after 0s
Tests: installation_iojs / actually compile io.js from source (gcc 4.9 container) (push) Canceled after 0s
Tests: fast / fast (bash, gawk) (push) Canceled after 0s
Tests: fast / fast (dash, gawk) (push) Canceled after 0s
Tests: fast / fast (sh, gawk) (push) Canceled after 0s
Tests: fast / fast (zsh, gawk) (push) Canceled after 0s
Tests: fast / fast (bash, mawk) (push) Canceled after 0s
Tests: fast / fast (dash, mawk) (push) Canceled after 0s
Tests: fast / fast (sh, mawk) (push) Canceled after 0s
Tests: fast / fast (zsh, mawk) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (bash) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (dash) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (sh) (push) Canceled after 0s
Tests: installation_iojs / installation_iojs without curl (zsh) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-18.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Debian) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Ubuntu-20.04) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, --lts, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 10, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 11, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 12, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 14, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 16, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 18, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (, 21, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, --lts, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 10, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 11, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 12, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 14, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 16, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 18, Alpine) (push) Canceled after 0s
Tests on Windows: `nvm install` / WSL nvm install (script, 21, Alpine) (push) Canceled after 0s
Tests: installation_iojs / all installation_iojs tests (push) Canceled after 0s
Tests: installation_node / all installation_node tests (push) Canceled after 0s
Tests: xenial / all xenial tests (push) Canceled after 0s
urchin tests / all test suites, all shells (push) Canceled after 0s
Tests: fast / all fast tests (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (${{ fromJson(needs.matrix.outputs.latest) }}) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (0.10) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (0.12) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (14.16) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (14.17) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (20.4) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (20.5) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (21) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.4) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.5) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (4.6) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (5.9) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (6.1) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.0) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.1) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (9.2) (push) Canceled after 0s
Tests: `nvm install-latest-npm` / nvm install-latest-npm (push) Canceled after 0s
Tests: linting / all linting (push) Canceled after 0s
Tests: shellcheck / shellcheck (push) Canceled after 0s
Tests: alpine / all alpine tests (push) Canceled after 0s
Tests on Windows: `nvm install` / tests, on windows (push) Canceled after 0s
In GitHub Actions, `gh` refuses to run without a token,
and `release-notes.sh` fails closed on `gh` errors,
so the `make release` dry run died once the script was checked in.
The workflow already permits `api.github.com` egress and only needs the default read-only token.
2026-08-17 23:33:17 -07:00
Jordan Harband df7a936157 [meta] add release-notes.sh, the release notes generator
The `release` target has invoked `./release-notes.sh` since 0b8ed9fa,
but the script itself was never committed,
so the "Tests: release process" workflow fails on a fresh checkout.
2026-08-17 23:21:32 -07:00
2 changed files with 154 additions and 0 deletions
+1
View File
@@ -35,5 +35,6 @@ jobs:
run: echo proceed | make TAG=99.99.99 release
env:
GIT_EDITOR: "sed -i '1 s/^/99.99.99 make release test/'"
GH_TOKEN: ${{ github.token }}
- name: Ensure tag is created
run: git tag | grep v99.99.99
+153
View File
@@ -0,0 +1,153 @@
#!/bin/sh
# Generates release notes for an nvm release, in the format used in the
# annotated release tags and version bump commits.
#
# Usage: ./release-notes.sh <new-version> [<prev-ref>] [<end-ref>]
# <new-version> the version being released, e.g. `v0.40.7` (the leading `v` is optional)
# <prev-ref> list commits since this ref; defaults to the most recent `vX.Y.Z` tag
# <end-ref> list commits up to this ref; defaults to HEAD
#
# Commits from <prev-ref> to <end-ref> are grouped into sections by the leading
# `[bracket]` tag of their subject line, in `git log` order (newest first).
# Category tags ([New], [Fix], ...) are stripped from the bullet text;
# context tags ([readme], [actions], [meta], ...) are kept.
# Commits without a recognized tag land under "Misc", with a warning on stderr.
#
# Each bullet gets a ` (#123)` reference to the pull request that introduced
# the commit, looked up via `gh` from GitHub's commit->PR association, unless
# the subject already ends with one. Set NVM_RELEASE_NOTES_SKIP_PRS to a
# nonempty value to skip the lookup (references will be omitted).
NEW_VERSION="${1-}"
PREV_REF="${2-}"
END_REF="${3:-HEAD}"
if [ -z "${NEW_VERSION}" ]; then
printf >&2 'Usage: %s <new-version> [<prev-ref>] [<end-ref>]\n' "$0"
exit 2
fi
case "${NEW_VERSION}" in
v*) ;;
*) NEW_VERSION="v${NEW_VERSION}" ;;
esac
if [ -z "${PREV_REF}" ]; then
PREV_REF="$(git describe --abbrev=0 --tags --match 'v[0-9]*.[0-9]*.[0-9]*')" || {
printf >&2 'release-notes: failed to determine the previous version tag.\n'
exit 1
}
fi
for REF in "${PREV_REF}" "${END_REF}"; do
git rev-parse --quiet --verify "${REF}^{commit}" >/dev/null || {
# shellcheck disable=SC2016
printf >&2 'release-notes: `%s` is not a valid ref.\n' "${REF}"
exit 1
}
done
LOOKUP_PRS=1
if [ -n "${NVM_RELEASE_NOTES_SKIP_PRS-}" ]; then
LOOKUP_PRS=0
elif ! command -v gh >/dev/null 2>&1; then
# shellcheck disable=SC2016
printf >&2 'release-notes: `gh` is not available; PR references will be omitted.\n'
LOOKUP_PRS=0
fi
# the repo to look up commit->PR associations in, e.g. `nvm-sh/nvm`
REPO_SLUG="${GH_REPO-}"
if [ -z "${REPO_SLUG}" ]; then
ORIGIN_URL="$(git remote get-url origin 2>/dev/null)" || ORIGIN_URL=''
case "${ORIGIN_URL}" in
*github.com[:/]*) REPO_SLUG="$(printf '%s' "${ORIGIN_URL}" | sed 's#^.*github\.com[:/]##;s#\.git$##')" ;;
esac
fi
: "${REPO_SLUG:=nvm-sh/nvm}"
TAB="$(printf '\t')"
COMMITS_FILE="$(mktemp)" || exit 1
GH_ERR_FILE="$(mktemp)" || exit 1
trap 'rm -f "${COMMITS_FILE}" "${GH_ERR_FILE}"' EXIT
# each line: <section key> TAB <sha> TAB <bullet text>, in git log order
git log --no-merges --format='%H %s' "${PREV_REF}..${END_REF}" | while IFS=' ' read -r SHA SUBJECT; do
LOWERED="$(printf '%s' "${SUBJECT}" | tr '[:upper:]' '[:lower:]')"
STRIPPED="${SUBJECT#\[*\] }"
case "${LOWERED}" in
v[0-9]*.[0-9]*.[0-9]*)
case "${SUBJECT}" in
*' '*) # not a bump commit, just a subject that starts with a version
printf >&2 'release-notes: no category prefix, filing under Misc: %s\n' "${SUBJECT}"
KEY='misc' TEXT="${SUBJECT}"
;;
*) continue ;; # a version bump commit
esac
;;
'[new] '*) KEY='new' TEXT="${STRIPPED}" ;;
'[fix] '* | '[patch] '*) KEY='fix' TEXT="${STRIPPED}" ;;
'[refactor] '*) KEY='refactor' TEXT="${STRIPPED}" ;;
'[shellcheck] '*) KEY='refactor' TEXT="${SUBJECT}" ;;
'[robustness] '*) KEY='robustness' TEXT="${STRIPPED}" ;;
'[perf] '* | '[performance] '*) KEY='perf' TEXT="${STRIPPED}" ;;
'[dockerfile] '*) KEY='dockerfile' TEXT="${STRIPPED}" ;;
'[docs] '* | '[doc] '*) KEY='docs' TEXT="${STRIPPED}" ;;
'[readme] '*) KEY='docs' TEXT="${SUBJECT}" ;;
'[meta] '* | '[security] '* | '[dev deps] '*)
KEY='misc' TEXT="${SUBJECT}" ;;
'[tests] '* | '[test] '*) KEY='tests' TEXT="${STRIPPED}" ;;
'[actions] '* | '[debug] '*) KEY='tests' TEXT="${SUBJECT}" ;;
*)
printf >&2 'release-notes: no category prefix, filing under Misc: %s\n' "${SUBJECT}"
KEY='misc' TEXT="${SUBJECT}"
;;
esac
printf '%s\t%s\t%s\n' "${KEY}" "${SHA}" "${TEXT}"
done > "${COMMITS_FILE}"
if ! [ -s "${COMMITS_FILE}" ]; then
printf >&2 'release-notes: no commits found in %s..HEAD.\n' "${PREV_REF}"
fi
print_section() {
if ! grep -q "^$1${TAB}" "${COMMITS_FILE}"; then
return 0
fi
printf '\n%s\n\n' "$2"
grep "^$1${TAB}" "${COMMITS_FILE}" | while IFS="${TAB}" read -r _KEY SHA TEXT; do
REF=''
case "${TEXT}" in
*'(#'[0-9]*')') ;; # the subject already carries a reference
*)
if [ "${LOOKUP_PRS}" = 1 ]; then
PR="$(gh api "repos/${REPO_SLUG}/commits/${SHA}/pulls" --jq '.[0].number // empty' 2>"${GH_ERR_FILE}")" || {
if grep -q 'No commit found' "${GH_ERR_FILE}"; then
PR='' # not pushed to GitHub yet, so it can not have come from a PR
else
printf >&2 'release-notes: failed to look up the PR for commit %s:\n' "${SHA}"
cat >&2 "${GH_ERR_FILE}"
exit 1
fi
}
case "${PR}" in
'' | *[!0-9]*) ;;
*) REF=" (#${PR})" ;;
esac
fi
;;
esac
printf ' - %s%s\n' "${TEXT}" "${REF}"
done || exit 1
}
printf '%s\n' "${NEW_VERSION}"
print_section 'new' 'New Stuff' &&
print_section 'fix' 'Bug Fixes' &&
print_section 'refactor' 'Refactors' &&
print_section 'robustness' 'Robustness' &&
print_section 'perf' 'Performance' &&
print_section 'dockerfile' 'Dockerfile' &&
print_section 'docs' 'Docs' &&
print_section 'misc' 'Misc' &&
print_section 'tests' 'Tests'