@ankhorage/devtools 1.15.6 → 1.15.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/tools/workflows/files/release.yml +115 -30
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
# @ankhorage/devtools
|
|
5
5
|
|
|
6
|
-
         
|
|
7
7
|
|
|
8
8
|
Shared tooling, repository automation, runtime policies, and agent standards for Ankhorage TypeScript projects
|
|
9
9
|
|
|
@@ -363,6 +363,8 @@ A repository participates in Changesets synchronization when `.changeset/config.
|
|
|
363
363
|
|
|
364
364
|
CI and Release render their `bun-version` from the same managed Bun runtime policy used for `package.json`. They also render Changesets status, version, and publish commands from the same policy that owns the synchronized package scripts. The CI workflow installs that Bun version with the frozen lockfile, builds before repository-provider validation, runs `bunx @ankhorage/ankh doctor validate .`, and conditionally runs lint, formatting, Knip, tests, typecheck, and the strict `changeset:status --since=origin/main` guard for pull requests. After a green change reaches `main`, Release uses the scoped Ankhorage Renovate Sync App token to apply Changesets versioning directly to `main` in a `chore(release)` `[skip ci]` commit and publishes without creating a second Version Packages pull request. Release publishing calls the Devtools-owned runner through the synchronized package script; it never resolves an ambient or mutable Changesets executable. Changesets v3 creates the local release tags; the managed workflow pushes those exact tags and creates any missing GitHub Releases directly, without parsing Changesets’ human-readable publish output.
|
|
365
365
|
|
|
366
|
+
For the **first npm publication** of a new `@ankhorage/*` package, the organization publishing credential must be able to create/publish packages in the `@ankhorage` scope. With a granular npm token, grant package permission **Read and write (publish and stage)** to the `@ankhorage` scope or **All Packages**. If initial publication fails after Changesets has already pushed the release commit, correct the npm credential and rerun Release; the current unpublished version is reused and must not be bumped again. The managed workflow diagnoses this first-publish state separately from registry/network failures.
|
|
367
|
+
|
|
366
368
|
The Renovate workflow accepts only same-repository branches created by `renovate[bot]`. It calls the SHA-pinned `ankhorage/renovate` workflow to add a release Changeset for runtime Ankhorage dependency updates or an empty Changeset for dev-only updates. The trusted workflow scopes the Ankhorage Renovate Sync GitHub App token to the current repository and uses it only for the validated commit, allowing every normal pull-request CI workflow to start without manual approval. It never checks out or executes pull-request code in the privileged `pull_request_target` context.
|
|
367
369
|
|
|
368
370
|
## Managed VS Code configuration
|
|
@@ -16,10 +16,16 @@ concurrency:
|
|
|
16
16
|
jobs:
|
|
17
17
|
release:
|
|
18
18
|
runs-on: ubuntu-latest
|
|
19
|
+
outputs:
|
|
20
|
+
versioned: ${{ steps.release.outputs.versioned }}
|
|
21
|
+
package_name: ${{ steps.release.outputs.package_name }}
|
|
22
|
+
package_version: ${{ steps.release.outputs.package_version }}
|
|
23
|
+
release_sha: ${{ steps.release.outputs.release_sha }}
|
|
19
24
|
|
|
20
25
|
steps:
|
|
21
26
|
- name: Create the scoped release token
|
|
22
27
|
id: release-token
|
|
28
|
+
continue-on-error: true
|
|
23
29
|
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
|
|
24
30
|
with:
|
|
25
31
|
client-id: ${{ vars.ANKHORAGE_RENOVATE_SYNC_CLIENT_ID }}
|
|
@@ -28,6 +34,12 @@ jobs:
|
|
|
28
34
|
repositories: ${{ github.event.repository.name }}
|
|
29
35
|
permission-contents: write
|
|
30
36
|
|
|
37
|
+
- name: Diagnose unavailable scoped release token
|
|
38
|
+
if: steps.release-token.outcome == 'failure'
|
|
39
|
+
run: |
|
|
40
|
+
echo "::error title=Renovate Sync App repository access required::Could not create the scoped Ankhorage release token for ${GITHUB_REPOSITORY}. Ensure the ankhorage-renovate-sync GitHub App is installed and authorized for this repository, then rerun Release. Bootstrap policy: https://github.com/ankhorage/renovate/issues/115"
|
|
41
|
+
exit 1
|
|
42
|
+
|
|
31
43
|
- name: Checkout repository
|
|
32
44
|
uses: actions/checkout@v4
|
|
33
45
|
with:
|
|
@@ -67,7 +79,16 @@ jobs:
|
|
|
67
79
|
git checkout -B main origin/main
|
|
68
80
|
|
|
69
81
|
if [ -z "$(find .changeset -maxdepth 1 -type f -name '*.md' ! -name README.md -print -quit)" ]; then
|
|
70
|
-
|
|
82
|
+
current_subject="$(git log -1 --pretty=%s)"
|
|
83
|
+
if [ "$current_subject" = "chore(release): version packages [skip ci]" ]; then
|
|
84
|
+
echo "Recovering the canonical versioned release commit without another version bump."
|
|
85
|
+
echo "versioned=true" >> "$GITHUB_OUTPUT"
|
|
86
|
+
echo "package_name=$(node -p "require('./package.json').name")" >> "$GITHUB_OUTPUT"
|
|
87
|
+
echo "package_version=$(node -p "require('./package.json').version")" >> "$GITHUB_OUTPUT"
|
|
88
|
+
echo "release_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
|
89
|
+
else
|
|
90
|
+
echo "versioned=false" >> "$GITHUB_OUTPUT"
|
|
91
|
+
fi
|
|
71
92
|
exit 0
|
|
72
93
|
fi
|
|
73
94
|
|
|
@@ -107,13 +128,33 @@ jobs:
|
|
|
107
128
|
echo "versioned=true" >> "$GITHUB_OUTPUT"
|
|
108
129
|
echo "package_name=$(node -p "require('./package.json').name")" >> "$GITHUB_OUTPUT"
|
|
109
130
|
echo "package_version=$after_version" >> "$GITHUB_OUTPUT"
|
|
131
|
+
echo "release_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
|
110
132
|
fi
|
|
111
133
|
|
|
112
134
|
- name: Publish unpublished packages
|
|
113
135
|
if: hashFiles('.changeset/config.json') != ''
|
|
114
136
|
run: |
|
|
115
137
|
if ! node -e "const p=require('./package.json'); process.exit(p.ankh?.apm === undefined ? 1 : 0)"; then
|
|
116
|
-
|
|
138
|
+
package_name="$(node -p "require('./package.json').name")"
|
|
139
|
+
package_version="$(node -p "require('./package.json').version")"
|
|
140
|
+
registry_evidence="${RUNNER_TEMP}/npm-package-preflight.json"
|
|
141
|
+
package_absent=false
|
|
142
|
+
|
|
143
|
+
if npm view "$package_name" version --json > "$registry_evidence"; then
|
|
144
|
+
:
|
|
145
|
+
elif node -e "const p=require(process.argv[1]); if(p.error?.code !== 'E404') process.exit(1)" "$registry_evidence"; then
|
|
146
|
+
package_absent=true
|
|
147
|
+
else
|
|
148
|
+
echo "::error title=npm registry preflight failed::Could not determine whether $package_name already exists in npm. Refusing to treat an authentication or network failure as first-publish bootstrap."
|
|
149
|
+
exit 1
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
if ! __ANKH_CHANGESETS_PUBLISH_COMMAND__; then
|
|
153
|
+
if [ "$package_absent" = true ]; then
|
|
154
|
+
echo "::error title=npm scope publish access required::Initial publish of ${package_name}@${package_version} failed while the package is absent from npm. Verify that the configured npm publishing credential has Read and write (publish and stage) access to the @ankhorage scope or All Packages, then rerun Release. The already-versioned release commit on main is reusable; do not create another version bump. Bootstrap guidance: https://github.com/ankhorage/devtools/issues/225"
|
|
155
|
+
fi
|
|
156
|
+
exit 1
|
|
157
|
+
fi
|
|
117
158
|
exit 0
|
|
118
159
|
fi
|
|
119
160
|
|
|
@@ -132,15 +173,29 @@ jobs:
|
|
|
132
173
|
__ANKH_APM_RELEASE_COMMAND__ validate . --allow-owner-code --artifact "$artifact"
|
|
133
174
|
npm publish "$artifact" --ignore-scripts
|
|
134
175
|
fi
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
176
|
+
- name: Skip release tooling
|
|
177
|
+
if: hashFiles('.changeset/config.json') == ''
|
|
178
|
+
run: echo "No Changesets config found; skipping versioning and publishing."
|
|
179
|
+
|
|
180
|
+
verify-publication:
|
|
181
|
+
needs: release
|
|
182
|
+
if: needs.release.outputs.versioned == 'true'
|
|
183
|
+
runs-on: ubuntu-latest
|
|
184
|
+
|
|
185
|
+
steps:
|
|
186
|
+
- name: Setup Node for npm verification
|
|
187
|
+
uses: actions/setup-node@v4
|
|
188
|
+
with:
|
|
189
|
+
node-version: '__ANKH_NODE_VERSION__'
|
|
190
|
+
registry-url: https://registry.npmjs.org
|
|
138
191
|
|
|
139
|
-
- name:
|
|
140
|
-
|
|
192
|
+
- name: Update npm
|
|
193
|
+
run: npm install -g npm@latest
|
|
194
|
+
|
|
195
|
+
- name: Verify published npm artifact from a fresh runner
|
|
141
196
|
env:
|
|
142
|
-
PUBLISHED_PACKAGE_NAME: ${{
|
|
143
|
-
PUBLISHED_PACKAGE_VERSION: ${{
|
|
197
|
+
PUBLISHED_PACKAGE_NAME: ${{ needs.release.outputs.package_name }}
|
|
198
|
+
PUBLISHED_PACKAGE_VERSION: ${{ needs.release.outputs.package_version }}
|
|
144
199
|
run: |
|
|
145
200
|
set -euo pipefail
|
|
146
201
|
package_spec="${PUBLISHED_PACKAGE_NAME}@${PUBLISHED_PACKAGE_VERSION}"
|
|
@@ -157,9 +212,9 @@ jobs:
|
|
|
157
212
|
last_stage="registry-metadata"
|
|
158
213
|
|
|
159
214
|
if npm view "$package_spec" version dist.tarball dist.integrity --json > "$registry_evidence"; then
|
|
160
|
-
resolved_version="$(node -e "const
|
|
161
|
-
tarball="$(node -e "const
|
|
162
|
-
integrity="$(node -e "const
|
|
215
|
+
resolved_version="$(node -e "const raw=require(process.argv[1]); const p=Array.isArray(raw)&&raw.length===1?raw[0]:raw; process.stdout.write(typeof p?.version==='string'?p.version:'')" "$registry_evidence")"
|
|
216
|
+
tarball="$(node -e "const raw=require(process.argv[1]); const p=Array.isArray(raw)&&raw.length===1?raw[0]:raw; process.stdout.write(typeof p?.['dist.tarball']==='string'?p['dist.tarball']:'')" "$registry_evidence")"
|
|
217
|
+
integrity="$(node -e "const raw=require(process.argv[1]); const p=Array.isArray(raw)&&raw.length===1?raw[0]:raw; process.stdout.write(typeof p?.['dist.integrity']==='string'?p['dist.integrity']:'')" "$registry_evidence")"
|
|
163
218
|
|
|
164
219
|
if [ "$resolved_version" = "$PUBLISHED_PACKAGE_VERSION" ] && [ -n "$tarball" ] && [ -n "$integrity" ]; then
|
|
165
220
|
last_stage="tarball-download"
|
|
@@ -188,24 +243,58 @@ jobs:
|
|
|
188
243
|
cat "$registry_evidence" 2>/dev/null || true
|
|
189
244
|
exit 1
|
|
190
245
|
|
|
191
|
-
|
|
192
|
-
|
|
246
|
+
finalize:
|
|
247
|
+
needs:
|
|
248
|
+
- release
|
|
249
|
+
- verify-publication
|
|
250
|
+
if: needs.release.outputs.versioned == 'true' && needs.verify-publication.result == 'success'
|
|
251
|
+
runs-on: ubuntu-latest
|
|
252
|
+
|
|
253
|
+
steps:
|
|
254
|
+
- name: Create the scoped release token
|
|
255
|
+
id: release-token
|
|
256
|
+
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
|
|
257
|
+
with:
|
|
258
|
+
client-id: ${{ vars.ANKHORAGE_RENOVATE_SYNC_CLIENT_ID }}
|
|
259
|
+
private-key: ${{ secrets.ANKHORAGE_RENOVATE_SYNC_PRIVATE_KEY }}
|
|
260
|
+
owner: ankhorage
|
|
261
|
+
repositories: ${{ github.event.repository.name }}
|
|
262
|
+
permission-contents: write
|
|
263
|
+
|
|
264
|
+
- name: Checkout exact release commit
|
|
265
|
+
uses: actions/checkout@v4
|
|
266
|
+
with:
|
|
267
|
+
fetch-depth: 0
|
|
268
|
+
ref: ${{ needs.release.outputs.release_sha }}
|
|
269
|
+
token: ${{ steps.release-token.outputs.token }}
|
|
270
|
+
|
|
271
|
+
- name: Finalize Changesets v3 tag and GitHub release
|
|
193
272
|
env:
|
|
194
|
-
GH_TOKEN: ${{
|
|
273
|
+
GH_TOKEN: ${{ steps.release-token.outputs.token }}
|
|
274
|
+
PUBLISHED_PACKAGE_VERSION: ${{ needs.release.outputs.package_version }}
|
|
275
|
+
RELEASE_SHA: ${{ needs.release.outputs.release_sha }}
|
|
195
276
|
run: |
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
277
|
+
set -euo pipefail
|
|
278
|
+
tag="v${PUBLISHED_PACKAGE_VERSION}"
|
|
279
|
+
remote_sha="$(git ls-remote --tags origin "refs/tags/$tag" | cut -f1)"
|
|
280
|
+
|
|
281
|
+
if [ -n "$remote_sha" ]; then
|
|
282
|
+
if [ "$remote_sha" != "$RELEASE_SHA" ]; then
|
|
283
|
+
echo "Existing tag $tag points to $remote_sha, expected $RELEASE_SHA."
|
|
284
|
+
exit 1
|
|
199
285
|
fi
|
|
286
|
+
else
|
|
287
|
+
git tag "$tag" "$RELEASE_SHA"
|
|
200
288
|
git push origin "refs/tags/$tag"
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
289
|
+
fi
|
|
290
|
+
|
|
291
|
+
if ! gh release view "$tag" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
|
|
292
|
+
gh release create "$tag" --repo "$GITHUB_REPOSITORY" --generate-notes --target "$RELEASE_SHA"
|
|
293
|
+
fi
|
|
205
294
|
|
|
206
295
|
- name: Create the scoped rollout token
|
|
207
296
|
id: rollout-token
|
|
208
|
-
if:
|
|
297
|
+
if: needs.release.outputs.package_name == '@ankhorage/devtools'
|
|
209
298
|
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
|
|
210
299
|
with:
|
|
211
300
|
client-id: ${{ vars.ANKHORAGE_RENOVATE_SYNC_CLIENT_ID }}
|
|
@@ -215,11 +304,11 @@ jobs:
|
|
|
215
304
|
permission-contents: write
|
|
216
305
|
|
|
217
306
|
- name: Trigger the Devtools consumer rollout
|
|
218
|
-
if:
|
|
307
|
+
if: needs.release.outputs.package_name == '@ankhorage/devtools'
|
|
219
308
|
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
|
|
220
309
|
env:
|
|
221
|
-
PUBLISHED_PACKAGE_NAME: ${{
|
|
222
|
-
PUBLISHED_PACKAGE_VERSION: ${{
|
|
310
|
+
PUBLISHED_PACKAGE_NAME: ${{ needs.release.outputs.package_name }}
|
|
311
|
+
PUBLISHED_PACKAGE_VERSION: ${{ needs.release.outputs.package_version }}
|
|
223
312
|
with:
|
|
224
313
|
github-token: ${{ steps.rollout-token.outputs.token }}
|
|
225
314
|
script: |
|
|
@@ -240,7 +329,3 @@ jobs:
|
|
|
240
329
|
event_type: 'devtools-release',
|
|
241
330
|
client_payload: { version: release.version },
|
|
242
331
|
});
|
|
243
|
-
|
|
244
|
-
- name: Skip release tooling
|
|
245
|
-
if: hashFiles('.changeset/config.json') == ''
|
|
246
|
-
run: echo "No Changesets config found; skipping versioning and publishing."
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ankhorage/devtools",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.8",
|
|
4
4
|
"description": "Shared tooling, repository automation, runtime policies, and agent standards for Ankhorage TypeScript projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/ankhorage/devtools#readme",
|