Files
awesome-cordova-plugins/scripts/tasks/trust-packages.sh
T
Daniel Sogl 9818f74831 ci: publish to npm via trusted publishing (OIDC)
npm validates the OIDC claim of the entry-point workflow, not the one that
runs `npm publish`. Calling publish.yml via workflow_call meant the trust
check could never match, so the publish job moves inline into
release-please.yml and publish.yml is removed.

setup-node with Node 22 ships npm 10.x; trusted publishing needs >= 11.5.1,
hence the explicit npm upgrade before publishing.

NPM_TOKEN stays as a fallback for packages that have no trusted publisher
yet — a brand new plugin cannot get one until it exists on npm. OIDC takes
precedence wherever a config is present.

Adds scripts/tasks/trust-packages.sh to configure the trusted publisher for
all 258 packages; npm has no multi-package call and `npm trust` requires
interactive 2FA, so it runs locally, in parallel, and is resumable.
2026-07-27 21:18:10 +02:00

110 lines
3.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# One-time (and after adding new plugins) bulk setup of npm trusted publishers.
# Run locally after `npm login` — `npm trust` needs interactive 2FA and cannot run in CI.
#
# ./scripts/tasks/trust-packages.sh # 4 parallel workers
# JOBS=8 ./scripts/tasks/trust-packages.sh # more, at the risk of rate limiting
#
# npm has no multi-package call, so this loops. The first package runs on its own to
# trigger the browser 2FA prompt — tick "skip 2FA for the next 5 minutes" there. That
# window is server-side, so the parallel batch afterwards runs unattended inside it.
# Parallelism is what keeps the whole set inside a single window instead of ~4.
#
# A trust call is ~2s, so JOBS=4 is ~2 req/s — 4x npm's serial guidance, and the
# reason there is no extra sleep here. If npm rate-limits, the affected packages
# just land in the failed list and the next run picks them up.
#
# Packages that already have a trust config come back as E409 — npm only ever creates,
# there is no update path — so those are treated as done. To actually *change* a config,
# revoke it first: npm trust list <pkg> && npm trust revoke <pkg> --id=<id>, then re-run.
#
# Progress is recorded in .npm-trust-done; re-running resumes where it stopped.
# Packages must already exist on npm; a brand new plugin publishes via NPM_TOKEN
# on its first release, then gets its trust config here.
set -euo pipefail
REPO=danielsogl/awesome-cordova-plugins
WORKFLOW=release-please.yml
JOBS="${JOBS:-4}"
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
SELF="$ROOT/scripts/tasks/trust-packages.sh"
DONE="$ROOT/.npm-trust-done"
create() {
npm trust github "$1" --file "$WORKFLOW" --repo "$REPO" --allow-publish --yes
}
trust_one() {
local pkg="$1" err rc=0
err=$(mktemp)
# stderr is buffered so E409 can be detected; stdout flows through untouched,
# otherwise npm's "Press ENTER to open in the browser" prompt would be invisible
create "$pkg" 2>"$err" || rc=$?
if [ "$rc" -eq 0 ]; then
# single short line + O_APPEND is atomic, so parallel workers can't interleave
echo "$pkg" >> "$DONE"
elif grep -q "E409" "$err"; then
# already has a trust config; npm only ever creates, so this is a no-op, not a failure
echo ">> $pkg already configured, skipping" >&2
echo "$pkg" >> "$DONE"
rc=0
else
cat "$err" >&2
fi
rm -f "$err"
return "$rc"
}
# re-entry point for xargs workers
if [ "${1:-}" = "--one" ]; then
trust_one "$2"
exit
fi
packages=(core)
for dir in "$ROOT"/src/@awesome-cordova-plugins/plugins/*/; do
packages+=("$(basename "$dir")")
done
touch "$DONE"
todo=()
for name in "${packages[@]}"; do
pkg="@awesome-cordova-plugins/$name"
grep -qxF "$pkg" "$DONE" || todo+=("$pkg")
done
if [ ${#todo[@]} -eq 0 ]; then
echo "All ${#packages[@]} packages already configured."
exit 0
fi
echo "${#todo[@]} of ${#packages[@]} packages left for $REPO/.github/workflows/$WORKFLOW"
echo
echo ">> ${todo[0]} runs first. Approve in the browser and tick"
echo ">> \"skip 2FA for the next 5 minutes\" — the rest then runs unattended."
echo
trust_one "${todo[0]}" || true
if [ ${#todo[@]} -gt 1 ]; then
echo
echo "Configuring the remaining $((${#todo[@]} - 1)) with $JOBS parallel workers..."
printf '%s\n' "${todo[@]:1}" | xargs -P "$JOBS" -n1 "$SELF" --one || true
fi
failed=()
for pkg in "${todo[@]}"; do
grep -qxF "$pkg" "$DONE" || failed+=("$pkg")
done
if [ ${#failed[@]} -gt 0 ]; then
echo
printf 'failed: %s\n' "${failed[@]}"
echo
echo "An expired 2FA window is the usual cause — re-run and approve again."
echo "Re-run retries only the failures; successes are recorded in $DONE."
exit 1
fi
echo "Done."