Skip to content

Commit 9f99595

Browse files
refactor(ci): use reusable workflows from kjldev/.github
Extract generic release mechanics to the org-wide kjldev/.github repo. Caller workflows now delegate to the reusable versions via workflow_call, making the release process adoptable across all repos with a single reference. - release-pr.yml: thin caller of kjldev/.github/.github/workflows/release-pr.yml - ci.yml: changeset-check delegates to kjldev/.github/.github/workflows/changeset-check.yml - workflows: fix action versions (checkout@v4, setup-dotnet@v4) - scripts: add --base-branch param + Step 0 auto-patches .changeset/config.json Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent b47b068 commit 9f99595

5 files changed

Lines changed: 100 additions & 100 deletions

File tree

.github/workflows/cd.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525

2626
steps:
2727
- name: Checkout code
28-
uses: actions/checkout@v6
28+
uses: actions/checkout@v4
2929
with:
3030
fetch-depth: 0
3131

@@ -63,7 +63,7 @@ jobs:
6363
6464
- name: Set up .NET
6565
if: ${{ steps.release-check.outputs.should_release == 'true' }}
66-
uses: actions/setup-dotnet@v5
66+
uses: actions/setup-dotnet@v4
6767
with:
6868
global-json-file: ./global.json
6969

.github/workflows/ci.yml

Lines changed: 7 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ jobs:
1515

1616
steps:
1717
- name: Checkout code
18-
uses: actions/checkout@v6
18+
uses: actions/checkout@v4
1919

2020
- name: Set up .NET
21-
uses: actions/setup-dotnet@v5
21+
uses: actions/setup-dotnet@v4
2222
with:
2323
global-json-file: ./global.json
2424

@@ -38,10 +38,10 @@ jobs:
3838

3939
steps:
4040
- name: Checkout code
41-
uses: actions/checkout@v6
41+
uses: actions/checkout@v4
4242

4343
- name: Set up .NET
44-
uses: actions/setup-dotnet@v5
44+
uses: actions/setup-dotnet@v4
4545
with:
4646
global-json-file: ./src/global.json
4747

@@ -64,10 +64,10 @@ jobs:
6464

6565
steps:
6666
- name: Checkout code
67-
uses: actions/checkout@v6
67+
uses: actions/checkout@v4
6868

6969
- name: Set up .NET
70-
uses: actions/setup-dotnet@v5
70+
uses: actions/setup-dotnet@v4
7171
with:
7272
global-json-file: ./samples/SampleApp/global.json
7373

@@ -82,47 +82,7 @@ jobs:
8282

8383
changeset-check:
8484
name: Changeset Check
85-
runs-on: ubuntu-latest
86-
87-
steps:
88-
- name: Checkout code
89-
uses: actions/checkout@v6
90-
with:
91-
fetch-depth: 0
92-
93-
- name: Check for changeset
94-
env:
95-
HEAD_REF: ${{ github.head_ref }}
96-
PR_LABELS: ${{ toJson(github.event.pull_request.labels.*.name) }}
97-
shell: bash
98-
run: |
99-
set -euo pipefail
100-
101-
# Version Packages PRs are created by the release bot — no changeset needed
102-
if [[ "${HEAD_REF}" == changeset-release/* ]]; then
103-
echo "Version Packages PR — changeset check skipped."
104-
exit 0
105-
fi
106-
107-
# PRs labelled skip-changeset are explicitly opted out (docs-only, CI-only, etc.)
108-
if echo "${PR_LABELS}" | grep -q '"skip-changeset"'; then
109-
echo "skip-changeset label present — changeset check skipped."
110-
exit 0
111-
fi
112-
113-
git fetch origin main --depth=1
114-
115-
changed_files="$(git diff --name-only origin/main...HEAD)"
116-
changeset_files="$(echo "${changed_files}" | grep -E '^\.changeset/[^/]+\.md$' | grep -v 'README\.md' || true)"
117-
118-
if [[ -z "${changeset_files}" ]]; then
119-
echo "::error::No changeset file found."
120-
echo "::error::Run 'just changeset' to create one, or add the 'skip-changeset' label if this PR needs no release note."
121-
exit 1
122-
fi
123-
124-
echo "✅ Changeset found:"
125-
echo "${changeset_files}"
85+
uses: kjldev/.github/.github/workflows/changeset-check.yml@main
12686

12787
ci-gate:
12888
name: CI Gate

.github/workflows/release-pr.yml

Lines changed: 8 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,17 @@
11
name: Release PR
22

3-
permissions:
4-
contents: write
5-
pull-requests: write
6-
73
on:
84
push:
95
branches:
106
- main
117

128
jobs:
139
release-pr:
14-
name: Create or update Release PR
15-
runs-on: ubuntu-latest
16-
17-
steps:
18-
- name: Generate GitHub App token
19-
id: app-token
20-
if: ${{ secrets.APP_ID != '' }}
21-
uses: actions/create-github-app-token@v1
22-
with:
23-
app-id: ${{ secrets.APP_ID }}
24-
private-key: ${{ secrets.APP_PRIVATE_KEY }}
25-
26-
- name: Checkout code
27-
uses: actions/checkout@v6
28-
with:
29-
fetch-depth: 0
30-
token: ${{ steps.app-token.outputs.token || secrets.CHANGESET_TOKEN }}
31-
32-
- name: Set up Bun
33-
uses: oven-sh/setup-bun@v2
34-
35-
- name: Install dependencies
36-
run: bun install
37-
38-
- name: Create or update Release PR
39-
uses: changesets/action@v1
40-
with:
41-
version: bun run version-packages
42-
createGithubReleases: false
43-
env:
44-
GITHUB_TOKEN: ${{ steps.app-token.outputs.token || secrets.CHANGESET_TOKEN }}
10+
uses: kjldev/.github/.github/workflows/release-pr.yml@main
11+
with:
12+
install-command: bun install
13+
version-command: bun run version-packages
14+
secrets:
15+
APP_ID: ${{ secrets.APP_ID }}
16+
APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
17+
CHANGESET_TOKEN: ${{ secrets.CHANGESET_TOKEN }}

scripts/setup-release.ps1

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ param (
8787

8888
[string]$AppPem = '',
8989

90+
[string]$BaseBranch = 'main',
91+
9092
[switch]$DryRun
9193
)
9294

@@ -178,8 +180,37 @@ Write-Host " Scope: $Scope"
178180
Write-Host " Token type: $TokenType"
179181
Write-Host ""
180182

183+
# ─── Step 0: .changeset/config.json ──────────────────────────────────────────
184+
Write-Step "Step 0/5 — .changeset/config.json"
185+
186+
$ChangesetConfig = '.changeset/config.json'
187+
if (Test-Path $ChangesetConfig) {
188+
$cfg = Get-Content $ChangesetConfig -Raw | ConvertFrom-Json
189+
$currentRepo = ''
190+
if ($cfg.changelog -is [array] -and $cfg.changelog.Count -gt 1 -and $cfg.changelog[1] -is [psobject]) {
191+
$currentRepo = $cfg.changelog[1].repo
192+
}
193+
if ($currentRepo -eq $FullRepo -and $cfg.baseBranch -eq $BaseBranch) {
194+
Write-OK ".changeset/config.json already correct — skipping."
195+
} else {
196+
Write-Info "Patching .changeset/config.json: repo → $FullRepo, baseBranch → $BaseBranch"
197+
if ($DryRun) {
198+
Write-Dry "Update $ChangesetConfig: changelog[1].repo=$FullRepo, baseBranch=$BaseBranch"
199+
} else {
200+
if ($cfg.changelog -is [array] -and $cfg.changelog.Count -gt 1) {
201+
$cfg.changelog[1] | Add-Member -MemberType NoteProperty -Name 'repo' -Value $FullRepo -Force
202+
}
203+
$cfg | Add-Member -MemberType NoteProperty -Name 'baseBranch' -Value $BaseBranch -Force
204+
$cfg | ConvertTo-Json -Depth 10 | Set-Content $ChangesetConfig -Encoding UTF8
205+
Write-OK ".changeset/config.json updated."
206+
}
207+
}
208+
} else {
209+
Write-Warn ".changeset/config.json not found — run 'npx changeset init' first, then re-run this script."
210+
}
211+
181212
# ─── Step 1: branch ruleset ───────────────────────────────────────────────────
182-
Write-Step "Step 1/4 — Branch ruleset (protect main)"
213+
Write-Step "Step 1/5 — Branch ruleset (protect main)"
183214

184215
$BranchRulesetName = 'Protect main branch'
185216
if (Test-RulesetExists $BranchRulesetName) {
@@ -228,7 +259,7 @@ if (Test-RulesetExists $BranchRulesetName) {
228259
}
229260

230261
# ─── Step 2: tag ruleset ──────────────────────────────────────────────────────
231-
Write-Step "Step 2/4 — Tag ruleset (protect v* tags)"
262+
Write-Step "Step 2/5 — Tag ruleset (protect v* tags)"
232263

233264
$TagRulesetName = 'Protect release tags'
234265
if (Test-RulesetExists $TagRulesetName) {
@@ -289,7 +320,7 @@ if (Test-RulesetExists $TagRulesetName) {
289320
}
290321

291322
# ─── Step 3: skip-changeset label ─────────────────────────────────────────────
292-
Write-Step "Step 3/4 — GitHub label: skip-changeset"
323+
Write-Step "Step 3/5 — GitHub label: skip-changeset"
293324

294325
if (Test-LabelExists 'skip-changeset') {
295326
Write-OK "Label 'skip-changeset' already exists — skipping."
@@ -309,7 +340,7 @@ if (Test-LabelExists 'skip-changeset') {
309340
}
310341

311342
# ─── Step 4: secrets guidance ─────────────────────────────────────────────────
312-
Write-Step "Step 4/4 — Repository secrets"
343+
Write-Step "Step 4/5 — Repository secrets"
313344

314345
switch ($TokenType) {
315346
'app' {

scripts/setup-release.sh

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ TOKEN_TYPE="app"
5252
GHES_HOST=""
5353
APP_ID=""
5454
APP_PEM=""
55+
BASE_BRANCH="main"
5556
DRY_RUN=false
5657

5758
# ─── colours ─────────────────────────────────────────────────────────────────
@@ -115,14 +116,15 @@ _tag_ruleset_ui_instructions() {
115116
# ─── argument parsing ─────────────────────────────────────────────────────────
116117
while [[ $# -gt 0 ]]; do
117118
case "$1" in
118-
--owner) OWNER="$2"; shift 2 ;;
119-
--repo) REPO="$2"; shift 2 ;;
120-
--scope) SCOPE="$2"; shift 2 ;;
121-
--token-type) TOKEN_TYPE="$2";shift 2 ;;
122-
--ghes-host) GHES_HOST="$2"; shift 2 ;;
123-
--app-id) APP_ID="$2"; shift 2 ;;
124-
--app-pem) APP_PEM="$2"; shift 2 ;;
125-
--dry-run) DRY_RUN=true; shift ;;
119+
--owner) OWNER="$2"; shift 2 ;;
120+
--repo) REPO="$2"; shift 2 ;;
121+
--scope) SCOPE="$2"; shift 2 ;;
122+
--token-type) TOKEN_TYPE="$2"; shift 2 ;;
123+
--ghes-host) GHES_HOST="$2"; shift 2 ;;
124+
--app-id) APP_ID="$2"; shift 2 ;;
125+
--app-pem) APP_PEM="$2"; shift 2 ;;
126+
--base-branch) BASE_BRANCH="$2"; shift 2 ;;
127+
--dry-run) DRY_RUN=true; shift ;;
126128
-h|--help)
127129
print_help
128130
exit 0
@@ -167,8 +169,42 @@ echo -e " Token type: ${TOKEN_TYPE}"
167169
[[ "${DRY_RUN}" == true ]] && echo -e " ${YELLOW}DRY RUN — no changes will be made${RESET}"
168170
echo ""
169171

172+
# ── Step 0: .changeset/config.json ───────────────────────────────────────────
173+
header "Step 0/5 — .changeset/config.json"
174+
175+
CHANGESET_CONFIG=".changeset/config.json"
176+
177+
if [[ -f "${CHANGESET_CONFIG}" ]]; then
178+
current_repo="$(python3 -c "import json,sys; d=json.load(open('${CHANGESET_CONFIG}')); cfg=d.get('changelog'); print(cfg[1]['repo'] if isinstance(cfg,list) else '')" 2>/dev/null || true)"
179+
180+
if [[ "${current_repo}" == "${FULL_REPO}" ]]; then
181+
success ".changeset/config.json already points to ${FULL_REPO} — skipping."
182+
else
183+
info "Patching .changeset/config.json: repo → ${FULL_REPO}, baseBranch → ${BASE_BRANCH}"
184+
if [[ "${DRY_RUN}" == true ]]; then
185+
dry "python3: update changelog[1].repo=${FULL_REPO}, baseBranch=${BASE_BRANCH} in ${CHANGESET_CONFIG}"
186+
else
187+
python3 - <<PYEOF
188+
import json, sys
189+
with open("${CHANGESET_CONFIG}") as f:
190+
d = json.load(f)
191+
if isinstance(d.get("changelog"), list) and len(d["changelog"]) > 1 and isinstance(d["changelog"][1], dict):
192+
d["changelog"][1]["repo"] = "${FULL_REPO}"
193+
d["baseBranch"] = "${BASE_BRANCH}"
194+
with open("${CHANGESET_CONFIG}", "w") as f:
195+
json.dump(d, f, indent=2)
196+
f.write("\n")
197+
PYEOF
198+
success ".changeset/config.json updated."
199+
fi
200+
fi
201+
else
202+
warning ".changeset/config.json not found — run 'npx changeset init' first, then re-run this script."
203+
fi
204+
170205
# ── Step 1: branch ruleset ────────────────────────────────────────────────────
171-
header "Step 1/4 — Branch ruleset (protect main)"
206+
207+
header "Step 1/5 — Branch ruleset (protect main)"
172208

173209
BRANCH_RULESET_NAME="Protect main branch"
174210

@@ -220,7 +256,7 @@ ENDJSON
220256
fi
221257

222258
# ── Step 2: tag ruleset ───────────────────────────────────────────────────────
223-
header "Step 2/4 — Tag ruleset (protect v* tags)"
259+
header "Step 2/5 — Tag ruleset (protect v* tags)"
224260

225261
TAG_RULESET_NAME="Protect release tags"
226262

@@ -273,7 +309,7 @@ ENDJSON
273309
fi
274310

275311
# ── Step 3: skip-changeset label ──────────────────────────────────────────────
276-
header "Step 3/4 — GitHub label: skip-changeset"
312+
header "Step 3/5 — GitHub label: skip-changeset"
277313

278314
if label_exists "skip-changeset"; then
279315
success "Label 'skip-changeset' already exists — skipping."
@@ -294,7 +330,7 @@ else
294330
fi
295331

296332
# ── Step 4: secrets guidance ──────────────────────────────────────────────────
297-
header "Step 4/4 — Repository secrets"
333+
header "Step 4/5 — Repository secrets"
298334

299335
_check_secret() {
300336
local secret_name="$1"

0 commit comments

Comments
 (0)