Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,17 @@ jobs:
fetch-depth: 0
- uses: './.github/actions/setup'
- run: |
npm config set workspaces-update false
npx multi-semantic-release \
--deps.release=inherit \
--ignore-private-packages
env:
# multi-semantic-release rewrites each package's "*" dependency
# ranges to the versions this run is about to publish, so reifying
# the workspace mid-run resolves versions the registry does not have
# yet. This has to travel as an env var: @semantic-release/npm runs
# `npm version` with --userconfig pointed at a temp file, which
# displaces ~/.npmrc, and env beats every config file.
npm_config_workspaces_update: 'false'
GIT_AUTHOR_EMAIL:
${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com
GIT_COMMITTER_EMAIL:
Expand Down
63 changes: 63 additions & 0 deletions scripts/npm-trust
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env bash

set -euo pipefail

# Registers GitHub Actions as the npm trusted publisher for every public
# workspace package. npm stores that relationship per package, and without it
# the OIDC token exchange in .github/workflows/push.yml gets rejected and
# @semantic-release/npm falls back to looking for an NPM_TOKEN. A newly added
# package needs a run of this script before its first release.
#
# Requires npm >= 11.15.0, write access to every package, and account-level
# 2FA. npm asks for an OTP on the first package; the npmjs.com prompt offers to
# skip 2FA for the next five minutes, which covers the rest of the run.
#
# Usage: scripts/npm-trust [package...]

repo=code-like-a-carpenter/workbench
workflow=push.yml
required_npm=11.15.0

npm_version="$(npm --version)"
if [ "$(printf '%s\n%s\n' "$required_npm" "$npm_version" | sort -V | head -n1)" != "$required_npm" ]; then
echo "npm trust requires npm >= $required_npm, but npm is $npm_version" >&2
exit 1
fi

if [ $# -gt 0 ]; then
packages=("$@")
else
mapfile -t packages < <(
npm pkg get name private --ws --json | node -e '
const chunks = [];
process.stdin.on("data", (chunk) => chunks.push(chunk));
process.stdin.on("end", () => {
for (const pkg of Object.values(JSON.parse(chunks.join("")))) {
if (pkg.private !== true) {
console.log(pkg.name);
}
}
});
'
)
fi

failed=()
for package in "${packages[@]}"; do
echo "==> $package"
if ! npm trust github "$package" \
--file "$workflow" \
--repo "$repo" \
--allow-publish \
--yes; then
failed+=("$package")
fi
# The registry rate limits the trust endpoint; npm's docs suggest a 2s gap.
sleep 2
done

if [ "${#failed[@]}" -gt 0 ]; then
echo "Failed to configure:" >&2
printf ' %s\n' "${failed[@]}" >&2
exit 1
fi
Loading