Skip to content

Commit 54a8bb2

Browse files
feat: scaffold GitHub Action with action.yml, types, CI
0 parents  commit 54a8bb2

30 files changed

Lines changed: 5962 additions & 0 deletions

.claude/hooks/on-stop.sh

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/bin/bash
2+
cd "$CLAUDE_PROJECT_DIR" || exit 0
3+
4+
# TypeScript checks
5+
if [ -f "package.json" ]; then
6+
TEST_OUTPUT=$(npm test 2>&1)
7+
if [ $? -ne 0 ]; then
8+
echo "TypeScript tests failed:" >&2
9+
echo "$TEST_OUTPUT" >&2
10+
exit 2
11+
fi
12+
13+
LINT_OUTPUT=$(npm run lint 2>&1)
14+
if [ $? -ne 0 ]; then
15+
echo "TypeScript errors:" >&2
16+
echo "$LINT_OUTPUT" >&2
17+
exit 2
18+
fi
19+
20+
FORMAT_OUTPUT=$(npm run format 2>&1)
21+
if [ $? -ne 0 ]; then
22+
echo "Prettier formatting issues:" >&2
23+
echo "$FORMAT_OUTPUT" >&2
24+
exit 2
25+
fi
26+
fi
27+
28+
# Kotlin checks
29+
if [ -f "build.gradle.kts" ]; then
30+
GRADLE_OUTPUT=$(./gradlew test 2>&1)
31+
if [ $? -ne 0 ]; then
32+
echo "Kotlin tests failed:" >&2
33+
echo "$GRADLE_OUTPUT" >&2
34+
exit 2
35+
fi
36+
fi
37+
38+
# PR artifact check
39+
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
40+
if [[ "$BRANCH" == feat/* ]] || [[ "$BRANCH" == fix/* ]]; then
41+
ISSUE_LINKED=$(git log origin/main..HEAD --format="%s %b" 2>/dev/null | grep -cE "#[0-9]+")
42+
if [ "$ISSUE_LINKED" -eq 0 ]; then
43+
echo "No GitHub issue linked in commit history. Add before finishing." >&2
44+
exit 2
45+
fi
46+
fi
47+
48+
# SUCCESS: completely silent

.claude/hooks/post-tool-call.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/bin/bash
2+
cd "$CLAUDE_PROJECT_DIR" || exit 0
3+
4+
# Hybrid project: TypeScript (GitHub Action) + Kotlin (Gradle plugin)
5+
# Check which part changed and lint accordingly
6+
7+
if [ -f "package.json" ]; then
8+
OUTPUT=$(npm run lint 2>&1)
9+
if [ $? -ne 0 ]; then
10+
echo "TypeScript errors:" >&2
11+
echo "$OUTPUT" >&2
12+
exit 2
13+
fi
14+
fi
15+
16+
if [ -f "build.gradle.kts" ]; then
17+
OUTPUT=$(./gradlew ktlintCheck 2>&1)
18+
if [ $? -ne 0 ]; then
19+
echo "Kotlin lint errors:" >&2
20+
echo "$OUTPUT" >&2
21+
exit 2
22+
fi
23+
fi
24+
25+
# SUCCESS: completely silent

.claude/hooks/pre-bash.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/bin/bash
2+
COMMAND="$CLAUDE_TOOL_INPUT_COMMAND"
3+
4+
# Block force-push
5+
if echo "$COMMAND" | grep -qE "git push --force|git push -f"; then
6+
echo "ERROR: Force push is not allowed. Use --force-with-lease and confirm with user." >&2
7+
exit 1
8+
fi
9+
10+
# Block rm -rf on important directories
11+
if echo "$COMMAND" | grep -qE "rm -rf /|rm -rf ~|rm -rf \."; then
12+
echo "ERROR: Recursive delete on root/home/cwd is not allowed." >&2
13+
exit 1
14+
fi
15+
16+
# Block npm publish without confirmation
17+
if echo "$COMMAND" | grep -q "npm publish" && ! echo "$COMMAND" | grep -q "\-\-dry-run"; then
18+
echo "ERROR: npm publish requires explicit user confirmation." >&2
19+
exit 1
20+
fi
21+
22+
# Block Gradle publish without confirmation
23+
if echo "$COMMAND" | grep -qE "publishPlugins|publishToMavenLocal" && ! echo "$COMMAND" | grep -q "\-\-dry-run"; then
24+
echo "ERROR: Gradle publish requires explicit user confirmation." >&2
25+
exit 1
26+
fi

.claude/settings.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"hooks": {
3+
"postToolCall": [
4+
{ "command": ".claude/hooks/post-tool-call.sh" }
5+
],
6+
"preBash": [
7+
{ "command": ".claude/hooks/pre-bash.sh" }
8+
],
9+
"stop": [
10+
{ "command": ".claude/hooks/on-stop.sh" }
11+
]
12+
}
13+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Code Review Skill — TypeScript + Kotlin Hybrid
2+
3+
## TypeScript Checklist (GitHub Action)
4+
- [ ] Strict TypeScript — no `any`, proper narrowing from `unknown`
5+
- [ ] Named exports only — no `export default`
6+
- [ ] ESM imports with `.js` extensions
7+
- [ ] `const` everywhere
8+
- [ ] `action.yml` inputs match code expectations
9+
- [ ] GitHub API calls use `@octokit/rest` properly
10+
- [ ] Error handling for missing env vars (GITHUB_TOKEN, etc.)
11+
12+
## Kotlin Checklist (Gradle Plugin)
13+
- [ ] No `var` — always `val`
14+
- [ ] No `!!` without justifying comment
15+
- [ ] Kotlin DSL for task configuration
16+
- [ ] KDoc on public classes and functions
17+
- [ ] JUnit 5 tests with Kotest matchers
18+
19+
## Both
20+
- [ ] No secrets in code
21+
- [ ] No debug output left in
22+
- [ ] Functions under 30 lines
23+
- [ ] Edge cases tested (empty spec, missing sections)
24+
25+
## Output Format
26+
Return: summary, blocking issues (must fix), suggestions (nice to have).
27+
Cite each issue as `filepath:line — description`.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# PR Artifacts Skill — TypeScript + Kotlin Hybrid
2+
3+
Produce ALL of the following before opening a PR for review.
4+
5+
## 1. GitHub Issue
6+
- Verify the PR is linked to a GH issue
7+
- Set the issue reference in the PR body: "Closes #N"
8+
9+
## 2. ADR (Architecture Decision Record)
10+
Required when the PR introduces or changes:
11+
- GitHub Action inputs/outputs contract
12+
- Gradle plugin DSL or task configuration
13+
- Integration approach with spec-linter/injection-scanner/ai-changelog
14+
- PR comment format or template
15+
16+
Not required for: bug fixes, test additions, documentation.
17+
18+
File as `docs/adr/NNNN-short-title.md`.
19+
20+
## 3. Documentation Update
21+
- `README.md` — if new inputs, outputs, or behavior
22+
- `action.yml` — keep inputs documented
23+
- Inline JSDoc (TypeScript) or KDoc (Kotlin) on public APIs
24+
25+
## 4. Tests
26+
TypeScript (GitHub Action):
27+
- [ ] `npm test` passes
28+
- [ ] `npm run lint` passes (tsc --noEmit)
29+
- [ ] `npm run format` passes (prettier)
30+
31+
Kotlin (Gradle Plugin):
32+
- [ ] `./gradlew test` passes
33+
- [ ] `./gradlew ktlintCheck` passes
34+
35+
## 5. Verification Report
36+
- [ ] No `any` types (TypeScript), no `!!` (Kotlin)
37+
- [ ] No secrets or tokens in code
38+
- [ ] ADR written (or: not required because ...)
39+
- [ ] Issue: Closes #N
40+
- [ ] Smoke test described
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# NNNN. [Short Title]
2+
3+
Date: YYYY-MM-DD
4+
Status: Proposed | Accepted | Deprecated | Superseded by NNNN
5+
6+
## Context
7+
[What situation? What problem? What constraints?]
8+
9+
## Decision
10+
[What did we decide?]
11+
12+
## Consequences
13+
14+
### Positive
15+
- [benefit]
16+
17+
### Negative / Trade-offs
18+
- [cost or risk]
19+
20+
## Alternatives Considered
21+
[What else was evaluated and why rejected?]

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
## What
2+
3+
<!-- Brief description of the change -->
4+
5+
## Why
6+
7+
<!-- Motivation / issue link -->
8+
9+
## How
10+
11+
<!-- Implementation approach -->
12+
13+
## Checklist
14+
15+
- [ ] Tests pass (`npm test`)
16+
- [ ] Types check (`npm run lint`)
17+
- [ ] Format check (`npm run format`)
18+
- [ ] Build succeeds (`npm run build`)
19+
- [ ] No `any` types introduced
20+
- [ ] No secrets committed

.github/workflows/ci.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
build-and-test:
11+
runs-on: [arc-runner-unityinflow]
12+
steps:
13+
- uses: actions/checkout@v4
14+
15+
- uses: actions/setup-node@v4
16+
with:
17+
node-version: "20"
18+
cache: "npm"
19+
20+
- run: npm ci
21+
22+
- run: npm run lint
23+
name: Type check
24+
25+
- run: npm run format
26+
name: Format check
27+
28+
- run: npm test
29+
name: Run tests
30+
31+
- run: npm run build
32+
name: Build action

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
node_modules/
2+
dist/
3+
*.tsbuildinfo
4+
.DS_Store
5+
coverage/
6+
.env
7+
.env.*

0 commit comments

Comments
 (0)