Skip to content
This repository was archived by the owner on May 5, 2026. It is now read-only.

Commit 5efaad7

Browse files
authored
ci: fix release workflow + add kc-check-imports gate (#13)
Release workflow: contents:write permission, guarded tarball mv, tag resolved once via outputs, manual-dispatch artifact upload. kc-check-imports: NEW workflow on PRs to ga/** + lts/**, fetches MachineWisdomAI/kissclaw-tools, runs --candidates and --final-tree against v2026.4.20 baseline.
1 parent 59b80d6 commit 5efaad7

2 files changed

Lines changed: 181 additions & 15 deletions

File tree

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
name: kc-check-imports
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- "ga/**"
7+
- "lts/**"
8+
workflow_dispatch:
9+
inputs:
10+
baseline:
11+
description: "Baseline ref (tag or SHA) to validate against"
12+
required: false
13+
default: "v2026.4.20"
14+
type: string
15+
range:
16+
description: "Range or candidates (e.g. origin/ga/1.0..HEAD)"
17+
required: false
18+
default: ""
19+
type: string
20+
21+
permissions:
22+
contents: read
23+
pull-requests: write
24+
25+
jobs:
26+
check-imports:
27+
runs-on: ubuntu-latest
28+
steps:
29+
- name: Checkout repo (full history)
30+
uses: actions/checkout@v4
31+
with:
32+
fetch-depth: 0
33+
34+
- name: Fetch baseline tag
35+
run: |
36+
set -euo pipefail
37+
baseline="${{ inputs.baseline || 'v2026.4.20' }}"
38+
if ! git rev-parse "$baseline" >/dev/null 2>&1; then
39+
echo "Baseline ref '$baseline' not found locally; fetching tags from origin."
40+
git fetch origin --tags --force
41+
fi
42+
if ! git rev-parse "$baseline" >/dev/null 2>&1; then
43+
echo "ERROR: baseline ref '$baseline' not found after fetch. Push the tag to origin or pass --baseline=<full-sha>."
44+
exit 1
45+
fi
46+
47+
- name: Checkout kissclaw-tools
48+
uses: actions/checkout@v4
49+
with:
50+
repository: MachineWisdomAI/kissclaw-tools
51+
path: .kissclaw-tools
52+
token: ${{ secrets.KISSCLAW_TOOLS_TOKEN || secrets.GITHUB_TOKEN }}
53+
54+
- name: Setup Node.js
55+
uses: actions/setup-node@v4
56+
with:
57+
node-version: "22"
58+
59+
- name: Install pnpm
60+
uses: pnpm/action-setup@v4
61+
62+
- name: Install kissclaw-tools dependencies
63+
working-directory: .kissclaw-tools
64+
run: |
65+
if [ -f pnpm-lock.yaml ]; then
66+
pnpm install --frozen-lockfile
67+
elif [ -f package.json ]; then
68+
pnpm install
69+
else
70+
echo "kissclaw-tools has no package.json yet; installing typescript locally for module resolution."
71+
npm install --no-save typescript
72+
fi
73+
74+
- name: Install repo dependencies (for TS module resolution)
75+
run: pnpm install --frozen-lockfile
76+
77+
- name: Resolve range
78+
id: range
79+
run: |
80+
set -euo pipefail
81+
if [ -n "${{ inputs.range }}" ]; then
82+
range="${{ inputs.range }}"
83+
elif [ "${{ github.event_name }}" = "pull_request" ]; then
84+
base_ref="origin/${{ github.base_ref }}"
85+
git fetch origin "${{ github.base_ref }}" --depth=200
86+
range="${base_ref}..HEAD"
87+
else
88+
range="origin/ga/1.0..HEAD"
89+
fi
90+
echo "range=$range" >> "$GITHUB_OUTPUT"
91+
92+
- name: kc-check-imports — per-candidate
93+
id: candidates
94+
run: |
95+
set -euo pipefail
96+
baseline="${{ inputs.baseline || 'v2026.4.20' }}"
97+
range="${{ steps.range.outputs.range }}"
98+
echo "Running kc-check-imports --candidates $range against baseline $baseline"
99+
node .kissclaw-tools/kc-check-imports.mjs \
100+
--baseline "$baseline" \
101+
--candidates "$range" \
102+
--repo "$PWD" \
103+
> kc-check-imports-candidates.json
104+
cat kc-check-imports-candidates.json
105+
continue-on-error: false
106+
107+
- name: kc-check-imports — final-tree
108+
if: always()
109+
run: |
110+
set -euo pipefail
111+
baseline="${{ inputs.baseline || 'v2026.4.20' }}"
112+
range="${{ steps.range.outputs.range }}"
113+
echo "Running kc-check-imports --final-tree $range against baseline $baseline"
114+
node .kissclaw-tools/kc-check-imports.mjs \
115+
--baseline "$baseline" \
116+
--final-tree "$range" \
117+
--repo "$PWD" \
118+
> kc-check-imports-final-tree.json
119+
cat kc-check-imports-final-tree.json
120+
121+
- name: Upload reports
122+
if: always()
123+
uses: actions/upload-artifact@v4
124+
with:
125+
name: kc-check-imports-reports
126+
path: |
127+
kc-check-imports-candidates.json
128+
kc-check-imports-final-tree.json

.github/workflows/kissclawjj-release.yml

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,39 @@ on:
1010
required: true
1111
type: string
1212

13+
# `contents: write` is required for `gh release upload`. The default-branch
14+
# defense-in-depth check below prevents this write capability from being abused
15+
# to publish builds from `main` (the upstream mirror).
1316
permissions:
14-
contents: read
17+
contents: write
1518

1619
jobs:
1720
build:
1821
runs-on: ubuntu-latest
1922
steps:
23+
- name: Resolve build ref
24+
id: ref
25+
run: |
26+
set -euo pipefail
27+
if [ "${{ github.event_name }}" = "release" ]; then
28+
ref="${{ github.event.release.tag_name }}"
29+
elif [ -n "${{ inputs.ref }}" ]; then
30+
ref="${{ inputs.ref }}"
31+
else
32+
ref="${{ github.ref }}"
33+
fi
34+
echo "ref=$ref" >> "$GITHUB_OUTPUT"
35+
2036
- name: Checkout release ref
2137
uses: actions/checkout@v4
2238
with:
23-
ref: ${{ inputs.ref || github.ref }}
39+
ref: ${{ steps.ref.outputs.ref }}
40+
fetch-depth: 0
2441

2542
- name: Verify checkout integrity
2643
run: |
2744
set -euo pipefail
28-
intended_ref="${{ inputs.ref || github.ref }}"
29-
# Annotated tags need dereferencing to get the commit SHA.
45+
intended_ref="${{ steps.ref.outputs.ref }}"
3046
intended_sha=$(git rev-list -n 1 "$intended_ref")
3147
actual_sha=$(git rev-parse HEAD)
3248
if [ "$intended_sha" != "$actual_sha" ]; then
@@ -58,37 +74,59 @@ jobs:
5874
run: pnpm build
5975

6076
- name: Package tarball
77+
id: pack
6178
run: |
6279
set -euo pipefail
6380
version=$(node -p "require('./package.json').version")
6481
name=$(node -p "require('./package.json').name")
6582
pnpm pack
66-
mv *.tgz "kissclawjj-${version}.tgz"
67-
tarball="kissclawjj-${version}.tgz"
68-
sha256sum "$tarball" > "${tarball}.sha256"
69-
echo "TARBALL=$tarball" >> "$GITHUB_ENV"
70-
echo "VERSION=$version" >> "$GITHUB_ENV"
83+
src="${name}-${version}.tgz"
84+
dst="kissclawjj-${version}.tgz"
85+
if [ ! -f "$src" ]; then
86+
src=$(ls *.tgz | head -n 1)
87+
fi
88+
if [ "$src" != "$dst" ]; then
89+
mv "$src" "$dst"
90+
fi
91+
sha256sum "$dst" > "${dst}.sha256"
92+
{
93+
echo "tarball=$dst"
94+
echo "version=$version"
95+
} >> "$GITHUB_OUTPUT"
7196
7297
- name: Generate release metadata
7398
run: |
7499
set -euo pipefail
100+
built_at=$(date -u +%Y-%m-%dT%H:%M:%SZ)
101+
sha=$(git rev-parse HEAD)
75102
cat > "kissclawjj-release-metadata.json" <<METADATA
76103
{
77104
"name": "kissclawjj",
78-
"version": "$VERSION",
79-
"ref": "${{ inputs.ref || github.ref }}",
80-
"sha": "$(git rev-parse HEAD)",
81-
"built_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
105+
"version": "${{ steps.pack.outputs.version }}",
106+
"ref": "${{ steps.ref.outputs.ref }}",
107+
"sha": "$sha",
108+
"built_at": "$built_at"
82109
}
83110
METADATA
84111
85112
- name: Upload release assets
86113
if: github.event_name == 'release'
87114
run: |
115+
set -euo pipefail
88116
gh release upload "${{ github.event.release.tag_name }}" \
89-
"$TARBALL" \
90-
"${TARBALL}.sha256" \
117+
"${{ steps.pack.outputs.tarball }}" \
118+
"${{ steps.pack.outputs.tarball }}.sha256" \
91119
"kissclawjj-release-metadata.json" \
92120
--clobber
93121
env:
94122
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
123+
124+
- name: Upload workflow artifacts (manual dispatch)
125+
if: github.event_name == 'workflow_dispatch'
126+
uses: actions/upload-artifact@v4
127+
with:
128+
name: kissclawjj-release-${{ steps.pack.outputs.version }}
129+
path: |
130+
${{ steps.pack.outputs.tarball }}
131+
${{ steps.pack.outputs.tarball }}.sha256
132+
kissclawjj-release-metadata.json

0 commit comments

Comments
 (0)