@ankhorage/devtools 1.15.5 → 1.15.7

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 CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # @ankhorage/devtools
5
5
 
6
- ![license: MIT](././paradox/badges/license.svg) ![npm: v1.15.5](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
6
+ ![license: MIT](././paradox/badges/license.svg) ![npm: v1.15.7](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
7
7
 
8
8
  Shared tooling, repository automation, runtime policies, and agent standards for Ankhorage TypeScript projects
9
9
 
@@ -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:
@@ -107,6 +119,7 @@ jobs:
107
119
  echo "versioned=true" >> "$GITHUB_OUTPUT"
108
120
  echo "package_name=$(node -p "require('./package.json').name")" >> "$GITHUB_OUTPUT"
109
121
  echo "package_version=$after_version" >> "$GITHUB_OUTPUT"
122
+ echo "release_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
110
123
  fi
111
124
 
112
125
  - name: Publish unpublished packages
@@ -132,70 +145,128 @@ jobs:
132
145
  __ANKH_APM_RELEASE_COMMAND__ validate . --allow-owner-code --artifact "$artifact"
133
146
  npm publish "$artifact" --ignore-scripts
134
147
  fi
135
- if ! git rev-parse -q --verify "refs/tags/v${package_version}" >/dev/null; then
136
- git tag "v${package_version}"
137
- fi
148
+ - name: Skip release tooling
149
+ if: hashFiles('.changeset/config.json') == ''
150
+ run: echo "No Changesets config found; skipping versioning and publishing."
138
151
 
139
- - name: Verify published npm artifact
140
- if: steps.release.outputs.versioned == 'true'
152
+ verify-publication:
153
+ needs: release
154
+ if: needs.release.outputs.versioned == 'true'
155
+ runs-on: ubuntu-latest
156
+
157
+ steps:
158
+ - name: Setup Node for npm verification
159
+ uses: actions/setup-node@v4
160
+ with:
161
+ node-version: '__ANKH_NODE_VERSION__'
162
+ registry-url: https://registry.npmjs.org
163
+
164
+ - name: Update npm
165
+ run: npm install -g npm@latest
166
+
167
+ - name: Verify published npm artifact from a fresh runner
141
168
  env:
142
- PUBLISHED_PACKAGE_NAME: ${{ steps.release.outputs.package_name }}
143
- PUBLISHED_PACKAGE_VERSION: ${{ steps.release.outputs.package_version }}
169
+ PUBLISHED_PACKAGE_NAME: ${{ needs.release.outputs.package_name }}
170
+ PUBLISHED_PACKAGE_VERSION: ${{ needs.release.outputs.package_version }}
144
171
  run: |
145
172
  set -euo pipefail
146
173
  package_spec="${PUBLISHED_PACKAGE_NAME}@${PUBLISHED_PACKAGE_VERSION}"
147
174
  registry_evidence="${RUNNER_TEMP}/npm-publish-verification.json"
148
175
  artifact="${RUNNER_TEMP}/npm-publish-verification.tgz"
149
176
  pack_dir="${RUNNER_TEMP}/npm-pack-verification"
150
- max_attempts=30
177
+ max_attempts=60
151
178
  retry_seconds=30
152
179
  mkdir -p "$pack_dir"
153
180
 
181
+ last_stage="registry-metadata"
154
182
  for attempt in $(seq 1 "$max_attempts"); do
155
183
  echo "Verifying ${package_spec} on npm (attempt ${attempt}/${max_attempts})..."
184
+ last_stage="registry-metadata"
185
+
156
186
  if npm view "$package_spec" version dist.tarball dist.integrity --json > "$registry_evidence"; then
157
187
  resolved_version="$(node -e "const p=require(process.argv[1]); process.stdout.write(p.version ?? '')" "$registry_evidence")"
158
188
  tarball="$(node -e "const p=require(process.argv[1]); process.stdout.write(p['dist.tarball'] ?? '')" "$registry_evidence")"
159
189
  integrity="$(node -e "const p=require(process.argv[1]); process.stdout.write(p['dist.integrity'] ?? '')" "$registry_evidence")"
160
190
 
161
191
  if [ "$resolved_version" = "$PUBLISHED_PACKAGE_VERSION" ] && [ -n "$tarball" ] && [ -n "$integrity" ]; then
192
+ last_stage="tarball-download"
162
193
  if curl --fail --location --silent --show-error --output "$artifact" "$tarball"; then
194
+ last_stage="integrity"
163
195
  if EXPECTED_INTEGRITY="$integrity" ARTIFACT="$artifact" node -e "const { createHash }=require('node:crypto'); const { readFileSync }=require('node:fs'); const actual='sha512-'+createHash('sha512').update(readFileSync(process.env.ARTIFACT)).digest('base64'); if(actual!==process.env.EXPECTED_INTEGRITY){console.error('Downloaded npm tarball integrity mismatch.'); process.exit(1)}"; then
164
- npm pack "$package_spec" --pack-destination "$pack_dir" >/dev/null
165
- echo "Verified ${package_spec}: metadata, integrity, tarball download, and npm pack are available."
166
- exit 0
196
+ last_stage="npm-pack"
197
+ attempt_pack_dir="$pack_dir/attempt-${attempt}"
198
+ mkdir -p "$attempt_pack_dir"
199
+ if npm pack "$package_spec" --pack-destination "$attempt_pack_dir" >/dev/null; then
200
+ echo "Verified ${package_spec}: metadata, integrity, tarball download, and npm pack are available."
201
+ exit 0
202
+ fi
167
203
  fi
168
204
  fi
169
205
  fi
170
206
  fi
171
207
 
208
+ echo "Published npm artifact not ready at stage: ${last_stage}."
172
209
  if [ "$attempt" -lt "$max_attempts" ]; then
173
210
  sleep "$retry_seconds"
174
211
  fi
175
212
  done
176
213
 
177
- echo "Published npm artifact did not become retrievable after ${max_attempts} attempts."
214
+ echo "Published npm artifact did not become retrievable after ${max_attempts} attempts; last stage: ${last_stage}."
178
215
  cat "$registry_evidence" 2>/dev/null || true
179
216
  exit 1
180
217
 
181
- - name: Finalize Changesets v3 tags and GitHub releases
182
- if: hashFiles('.changeset/config.json') != ''
218
+ finalize:
219
+ needs:
220
+ - release
221
+ - verify-publication
222
+ if: needs.release.outputs.versioned == 'true' && needs.verify-publication.result == 'success'
223
+ runs-on: ubuntu-latest
224
+
225
+ steps:
226
+ - name: Create the scoped release token
227
+ id: release-token
228
+ uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
229
+ with:
230
+ client-id: ${{ vars.ANKHORAGE_RENOVATE_SYNC_CLIENT_ID }}
231
+ private-key: ${{ secrets.ANKHORAGE_RENOVATE_SYNC_PRIVATE_KEY }}
232
+ owner: ankhorage
233
+ repositories: ${{ github.event.repository.name }}
234
+ permission-contents: write
235
+
236
+ - name: Checkout exact release commit
237
+ uses: actions/checkout@v4
238
+ with:
239
+ fetch-depth: 0
240
+ ref: ${{ needs.release.outputs.release_sha }}
241
+ token: ${{ steps.release-token.outputs.token }}
242
+
243
+ - name: Finalize Changesets v3 tag and GitHub release
183
244
  env:
184
- GH_TOKEN: ${{ github.token }}
245
+ GH_TOKEN: ${{ steps.release-token.outputs.token }}
246
+ PUBLISHED_PACKAGE_VERSION: ${{ needs.release.outputs.package_version }}
247
+ RELEASE_SHA: ${{ needs.release.outputs.release_sha }}
185
248
  run: |
186
- git tag --points-at HEAD | while IFS= read -r tag; do
187
- if [ -z "$tag" ]; then
188
- continue
249
+ set -euo pipefail
250
+ tag="v${PUBLISHED_PACKAGE_VERSION}"
251
+ remote_sha="$(git ls-remote --tags origin "refs/tags/$tag" | cut -f1)"
252
+
253
+ if [ -n "$remote_sha" ]; then
254
+ if [ "$remote_sha" != "$RELEASE_SHA" ]; then
255
+ echo "Existing tag $tag points to $remote_sha, expected $RELEASE_SHA."
256
+ exit 1
189
257
  fi
258
+ else
259
+ git tag "$tag" "$RELEASE_SHA"
190
260
  git push origin "refs/tags/$tag"
191
- if ! gh release view "$tag" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
192
- gh release create "$tag" --repo "$GITHUB_REPOSITORY" --generate-notes
193
- fi
194
- done
261
+ fi
262
+
263
+ if ! gh release view "$tag" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
264
+ gh release create "$tag" --repo "$GITHUB_REPOSITORY" --generate-notes --target "$RELEASE_SHA"
265
+ fi
195
266
 
196
267
  - name: Create the scoped rollout token
197
268
  id: rollout-token
198
- if: steps.release.outputs.versioned == 'true' && steps.release.outputs.package_name == '@ankhorage/devtools'
269
+ if: needs.release.outputs.package_name == '@ankhorage/devtools'
199
270
  uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
200
271
  with:
201
272
  client-id: ${{ vars.ANKHORAGE_RENOVATE_SYNC_CLIENT_ID }}
@@ -205,11 +276,11 @@ jobs:
205
276
  permission-contents: write
206
277
 
207
278
  - name: Trigger the Devtools consumer rollout
208
- if: steps.release.outputs.versioned == 'true' && steps.release.outputs.package_name == '@ankhorage/devtools'
279
+ if: needs.release.outputs.package_name == '@ankhorage/devtools'
209
280
  uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
210
281
  env:
211
- PUBLISHED_PACKAGE_NAME: ${{ steps.release.outputs.package_name }}
212
- PUBLISHED_PACKAGE_VERSION: ${{ steps.release.outputs.package_version }}
282
+ PUBLISHED_PACKAGE_NAME: ${{ needs.release.outputs.package_name }}
283
+ PUBLISHED_PACKAGE_VERSION: ${{ needs.release.outputs.package_version }}
213
284
  with:
214
285
  github-token: ${{ steps.rollout-token.outputs.token }}
215
286
  script: |
@@ -230,7 +301,3 @@ jobs:
230
301
  event_type: 'devtools-release',
231
302
  client_payload: { version: release.version },
232
303
  });
233
-
234
- - name: Skip release tooling
235
- if: hashFiles('.changeset/config.json') == ''
236
- 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.5",
3
+ "version": "1.15.7",
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",