Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0

Expand Down Expand Up @@ -63,7 +63,7 @@ jobs:

- name: Set up .NET
if: ${{ steps.release-check.outputs.should_release == 'true' }}
uses: actions/setup-dotnet@v5
uses: actions/setup-dotnet@v4
with:
global-json-file: ./global.json

Expand Down
54 changes: 7 additions & 47 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v4

- name: Set up .NET
uses: actions/setup-dotnet@v5
uses: actions/setup-dotnet@v4
with:
global-json-file: ./global.json

Expand All @@ -38,10 +38,10 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v4

- name: Set up .NET
uses: actions/setup-dotnet@v5
uses: actions/setup-dotnet@v4
with:
global-json-file: ./src/global.json

Expand All @@ -64,10 +64,10 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v6
uses: actions/checkout@v4

- name: Set up .NET
uses: actions/setup-dotnet@v5
uses: actions/setup-dotnet@v4
with:
global-json-file: ./samples/SampleApp/global.json

Expand All @@ -82,47 +82,7 @@ jobs:

changeset-check:
name: Changeset Check
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Check for changeset
env:
HEAD_REF: ${{ github.head_ref }}
PR_LABELS: ${{ toJson(github.event.pull_request.labels.*.name) }}
shell: bash
run: |
set -euo pipefail

# Version Packages PRs are created by the release bot — no changeset needed
if [[ "${HEAD_REF}" == changeset-release/* ]]; then
echo "Version Packages PR — changeset check skipped."
exit 0
fi

# PRs labelled skip-changeset are explicitly opted out (docs-only, CI-only, etc.)
if echo "${PR_LABELS}" | grep -q '"skip-changeset"'; then
echo "skip-changeset label present — changeset check skipped."
exit 0
fi

git fetch origin main --depth=1

changed_files="$(git diff --name-only origin/main...HEAD)"
changeset_files="$(echo "${changed_files}" | grep -E '^\.changeset/[^/]+\.md$' | grep -v 'README\.md' || true)"

if [[ -z "${changeset_files}" ]]; then
echo "::error::No changeset file found."
echo "::error::Run 'just changeset' to create one, or add the 'skip-changeset' label if this PR needs no release note."
exit 1
fi

echo "✅ Changeset found:"
echo "${changeset_files}"
uses: kjldev/.github/.github/workflows/changeset-check.yml@main

Comment on lines 83 to 86
ci-gate:
name: CI Gate
Expand Down
43 changes: 8 additions & 35 deletions .github/workflows/release-pr.yml
Original file line number Diff line number Diff line change
@@ -1,44 +1,17 @@
name: Release PR

permissions:
contents: write
pull-requests: write

on:
push:
branches:
- main

jobs:
release-pr:
name: Create or update Release PR
runs-on: ubuntu-latest

steps:
- name: Generate GitHub App token
id: app-token
if: ${{ secrets.APP_ID != '' }}
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}

- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0
token: ${{ steps.app-token.outputs.token || secrets.CHANGESET_TOKEN }}

- name: Set up Bun
uses: oven-sh/setup-bun@v2

- name: Install dependencies
run: bun install

- name: Create or update Release PR
uses: changesets/action@v1
with:
version: bun run version-packages
createGithubReleases: false
env:
GITHUB_TOKEN: ${{ steps.app-token.outputs.token || secrets.CHANGESET_TOKEN }}
uses: kjldev/.github/.github/workflows/release-pr.yml@main
with:
Comment on lines 9 to +11
install-command: bun install
version-command: bun run version-packages
secrets:
APP_ID: ${{ secrets.APP_ID }}
APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
CHANGESET_TOKEN: ${{ secrets.CHANGESET_TOKEN }}
Comment on lines 1 to +17
39 changes: 35 additions & 4 deletions scripts/setup-release.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ param (

[string]$AppPem = '',

[string]$BaseBranch = 'main',

[switch]$DryRun
)

Expand Down Expand Up @@ -178,8 +180,37 @@ Write-Host " Scope: $Scope"
Write-Host " Token type: $TokenType"
Write-Host ""

# ─── Step 0: .changeset/config.json ──────────────────────────────────────────
Write-Step "Step 0/5 — .changeset/config.json"

$ChangesetConfig = '.changeset/config.json'
if (Test-Path $ChangesetConfig) {
$cfg = Get-Content $ChangesetConfig -Raw | ConvertFrom-Json
$currentRepo = ''
if ($cfg.changelog -is [array] -and $cfg.changelog.Count -gt 1 -and $cfg.changelog[1] -is [psobject]) {
$currentRepo = $cfg.changelog[1].repo
}
if ($currentRepo -eq $FullRepo -and $cfg.baseBranch -eq $BaseBranch) {
Write-OK ".changeset/config.json already correct — skipping."
} else {
Write-Info "Patching .changeset/config.json: repo → $FullRepo, baseBranch → $BaseBranch"
if ($DryRun) {
Write-Dry "Update $ChangesetConfig: changelog[1].repo=$FullRepo, baseBranch=$BaseBranch"
} else {
if ($cfg.changelog -is [array] -and $cfg.changelog.Count -gt 1) {
$cfg.changelog[1] | Add-Member -MemberType NoteProperty -Name 'repo' -Value $FullRepo -Force
}
$cfg | Add-Member -MemberType NoteProperty -Name 'baseBranch' -Value $BaseBranch -Force
$cfg | ConvertTo-Json -Depth 10 | Set-Content $ChangesetConfig -Encoding UTF8
Write-OK ".changeset/config.json updated."
}
}
} else {
Write-Warn ".changeset/config.json not found — run 'npx changeset init' first, then re-run this script."
}

# ─── Step 1: branch ruleset ───────────────────────────────────────────────────
Write-Step "Step 1/4 — Branch ruleset (protect main)"
Write-Step "Step 1/5 — Branch ruleset (protect main)"

$BranchRulesetName = 'Protect main branch'
if (Test-RulesetExists $BranchRulesetName) {
Expand Down Expand Up @@ -228,7 +259,7 @@ if (Test-RulesetExists $BranchRulesetName) {
}

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

$TagRulesetName = 'Protect release tags'
if (Test-RulesetExists $TagRulesetName) {
Expand Down Expand Up @@ -289,7 +320,7 @@ if (Test-RulesetExists $TagRulesetName) {
}

# ─── Step 3: skip-changeset label ─────────────────────────────────────────────
Write-Step "Step 3/4 — GitHub label: skip-changeset"
Write-Step "Step 3/5 — GitHub label: skip-changeset"

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

# ─── Step 4: secrets guidance ─────────────────────────────────────────────────
Write-Step "Step 4/4 — Repository secrets"
Write-Step "Step 4/5 — Repository secrets"

switch ($TokenType) {
'app' {
Expand Down
60 changes: 48 additions & 12 deletions scripts/setup-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ TOKEN_TYPE="app"
GHES_HOST=""
APP_ID=""
APP_PEM=""
BASE_BRANCH="main"
DRY_RUN=false

# ─── colours ─────────────────────────────────────────────────────────────────
Expand Down Expand Up @@ -115,14 +116,15 @@ _tag_ruleset_ui_instructions() {
# ─── argument parsing ─────────────────────────────────────────────────────────
while [[ $# -gt 0 ]]; do
case "$1" in
--owner) OWNER="$2"; shift 2 ;;
--repo) REPO="$2"; shift 2 ;;
--scope) SCOPE="$2"; shift 2 ;;
--token-type) TOKEN_TYPE="$2";shift 2 ;;
--ghes-host) GHES_HOST="$2"; shift 2 ;;
--app-id) APP_ID="$2"; shift 2 ;;
--app-pem) APP_PEM="$2"; shift 2 ;;
--dry-run) DRY_RUN=true; shift ;;
--owner) OWNER="$2"; shift 2 ;;
--repo) REPO="$2"; shift 2 ;;
--scope) SCOPE="$2"; shift 2 ;;
--token-type) TOKEN_TYPE="$2"; shift 2 ;;
--ghes-host) GHES_HOST="$2"; shift 2 ;;
--app-id) APP_ID="$2"; shift 2 ;;
--app-pem) APP_PEM="$2"; shift 2 ;;
--base-branch) BASE_BRANCH="$2"; shift 2 ;;
--dry-run) DRY_RUN=true; shift ;;
-h|--help)
print_help
exit 0
Expand Down Expand Up @@ -167,8 +169,42 @@ echo -e " Token type: ${TOKEN_TYPE}"
[[ "${DRY_RUN}" == true ]] && echo -e " ${YELLOW}DRY RUN — no changes will be made${RESET}"
echo ""

# ── Step 0: .changeset/config.json ───────────────────────────────────────────
header "Step 0/5 — .changeset/config.json"

CHANGESET_CONFIG=".changeset/config.json"

if [[ -f "${CHANGESET_CONFIG}" ]]; then
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)"

if [[ "${current_repo}" == "${FULL_REPO}" ]]; then
success ".changeset/config.json already points to ${FULL_REPO} — skipping."
Comment on lines +178 to +181
else
info "Patching .changeset/config.json: repo → ${FULL_REPO}, baseBranch → ${BASE_BRANCH}"
if [[ "${DRY_RUN}" == true ]]; then
dry "python3: update changelog[1].repo=${FULL_REPO}, baseBranch=${BASE_BRANCH} in ${CHANGESET_CONFIG}"
else
python3 - <<PYEOF
import json, sys
with open("${CHANGESET_CONFIG}") as f:
d = json.load(f)
if isinstance(d.get("changelog"), list) and len(d["changelog"]) > 1 and isinstance(d["changelog"][1], dict):
d["changelog"][1]["repo"] = "${FULL_REPO}"
d["baseBranch"] = "${BASE_BRANCH}"
with open("${CHANGESET_CONFIG}", "w") as f:
json.dump(d, f, indent=2)
f.write("\n")
PYEOF
success ".changeset/config.json updated."
fi
fi
else
warning ".changeset/config.json not found — run 'npx changeset init' first, then re-run this script."
fi

# ── Step 1: branch ruleset ────────────────────────────────────────────────────
header "Step 1/4 — Branch ruleset (protect main)"

header "Step 1/5 — Branch ruleset (protect main)"

BRANCH_RULESET_NAME="Protect main branch"

Expand Down Expand Up @@ -220,7 +256,7 @@ ENDJSON
fi

# ── Step 2: tag ruleset ───────────────────────────────────────────────────────
header "Step 2/4 — Tag ruleset (protect v* tags)"
header "Step 2/5 — Tag ruleset (protect v* tags)"

TAG_RULESET_NAME="Protect release tags"

Expand Down Expand Up @@ -273,7 +309,7 @@ ENDJSON
fi

# ── Step 3: skip-changeset label ──────────────────────────────────────────────
header "Step 3/4 — GitHub label: skip-changeset"
header "Step 3/5 — GitHub label: skip-changeset"

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

# ── Step 4: secrets guidance ──────────────────────────────────────────────────
header "Step 4/4 — Repository secrets"
header "Step 4/5 — Repository secrets"

_check_secret() {
local secret_name="$1"
Expand Down
Loading