@ankhorage/devtools 1.15.7 → 1.15.9

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.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)
6
+ ![license: MIT](././paradox/badges/license.svg) ![npm: v1.15.9](././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
 
@@ -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
@@ -46,6 +46,11 @@ jobs:
46
46
  fetch-depth: 0
47
47
  token: ${{ steps.release-token.outputs.token }}
48
48
 
49
+ - name: Synchronize latest main
50
+ run: |
51
+ git fetch origin main
52
+ git checkout -B main origin/main
53
+
49
54
  - name: Setup Bun
50
55
  uses: oven-sh/setup-bun@v2
51
56
  with:
@@ -75,14 +80,32 @@ jobs:
75
80
  id: release
76
81
  if: hashFiles('.changeset/config.json') != ''
77
82
  run: |
78
- git fetch origin main
79
- git checkout -B main origin/main
80
-
81
83
  if [ -z "$(find .changeset -maxdepth 1 -type f -name '*.md' ! -name README.md -print -quit)" ]; then
82
- echo "versioned=false" >> "$GITHUB_OUTPUT"
84
+ current_version="$(node -p "require('./package.json').version")"
85
+ release_sha=""
86
+ for candidate_sha in $(git rev-list HEAD); do
87
+ candidate_subject="$(git show -s --format=%s "$candidate_sha")"
88
+ if [ "$candidate_subject" != "chore(release): version packages [skip ci]" ]; then
89
+ continue
90
+ fi
91
+ candidate_version="$(git show "${candidate_sha}:package.json" | node -e "let s=''; process.stdin.on('data',(d)=>s+=d); process.stdin.on('end',()=>process.stdout.write(JSON.parse(s).version ?? ''))")"
92
+ if [ "$candidate_version" = "$current_version" ]; then
93
+ release_sha="$candidate_sha"
94
+ break
95
+ fi
96
+ done
97
+
98
+ if [ -n "$release_sha" ]; then
99
+ echo "Recovering canonical release commit $release_sha for version $current_version without another version bump."
100
+ echo "versioned=true" >> "$GITHUB_OUTPUT"
101
+ echo "package_name=$(node -p "require('./package.json').name")" >> "$GITHUB_OUTPUT"
102
+ echo "package_version=$current_version" >> "$GITHUB_OUTPUT"
103
+ echo "release_sha=$release_sha" >> "$GITHUB_OUTPUT"
104
+ else
105
+ echo "versioned=false" >> "$GITHUB_OUTPUT"
106
+ fi
83
107
  exit 0
84
108
  fi
85
-
86
109
  before_version="$(node -p "require('./package.json').version")"
87
110
  __ANKH_CHANGESETS_VERSION_COMMAND__
88
111
  if node -e "const p=require('./package.json'); process.exit(p.ankh?.apm === undefined ? 1 : 0)"; then
@@ -126,7 +149,26 @@ jobs:
126
149
  if: hashFiles('.changeset/config.json') != ''
127
150
  run: |
128
151
  if ! node -e "const p=require('./package.json'); process.exit(p.ankh?.apm === undefined ? 1 : 0)"; then
129
- __ANKH_CHANGESETS_PUBLISH_COMMAND__
152
+ package_name="$(node -p "require('./package.json').name")"
153
+ package_version="$(node -p "require('./package.json').version")"
154
+ registry_evidence="${RUNNER_TEMP}/npm-package-preflight.json"
155
+ package_absent=false
156
+
157
+ if npm view "$package_name" version --json > "$registry_evidence"; then
158
+ :
159
+ elif node -e "const p=require(process.argv[1]); if(p.error?.code !== 'E404') process.exit(1)" "$registry_evidence"; then
160
+ package_absent=true
161
+ else
162
+ 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."
163
+ exit 1
164
+ fi
165
+
166
+ if ! __ANKH_CHANGESETS_PUBLISH_COMMAND__; then
167
+ if [ "$package_absent" = true ]; then
168
+ 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"
169
+ fi
170
+ exit 1
171
+ fi
130
172
  exit 0
131
173
  fi
132
174
 
@@ -184,9 +226,9 @@ jobs:
184
226
  last_stage="registry-metadata"
185
227
 
186
228
  if npm view "$package_spec" version dist.tarball dist.integrity --json > "$registry_evidence"; then
187
- resolved_version="$(node -e "const p=require(process.argv[1]); process.stdout.write(p.version ?? '')" "$registry_evidence")"
188
- tarball="$(node -e "const p=require(process.argv[1]); process.stdout.write(p['dist.tarball'] ?? '')" "$registry_evidence")"
189
- integrity="$(node -e "const p=require(process.argv[1]); process.stdout.write(p['dist.integrity'] ?? '')" "$registry_evidence")"
229
+ 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")"
230
+ 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")"
231
+ 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")"
190
232
 
191
233
  if [ "$resolved_version" = "$PUBLISHED_PACKAGE_VERSION" ] && [ -n "$tarball" ] && [ -n "$integrity" ]; then
192
234
  last_stage="tarball-download"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ankhorage/devtools",
3
- "version": "1.15.7",
3
+ "version": "1.15.9",
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",