@_linked/server 2.3.0 → 2.3.1

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.
@@ -0,0 +1,18 @@
1
+ name: PR
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - main
7
+
8
+ jobs:
9
+ checks:
10
+ uses: linked-fw/.github/.github/workflows/pr.yml@v1
11
+ # The changeset reminder posts a PR comment. A reusable workflow only holds what its
12
+ # caller granted, and the org default is read-only.
13
+ permissions:
14
+ contents: read
15
+ pull-requests: write
16
+ with:
17
+ require-tests: true
18
+ run-e2e: false
@@ -1,3 +1,8 @@
1
+ # Calls the shared workflow in linked-fw/.github.
2
+ #
3
+ # This FILENAME is what npm's trusted-publisher check validates — not the shared workflow's.
4
+ # Renaming this file invalidates this package's trusted publisher, and the only symptom is
5
+ # that releases quietly start needing manual approval again.
1
6
  name: Publish
2
7
 
3
8
  on:
@@ -9,152 +14,17 @@ concurrency: ${{ github.workflow }}-${{ github.ref }}
9
14
 
10
15
  jobs:
11
16
  release:
12
- name: Publish Release
13
- runs-on: ubuntu-latest
17
+ uses: linked-fw/.github/.github/workflows/publish.yml@v1
14
18
  permissions:
15
19
  contents: write
16
20
  pull-requests: write
17
- # `npm stage publish --provenance` signs the tarball with a GitHub OIDC token, so the
18
- # job needs to be able to mint one. This does NOT switch the package to OIDC trusted
19
- # publishing — authentication is still the org npm token. It only lets npm attest where
20
- # the tarball was built, which is worth having on a package a human is about to approve
21
- # sight-unseen.
21
+ # Needed HERE as well as in the shared workflow: a reusable workflow cannot widen the
22
+ # permissions its caller was granted, and without this npm never gets an id-token and
23
+ # every release silently falls back to the approval queue.
22
24
  id-token: write
23
- steps:
24
- # Author the changesets "Version Packages" PR as the org release App (not the default
25
- # GITHUB_TOKEN) so its CI runs without a manual "Approve and run" gate. Requires the org
26
- # App installed on this repo + org secrets RELEASE_APP_ID / RELEASE_APP_PRIVATE_KEY.
27
- - name: Generate GitHub App token
28
- id: app-token
29
- uses: actions/create-github-app-token@v2
30
- with:
31
- app-id: ${{ secrets.RELEASE_APP_ID }}
32
- private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
33
-
34
- - name: Checkout
35
- uses: actions/checkout@v4
36
- with:
37
- token: ${{ steps.app-token.outputs.token }}
38
-
39
- - name: Setup Node.js
40
- uses: actions/setup-node@v4
41
- with:
42
- node-version: 22.16.0
43
- registry-url: 'https://registry.npmjs.org'
44
-
45
- # `npm stage` landed in CLI 11.15.0; Node 22.16 ships npm 10.x, so the bundled one
46
- # cannot stage. Pinned rather than `@latest` so a future npm release cannot change how
47
- # releases behave without a commit here.
48
- - name: Use an npm that can stage
49
- run: npm i -g npm@^11.15.0
50
-
51
- - name: Install dependencies
52
- run: npm ci --legacy-peer-deps
53
-
54
- - name: Build
55
- run: npm run build
56
-
57
- # No `publish:` — changesets only opens/updates the version PR here. Publishing is the
58
- # step below, because `changeset publish` shells out to `npm publish`, which a
59
- # stage-only token cannot do (changesets/changesets#2025 is open for first-class
60
- # support). Splitting them keeps changesets doing what it is good at — versions and
61
- # changelogs — and leaves the registry call to us.
62
- - name: Create release Pull Request
63
- id: changesets
64
- uses: changesets/action@v1
65
- with:
66
- title: 'chore: release'
67
- commit: 'chore: release'
68
- env:
69
- GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
70
-
71
- # Stage the version for a human to approve.
72
- #
73
- # A staged version is uploaded but NOT public: a maintainer reviews it and approves with
74
- # 2FA, from the Staged Packages tab in the npm user menu or `npm stage approve`. That is
75
- # the point — every release keeps a proof-of-presence step even though CI is
76
- # unattended — and it is why the org token is scoped "read and write (stage only)".
77
- #
78
- # Idempotent: this workflow runs on every push to main, including the merge of the
79
- # version PR and any later commit, so it must do nothing when the version is already on
80
- # the registry or already sitting in the queue.
81
- - name: Stage the release for approval
82
- if: steps.changesets.outputs.hasChangesets != 'true'
83
- env:
84
- NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
85
- NPM_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
86
- run: |
87
- set -euo pipefail
88
- name=$(node -p "require('./package.json').name")
89
- version=$(node -p "require('./package.json').version")
90
- private=$(node -p "require('./package.json').private === true")
91
- if [ "$private" = "true" ]; then
92
- echo "$name is private — nothing to publish."; exit 0
93
- fi
94
-
95
- if npm view "$name@$version" version >/dev/null 2>&1; then
96
- echo "$name@$version is already on the registry — nothing to do."
97
- exit 0
98
- fi
99
-
100
- if npm stage list "$name" 2>/dev/null | grep -q "$version"; then
101
- echo "$name@$version is already staged and waiting for approval."
102
- exit 0
103
- fi
104
-
105
- echo "Staging $name@$version…"
106
- # Capture the output: `npm stage publish` prints the stage id, and `npm stage
107
- # approve` takes ONLY that id — a package spec is rejected with "stage-id must be a
108
- # valid UUID". Without this the notice below hands out a command that does not work.
109
- out=$(npm stage publish --access public --provenance 2>&1 | tee /dev/stderr)
110
- uuid='[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
111
- # `|| true` because the script runs under `set -euo pipefail`: a grep that matches
112
- # nothing exits 1 and would fail the step even though the staging itself succeeded.
113
- stage_id=$(printf '%s' "$out" | grep -oE "$uuid" | tail -1 || true)
114
-
115
- {
116
- echo "### 📦 \`$name@$version\` is staged, not published"
117
- echo
118
- echo "It is uploaded and held for review. **Approve it to make it public:**"
119
- echo
120
- if [ -n "$stage_id" ]; then
121
- echo "- **CLI:** \`npm stage approve $stage_id\`"
122
- else
123
- echo "- **CLI:** \`npm stage list $name\` to find the id, then"
124
- echo " \`npm stage approve <stage-id>\`"
125
- fi
126
- echo "- **Web:** [npmjs.com](https://www.npmjs.com) → your avatar → **Staged"
127
- echo " Packages** → **Approve**. The button stays disabled until npm has"
128
- echo " finished scanning the tarball; the page refreshes every minute."
129
- echo
130
- echo "Both prompt for 2FA. Until then \`npm install $name\` still resolves"
131
- echo "\`$(npm view "$name" version 2>/dev/null || echo 'nothing')\`."
132
- } >> "$GITHUB_STEP_SUMMARY"
133
-
134
- if [ -n "$stage_id" ]; then
135
- echo "::notice title=Approval needed::$name@$version is staged. Run: npm stage approve $stage_id"
136
- else
137
- echo "::notice title=Approval needed::$name@$version is staged, but the stage id could not be read from the output. Run: npm stage list $name"
138
- fi
139
-
140
- # When changesets opened/updated the version PR, merge it so the release reaches the
141
- # staging queue without a manual click. App token → the merge's push re-triggers this
142
- # workflow, which then stages. DIRECT-merge (not `--auto`): GitHub
143
- # auto-merge ignores branch-protection review-bypass allowances; main is check-only so a
144
- # direct merge lands once the required check is green — retry until then.
145
- - name: Merge the version PR to stage the release
146
- if: steps.changesets.outputs.hasChangesets == 'true'
147
- env:
148
- GH_TOKEN: ${{ steps.app-token.outputs.token }}
149
- run: |
150
- pr=$(gh pr list --base main --head changeset-release/main --state open --json number --jq '.[0].number // empty')
151
- if [ -z "$pr" ]; then echo "No open version PR (nothing to merge)."; exit 0; fi
152
- for i in $(seq 1 40); do
153
- if gh pr merge "$pr" --merge 2>/tmp/merge_err; then
154
- echo "Merged version PR #$pr on attempt $i."
155
- exit 0
156
- fi
157
- echo "Attempt $i/40: version PR #$pr not mergeable yet ($(tr -d '\n' < /tmp/merge_err)); waiting for the required check…"
158
- sleep 15
159
- done
160
- echo "::warning::Version PR #$pr not merged after retries — merge it manually."
25
+ # Named rather than `inherit`: `inherit` forwards everything this repo can see, which is
26
+ # how a community repo would end up forwarding a first-party token.
27
+ secrets:
28
+ NPM_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}
29
+ RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }}
30
+ RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @\_linked/server
2
2
 
3
+ ## 2.3.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#40](https://github.com/linked-fw/server/pull/40) [`804851d`](https://github.com/linked-fw/server/commit/804851d16f005b56893c73561aaf72ad64a78434) Thanks [@flyon](https://github.com/flyon)! - Point `repository.url` at the linked-fw organisation, so npm provenance verification matches the repository that builds the package.
8
+
3
9
  ## 2.3.0
4
10
 
5
11
  ### Minor Changes
package/package.json CHANGED
@@ -8,9 +8,9 @@
8
8
  },
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "git+https://github.com/linked-cm/server.git"
11
+ "url": "git+https://github.com/linked-fw/server.git"
12
12
  },
13
- "version": "2.3.0",
13
+ "version": "2.3.1",
14
14
  "linkedPackage": true,
15
15
  "type": "module",
16
16
  "main": "lib/esm/index.js",
@@ -1,44 +0,0 @@
1
- name: Changeset Check
2
-
3
- on:
4
- pull_request:
5
- branches:
6
- - main
7
-
8
- jobs:
9
- changeset-check:
10
- name: Check for changeset
11
- # Skip the check on the automated Release PR.
12
- if: ${{ github.head_ref != 'changeset-release/main' }}
13
- runs-on: ubuntu-latest
14
- steps:
15
- - name: Checkout
16
- uses: actions/checkout@v4
17
- with:
18
- fetch-depth: 0
19
-
20
- - name: Check for changeset files
21
- uses: actions/github-script@v7
22
- with:
23
- script: |
24
- const { data: files } = await github.rest.pulls.listFiles({
25
- owner: context.repo.owner,
26
- repo: context.repo.repo,
27
- pull_number: context.issue.number,
28
- });
29
-
30
- const hasChangeset = files.some(f =>
31
- f.filename.startsWith('.changeset/') &&
32
- f.filename.endsWith('.md') &&
33
- f.filename !== '.changeset/README.md'
34
- );
35
-
36
- if (!hasChangeset) {
37
- await github.rest.issues.createComment({
38
- owner: context.repo.owner,
39
- repo: context.repo.repo,
40
- issue_number: context.issue.number,
41
- body: "No changeset found. If this PR should trigger a release, run `npx changeset` and commit the generated file.\n\nIf this change doesn't need a release (docs, CI config, etc.), you can ignore this message."
42
- });
43
- core.warning('No changeset file found in this PR.');
44
- }
@@ -1,43 +0,0 @@
1
- name: CI
2
-
3
- on:
4
- pull_request:
5
- branches:
6
- - main
7
-
8
- jobs:
9
- build-and-test:
10
- name: Build & Test
11
- runs-on: ubuntu-latest
12
- steps:
13
- - name: Detect Release PR
14
- id: rpr
15
- run: |
16
- if [[ "${{ github.event.pull_request.head.ref }}" == "changeset-release/main" ]]; then
17
- echo "is_release_pr=true" >> $GITHUB_OUTPUT
18
- echo "Release PR from changesets/action detected — skipping build/test (auto-generated version+CHANGELOG only)."
19
- else
20
- echo "is_release_pr=false" >> $GITHUB_OUTPUT
21
- fi
22
-
23
- - name: Checkout
24
- if: steps.rpr.outputs.is_release_pr == 'false'
25
- uses: actions/checkout@v4
26
-
27
- - name: Setup Node.js
28
- if: steps.rpr.outputs.is_release_pr == 'false'
29
- uses: actions/setup-node@v4
30
- with:
31
- node-version: 22.16.0
32
-
33
- - name: Install dependencies
34
- if: steps.rpr.outputs.is_release_pr == 'false'
35
- run: npm ci --legacy-peer-deps
36
-
37
- - name: Build
38
- if: steps.rpr.outputs.is_release_pr == 'false'
39
- run: npm run build
40
-
41
- - name: Test
42
- if: steps.rpr.outputs.is_release_pr == 'false'
43
- run: npm test --if-present