-
Notifications
You must be signed in to change notification settings - Fork 8
193 lines (168 loc) · 7.24 KB
/
Copy pathrelease-npm.yml
File metadata and controls
193 lines (168 loc) · 7.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
name: 'Publish npm Packages'
on:
push:
branches:
- main
paths:
- 'packages/**'
- 'pnpm-lock.yaml'
- '.github/workflows/release-npm.yml'
workflow_dispatch:
permissions:
contents: read
concurrency:
group: npm-publish-${{ github.ref }}
cancel-in-progress: false
jobs:
pack:
if: ${{ github.repository == 'MaaXYZ/MaaLogAnalyzer' }}
runs-on: ubuntu-latest
timeout-minutes: 30
outputs:
tarball_count: ${{ steps.pack.outputs.tarball_count }}
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa # v4
with:
version: 10.34.5
run_install: false
# No registry-url on purpose: publishing authenticates through npm trusted publishing (OIDC),
# and setup-node's registry-url writes an .npmrc whose placeholder token shadows the OIDC
# exchange, which npm reports as a masked E404 on PUT.
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 24
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build packages
run: pnpm build:packages
- name: Pack release tarballs
id: pack
shell: bash
run: |
set -euo pipefail
# Update this list (and the docs in RELEASING.md) when a package is added or renamed.
packages=(
"packages/maa-log-kernel"
"packages/maa-log-parser"
"packages/maa-log-runtime"
"packages/maa-log-adapter"
"packages/maa-log-tools"
)
pack_root="${RUNNER_TEMP}/mla-npm-packages"
rm -rf "${pack_root}"
mkdir -p "${pack_root}"
for pkg_dir in "${packages[@]}"; do
echo "==== ${pkg_dir} ===="
pnpm --dir "${pkg_dir}" pack --pack-destination "${pack_root}"
done
mapfile -t tarballs < <(find "${pack_root}" -maxdepth 1 -type f -name '*.tgz' -print | sort)
if [ "${#tarballs[@]}" -ne "${#packages[@]}" ]; then
echo "Expected one tarball per package (${#packages[@]}), found ${#tarballs[@]}." >&2
exit 1
fi
printf 'pack_dir=%s\n' "${pack_root}" >> "${GITHUB_OUTPUT}"
printf 'tarball_count=%s\n' "${#tarballs[@]}" >> "${GITHUB_OUTPUT}"
# The pack directory is uploaded through a wildcard on purpose: a wildcard makes the artifact
# root the directory itself, so the tarballs land at the artifact root instead of nested under
# their parent directory name.
- name: Upload release tarballs
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: npm-packages
path: ${{ steps.pack.outputs.pack_dir }}/*.tgz
if-no-files-found: error
publish:
needs: pack
if: ${{ github.repository == 'MaaXYZ/MaaLogAnalyzer' }}
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
id-token: write
steps:
- name: Download release tarballs
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: npm-packages
path: dist/npm
# No install, no build and no checkout here: the tarballs are published exactly as the pack job
# produced them, and an OIDC credential is the only authentication involved.
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: 24
- name: Publish release tarballs
shell: bash
env:
EXPECTED_TARBALLS: ${{ needs.pack.outputs.tarball_count }}
run: |
set -euo pipefail
npm_version="$(npm --version)"
echo "npm ${npm_version}"
# Trusted publishing requires npm >= 11.5.1. Fail loudly here rather than letting it
# surface later as the masked E404 that npm returns for any authentication failure.
node -e '
const [major, minor, patch] = process.argv[1].split(".").map(Number);
const supported = major > 11 || (major === 11 && (minor > 5 || (minor === 5 && patch >= 1)));
if (!supported) {
console.error(`npm ${process.argv[1]} does not support trusted publishing (need >= 11.5.1)`);
process.exit(1);
}
' "$npm_version"
# Trusted publishing must not ride on a long-lived token: a token left in the environment
# would silently replace the OIDC credential this workflow exists to use.
if [ -n "${NODE_AUTH_TOKEN:-}" ]; then
echo "NODE_AUTH_TOKEN is set; trusted publishing expects no npm token." >&2
exit 1
fi
# A stale token in any npmrc would shadow the OIDC exchange, so drop it explicitly.
npm config delete "//registry.npmjs.org/:_authToken" >/dev/null 2>&1 || true
if ! [[ "${EXPECTED_TARBALLS}" =~ ^[0-9]+$ ]]; then
echo "Expected tarball count from the pack job is missing: '${EXPECTED_TARBALLS}'." >&2
exit 1
fi
mapfile -t tarballs < <(find dist/npm -maxdepth 1 -type f -name '*.tgz' -print | sort)
if [ "${#tarballs[@]}" -ne "${EXPECTED_TARBALLS}" ]; then
echo "Expected ${EXPECTED_TARBALLS} tarballs in the artifact, found ${#tarballs[@]}." >&2
exit 1
fi
package_exists() {
local package_ref="$1"
local output
if output=$(npm view "${package_ref}" version 2>&1); then
return 0
fi
if grep -q 'E404' <<< "${output}"; then
return 1
fi
echo "Unable to query ${package_ref} on npm:" >&2
echo "${output}" >&2
exit 1
}
metadata_root="${RUNNER_TEMP}/mla-npm-package-metadata"
published=0
for tarball in "${tarballs[@]}"; do
# Read the identity from the artifact itself: the already-published check must describe
# what would actually be uploaded, not what some other checkout claims.
rm -rf "${metadata_root}"
mkdir -p "${metadata_root}"
tar -xzf "${tarball}" -C "${metadata_root}" package/package.json
package_name="$(node -e 'process.stdout.write(require(process.argv[1]).name)' "${metadata_root}/package/package.json")"
package_version="$(node -e 'process.stdout.write(require(process.argv[1]).version)' "${metadata_root}/package/package.json")"
package_ref="${package_name}@${package_version}"
if package_exists "${package_ref}"; then
echo "Skip existing: ${package_ref}"
continue
fi
echo "Publish ${package_ref}"
# Provenance is kept explicit: it is generated from the same OIDC identity, and losing it
# silently would be a supply-chain regression.
npm publish "${tarball}" --access public --provenance
published=$((published + 1))
done
if [ "${published}" -eq 0 ]; then
echo "All package versions already exist."
fi