Skip to content

Commit 9883421

Browse files
chore: improve Claude setup — token reduction, /commit command, CI/CD integration
Token reduction: - Condense CLAUDE.md project structure tree (27 → 14 lines) - Remove stale test count from CLAUDE.md - Remove duplicated failures table from test.md (reference CLAUDE.md instead) - Collapse duplicate naming/normalisation sections in code-review.md Productivity: - Add /commit command with Jira ticket ID extraction from branch name - Add git/find/grep/npx cspell to settings.json allow list CI/CD: - Add claude-pr-review.yml: automated SDK patterns + security review on PRs - Add claude-changelog.yml: auto-generated release notes on tag push Requires ANTHROPIC_API_KEY secret in GitHub Actions. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
1 parent 4fb5855 commit 9883421

7 files changed

Lines changed: 352 additions & 102 deletions

File tree

.claude/commands/code-review.md

Lines changed: 36 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
---
22
name: code-review
3-
description: Full code review — SDK patterns, naming, test coverage, code smells, and security. Reads code-smell.md and code-security.md inline.
3+
description: Full code review — SDK patterns, naming, test coverage, then runs /code-smell and /code-security.
44
paths:
55
- src/main/java/**/*.java
66
- src/test/java/**/*.java
77
---
88

99
You are a senior engineer performing a thorough code review on the Skyflow Java SDK.
1010

11-
## Review Mode
11+
## Scope
1212

1313
Use `$ARGUMENTS` to determine scope:
1414
- `full review` — scan all files under `src/main/java/com/skyflow/` recursively (exclude `generated/`)
@@ -22,100 +22,51 @@ Use `$ARGUMENTS` to determine scope:
2222

2323
---
2424

25-
## 1. Request / Response / Options patterns
25+
## Step 1 — SDK Pattern Review
26+
27+
Check the files in scope against the rules below.
28+
29+
### 1. Request / Response / Options patterns
2630

2731
- Request builders are plain data holders — validation happens in `Validations.validateXxxRequest()` inside the controller, not in `build()`. Flag if validation logic is duplicated outside `Validations`.
2832
- Response getters returning `ArrayList<HashMap<String, Object>>` is the established SDK pattern — do not flag these as violations.
2933
- All response classes must have `getErrors()` returning `null` (not absent) when no errors.
3034
- No separate `*Options` classes exist — options are fields on the request builder itself.
3135
- SDK must not add field-level null/empty validation on top of what the backend enforces. Only structural checks (`table == null`, `values == null`) are permitted.
3236

33-
---
34-
35-
## 2. Error handling
37+
### 2. Error handling
3638

3739
- All public methods must declare `throws SkyflowException`
3840
- `SkyflowException` must be thrown (not swallowed) on invalid input
3941
- No `System.out.println` or bare `e.printStackTrace()` — use `LogUtil`
4042
- Catch blocks must not silently drop exceptions
4143
- `catch (Exception e)` without re-throw or explicit handling is a critical issue
4244

43-
---
44-
45-
## 3. Naming conventions
46-
47-
- Classes: `PascalCase`
48-
- Methods / fields: `camelCase` — acronyms as words: `skyflowId` not `skyflowID`, `tokenUri` not `tokenURI`, `downloadUrl` not `downloadURL`
49-
- Constants: `UPPER_SNAKE_CASE`
50-
- Builder setter methods: `setFooId()` not `setFooID()`
51-
- Deprecated methods must use `@Deprecated(since = "x.x", forRemoval = true)` + `@deprecated` Javadoc with `{@link}` to the replacement
45+
### 3. Naming conventions and response field normalisation
5246

53-
---
47+
Follow the conventions in CLAUDE.md under "Naming Conventions". Key enforcement points:
48+
- Acronyms as words: `skyflowId`, `tokenUri`, `clientId` — never uppercase abbreviations
49+
- Builder setters: `setFooId()` not `setFooID()`; constants: `UPPER_SNAKE_CASE`; classes: `PascalCase`
50+
- Response maps: `skyflowId` (camelCase) only — never `skyflow_id`; `getErrors()` must be present on every response class
51+
- Deprecated methods: `@Deprecated(since = "x.x", forRemoval = true)` + `@deprecated` Javadoc with `{@link}` to replacement
5452

55-
## 4. Response field normalisation
56-
57-
- All response maps must use `skyflowId` (camelCase), never `skyflow_id` (snake_case)
58-
- `getErrors()` must be present on every response class
59-
60-
---
61-
62-
## 5. Test coverage
53+
### 5. Test coverage
6354

6455
- Every public method must have at least one positive and one negative test
6556
- Tests must use `Assert.assertEquals` / `Assert.assertNull` — not just `Assert.fail` guards
6657
- No mocking of the production class under test
6758
- Reflection-based tests on private methods are acceptable only when no public API exercises the method
6859

69-
---
70-
71-
## 6. Code quality
60+
### 6. Code quality
7261

7362
- No magic strings for API field names — use `Constants` or `ErrorMessage` enums
7463
- No duplicate validation logic across request classes — belongs in `Validations`
7564
- No `@SuppressWarnings` without a comment explaining why
7665
- `LogUtil.printWarningLog` must be used for deprecation warnings, not `System.err`
7766

78-
---
79-
80-
## 7. Code smells
81-
82-
Code smells are structural signals — they may not need immediate fixes but must be flagged. Report them at **Smell** severity.
83-
84-
### Method & class size
85-
- **Long method** — any method over 40 lines. Candidate for decomposition into private helpers.
86-
- **Long class** — any class over 300 lines. May be taking on too many responsibilities.
87-
- **Large parameter list** — more than 4 parameters on a method. Consider a config/options object.
88-
89-
### Responsibility violations
90-
- **Business logic in Request/Response classes** — these are data holders. If a Request/Response class contains conditional logic beyond null-safe getters, flag it.
91-
- **toString() with business logic**`toString()` should only serialise state. Logic like field renaming, manual JSON construction, or conditional field injection belongs in the controller or formatter methods.
92-
- **Validation outside Validations.java** — any `if (x == null) throw new SkyflowException(...)` outside `src/main/java/com/skyflow/utils/validations/` is misplaced.
67+
### Output for Step 1
9368

94-
### Control flow
95-
- **Deep nesting** — more than 3 levels of `if`/`for`/`try` nesting. Extract inner blocks to named methods.
96-
- **Long if-else chains** — more than 4 branches. Consider a map, switch, or polymorphism.
97-
- **Null checks scattered** — multiple consecutive null guards that could be replaced with `Optional` or early return.
98-
99-
### Data
100-
- **Magic numbers** — literal integers or sizes (e.g. `25`, `3600`, `100`) without a named constant. Use `Constants`.
101-
- **Raw HashMap chains**`HashMap<String, Object>` passed through more than 2 method boundaries without a typed wrapper or comment explaining why. Flag for awareness; don't require a fix.
102-
- **Temporary field** — a class field that is only set in certain code paths and `null` the rest of the time. Should be a local variable or method parameter instead.
103-
104-
### Dead code
105-
- **Unused private methods** — private methods with no callers.
106-
- **Unused imports** — any `import` not referenced in the file.
107-
- **Unreachable code** — code after `return`/`throw` in the same branch.
108-
- **Commented-out code** — blocks of commented code without explanation. Remove or add a TODO with a ticket reference.
109-
110-
### Comments
111-
- **Explains what, not why** — a comment that restates what the code does (`// get the vault ID`) is noise. Only flag comments that explain the *what* without adding *why*.
112-
- **Stale comment** — a comment that contradicts the current code (e.g. references a removed parameter or old method name).
113-
114-
---
115-
116-
## Output Format
117-
118-
Group findings by file. For each file:
69+
Group findings by file:
11970

12071
```
12172
### path/to/File.java
@@ -125,8 +76,6 @@ Group findings by file. For each file:
12576
| Critical | 42 | SkyflowException swallowed in catch block |
12677
| Bug | 87 | skyflow_id not normalised to skyflowId |
12778
| Quality | 103 | Magic string "records" — use Constants |
128-
| Smell | 210 | toString() renames map keys — move to formatter method |
129-
| Smell | 315 | Method is 58 lines — candidate for decomposition |
13079
```
13180

13281
**Severities:**
@@ -136,8 +85,23 @@ Group findings by file. For each file:
13685
| **Bug** | Wrong behaviour, incorrect output — must fix before merge |
13786
| **Edge Case** | Unhandled input that will cause runtime failure — fix before merge |
13887
| **Quality** | Maintainability issue, naming violation, missing pattern — fix before merge |
139-
| **Smell** | Structural signal, technical debt — flag and track, fix when in the area |
14088

141-
End with:
142-
1. A tech-debt summary table grouped by category (Error handling / Naming / Smells / Tests)
89+
---
90+
91+
## Step 2 — Code Smell Analysis
92+
93+
Read the file `.claude/commands/code-smell.md` and follow all of its instructions for the same files in scope. Produce its full output (per-file smell table + smell summary + recommendation).
94+
95+
---
96+
97+
## Step 3 — Security Audit
98+
99+
Read the file `.claude/commands/code-security.md` and follow all of its instructions for the same files in scope. Produce its full output (per-finding blocks + summary table + overall risk rating).
100+
101+
---
102+
103+
## Final Verdict
104+
105+
After all three steps, close with:
106+
1. A tech-debt summary table grouped by category (SDK Patterns / Error Handling / Naming / Tests / Smells / Security)
143107
2. A verdict: `APPROVE` / `APPROVE WITH FIXES` / `REQUEST CHANGES`

.claude/commands/commit.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
name: commit
3+
description: Stage check + Jira-aware commit — extracts ticket ID from branch name and validates against pr.yml commit-message check.
4+
---
5+
6+
Create a git commit for staged changes on the current branch.
7+
8+
Use `$ARGUMENTS` as the commit message description. If empty, ask the user for a description before proceeding.
9+
10+
## Step 1 — Extract ticket ID from branch name
11+
12+
```bash
13+
git rev-parse --abbrev-ref HEAD
14+
```
15+
16+
Extract the Jira ticket ID using the pattern `[A-Z]{1,10}-[0-9]+`:
17+
- `devesh/SK-1234-fix-foo``SK-1234`
18+
- `karthik/GV-770-ext-auth-json-error``GV-770`
19+
- `username/SDK-2814-some-fix``SDK-2814`
20+
21+
If no ticket ID is found, **stop** and ask the user to provide one before continuing.
22+
23+
## Step 2 — Check what is staged
24+
25+
```bash
26+
git status --short
27+
git diff --cached --stat
28+
```
29+
30+
If nothing is staged, list the unstaged files and ask the user which files to stage. Do not run `git add .` — ask for explicit paths (`.env`, `credentials.json`, and `generated/` must never be staged).
31+
32+
## Step 3 — Assemble and validate the commit message
33+
34+
Build the message as:
35+
```
36+
<ticket-id> <description>
37+
```
38+
39+
If the user provided a Conventional Commits prefix (`feat`, `fix`, `chore`, `docs`, `refactor`, `test`), prepend it:
40+
```
41+
feat: SK-1234 add bulk insert support
42+
fix: GV-770 handle null bearer token on refresh
43+
```
44+
45+
Validate against the `pr.yml` enforced pattern: `(\[?[A-Z]{1,10}-[1-9][0-9]*)|(\[AUTOMATED\])|(Merge)|(Release)`
46+
- Must contain a Jira ID — a bare description without a ticket ID will fail CI.
47+
- If validation fails, report the exact requirement and stop.
48+
49+
## Step 4 — Commit
50+
51+
```bash
52+
git commit -m "<assembled message>"
53+
```
54+
55+
Report the resulting commit SHA and the commit message first line.

.claude/commands/test.md

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,8 @@ Run the Skyflow Java SDK quality pipeline.
1010

1111
Use `$ARGUMENTS` to target a specific test class (e.g. `BearerTokenTests`). If empty, run the full suite.
1212

13-
## Known Pre-existing Failures (not regressions)
14-
15-
Before reporting failures, check against this baseline:
16-
- `HttpUtilityTests` — ALL tests fail (JDK 21 + PowerMock `InaccessibleObject` incompatibility)
17-
- `TokenTests#testExpiredTokenForIsExpiredToken` — needs live credentials
18-
- `VaultClientTests#testSetBearerTokenWithEnvCredentials` — needs `SKYFLOW_CREDENTIALS` env var
19-
- `ConnectionClientTests#testSetBearerTokenWithEnvCredentials` — needs `SKYFLOW_CREDENTIALS` env var
20-
21-
Baseline: 374 tests, ~5 failures, ~4 errors. Only report failures **beyond** this baseline.
13+
> Baseline failures are listed in CLAUDE.md under "Known Pre-existing Test Failures".
14+
> Do not investigate them unless specifically asked. Only report failures **beyond** that baseline.
2215
2316
## Pipeline
2417

.claude/settings.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@
1616
"allow": [
1717
"Bash(mvn *)",
1818
"Bash(java *)",
19-
"Bash(python3 *)"
19+
"Bash(python3 *)",
20+
"Bash(git *)",
21+
"Bash(find *)",
22+
"Bash(grep *)",
23+
"Bash(npx cspell *)"
2024
],
2125
"deny": [
2226
"Edit(src/main/java/com/skyflow/generated/**)",
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
name: Claude Changelog
2+
3+
on:
4+
push:
5+
tags:
6+
- '[0-9]+.[0-9]+.[0-9]+'
7+
- '*.*.*-beta.*'
8+
9+
permissions:
10+
contents: write
11+
12+
jobs:
13+
generate-changelog:
14+
name: Generate Release Notes
15+
runs-on: ubuntu-latest
16+
timeout-minutes: 10
17+
steps:
18+
- uses: actions/checkout@v4
19+
with:
20+
fetch-depth: 0
21+
22+
- name: Get previous tag
23+
id: previoustag
24+
uses: WyriHaximus/github-action-get-previous-tag@v1
25+
with:
26+
fallback: '0.0.0'
27+
28+
- name: Get commits since previous tag
29+
id: commits
30+
run: |
31+
PREV="${{ steps.previoustag.outputs.tag }}"
32+
CURR="${{ github.ref_name }}"
33+
COMMITS=$(git log "${PREV}..${CURR}" --oneline \
34+
| grep -v '^\S* \[AUTOMATED\]' \
35+
| grep -v '^\S* Merge ' \
36+
| grep -v '^\S* \[AUTOMATED\]')
37+
echo "log<<EOF" >> $GITHUB_OUTPUT
38+
echo "$COMMITS" >> $GITHUB_OUTPUT
39+
echo "EOF" >> $GITHUB_OUTPUT
40+
41+
- name: Install Claude CLI
42+
run: npm install -g @anthropic-ai/claude-code
43+
44+
- name: Generate release notes
45+
id: notes
46+
continue-on-error: true
47+
env:
48+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
49+
run: |
50+
PREV="${{ steps.previoustag.outputs.tag }}"
51+
CURR="${{ github.ref_name }}"
52+
COMMITS="${{ steps.commits.outputs.log }}"
53+
NOTES=$(claude --print --model claude-sonnet-4-5 -p "
54+
Generate GitHub Release notes for the Skyflow Java SDK.
55+
56+
Release: $CURR (previous: $PREV)
57+
58+
Commits:
59+
$COMMITS
60+
61+
Rules:
62+
- Group into sections: ## Features, ## Bug Fixes, ## Security, ## Breaking Changes
63+
- Omit any section with no entries
64+
- Each entry: bullet point with a concise one-line description; include the Jira ticket ID if present (e.g. SK-1234)
65+
- Strip PR merge numbers like (#323) — keep the substance
66+
- Skip [AUTOMATED] commits, version bump commits, and bare merge commits
67+
- Breaking Changes section must come first if present
68+
- End with: _Full changelog: https://github.com/skyflowapi/skyflow-java/compare/${PREV}...${CURR}_
69+
70+
Output only the markdown. No preamble or explanation.
71+
")
72+
echo "notes<<EOF" >> $GITHUB_OUTPUT
73+
echo "$NOTES" >> $GITHUB_OUTPUT
74+
echo "EOF" >> $GITHUB_OUTPUT
75+
76+
- name: Create or update GitHub Release
77+
env:
78+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
79+
run: |
80+
TAG="${{ github.ref_name }}"
81+
NOTES="${{ steps.notes.outputs.notes }}"
82+
if gh release view "$TAG" > /dev/null 2>&1; then
83+
gh release edit "$TAG" --notes "$NOTES"
84+
else
85+
gh release create "$TAG" --notes "$NOTES" --title "Release $TAG"
86+
fi

0 commit comments

Comments
 (0)