claude-ci-serverside-plan.cspec
1 # Claude CI Serverside Implementation Plan 2 # purpose: Step-by-step implementation guide for Claude worker 3 # status: verified 4 # updated: 2026-01-06 5 # verified: 2026-01-06 6 # spec_ref: project/descriptive-docs/machine/Claude-CI-Serverside.cspec 7 8 # === VERIFIED SERVER STATE === 9 server_state: 10 host: ci.ac-dc.network 11 ssh_port: 2584 12 user: devops 13 14 installed: 15 python: {path: /usr/bin/python3, version: "3.12.3"} 16 claude_cli: {path: /usr/bin/claude, version: "2.0.76"} 17 node: {path: /usr/bin/node, version: "24.12.0"} 18 npm: {path: /usr/bin/npm, version: "11.6.2"} 19 20 python_packages: 21 - {name: requests, version: "2.31.0", status: installed} 22 - {name: anthropic, version: "0.75.0", status: installed} 23 24 directories: 25 writable: /opt/ci/ # owned by devops 26 not_writable: /var/lib/ # needs sudo 27 28 credentials: 29 claude: NOT_CONFIGURED # need to run: claude /login 30 forgejo_token: AVAILABLE # token works, needs to be stored 31 32 api_verified: 33 endpoint: https://source.ac-dc.network/api/v1 34 repos_in_org: 12 35 test_result: success 36 37 # === IMPLEMENTATION PHASES === 38 39 phases: 40 total: 4 41 order: [setup, service, deploy, protect] 42 43 # ============================================================ 44 # PHASE 1: SETUP 45 # ============================================================ 46 phase_1_setup: 47 name: Environment Setup 48 49 tasks: 50 1_1_create_labels: 51 action: Create labels in Forgejo via API 52 endpoint: POST /api/v1/orgs/alpha-delta-network/labels 53 labels: 54 - name: claude-approved 55 color: "00ff00" 56 description: "Claude review passed" 57 - name: claude-changes-requested 58 color: "ff0000" 59 description: "Claude requested changes" 60 verify: GET /api/v1/orgs/alpha-delta-network/labels 61 62 1_2_setup_credentials: 63 action: Setup Claude CLI credentials on CI server 64 host: ci.ac-dc.network 65 user: devops 66 commands: 67 - ssh -p 2584 devops@ci.ac-dc.network 68 - claude /login 69 - verify: ls -la ~/.claude/.credentials.json 70 output: /home/devops/.claude/.credentials.json exists 71 72 1_3_verify_forgejo_token: 73 action: Verify FORGEJO_TOKEN works 74 test: | 75 curl -s -H "Authorization: token $FORGEJO_TOKEN" \ 76 https://source.ac-dc.network/api/v1/user 77 expect: returns authenticated user info 78 79 # ============================================================ 80 # PHASE 2: SERVICE IMPLEMENTATION 81 # ============================================================ 82 phase_2_service: 83 name: Review Service Script 84 output: tools/claude-review-service.py 85 86 tasks: 87 2_1_create_script: 88 action: Create main service script 89 path: tools/claude-review-service.py 90 91 imports: 92 - requests 93 - subprocess 94 - json 95 - os 96 - logging 97 98 classes: 99 ForgejoClient: 100 methods: 101 - __init__(base_url, token) 102 - list_org_repos(org) -> list[dict] 103 - list_open_prs(owner, repo) -> list[dict] 104 - get_pr_diff(owner, repo, pr_num) -> str 105 - get_pr_details(owner, repo, pr_num) -> dict 106 - get_commit_status(owner, repo, sha) -> dict 107 - post_comment(owner, repo, issue_num, body) 108 - add_label(owner, repo, issue_num, label) 109 - remove_label(owner, repo, issue_num, label) 110 - set_commit_status(owner, repo, sha, state, context, description) 111 112 ClaudeReviewer: 113 methods: 114 - __init__(credentials_path) 115 - review_diff(diff, pr_info) -> ReviewResult 116 117 review_prompt: | 118 Review this PR diff for: 119 1. Code quality issues 120 2. Security vulnerabilities 121 3. Architecture concerns 122 4. Missing documentation 123 5. Test coverage gaps 124 125 Classify each issue as: critical, high, medium, low 126 127 Return JSON: {approved, summary, issues[], suggestions[]} 128 129 ReviewService: 130 methods: 131 - __init__(forgejo_client, claude_reviewer) 132 - get_reviewed_shas() -> set # from state file 133 - save_reviewed_sha(sha) 134 - needs_review(pr) -> bool 135 - should_block(issues) -> bool 136 - format_comment(result) -> str 137 - process_pr(owner, repo, pr) 138 - run() 139 140 main_logic: | 141 1. Load config from env vars 142 2. Init ForgejoClient and ClaudeReviewer 143 3. For each repo in org: 144 a. List open PRs 145 b. For each PR: 146 - Check if CI passed 147 - Check if already reviewed (by SHA) 148 - If needs review: fetch diff, run Claude, post result 149 4. Log summary 150 151 2_2_blocking_logic: 152 action: Implement blocking decision 153 code: | 154 def should_block(self, issues: list) -> bool: 155 blocking = {'critical', 'high', 'medium'} 156 return any(i['severity'] in blocking for i in issues) 157 158 2_3_comment_format: 159 action: Define comment template 160 template: | 161 ## Claude Code Review 162 163 {%if approved%} 164 ### Approved 165 {summary} 166 {%else%} 167 ### Changes Requested 168 {summary} 169 170 #### Issues Found 171 {%for issue in issues%} 172 - **[{issue.severity}]** `{issue.file}:{issue.line}` - {issue.message} 173 {%endfor%} 174 {%endif%} 175 176 {%if suggestions%} 177 #### Suggestions 178 {%for s in suggestions%} 179 - {s} 180 {%endfor%} 181 {%endif%} 182 183 --- 184 *Automated review by Claude* 185 186 2_4_state_tracking: 187 action: Track reviewed PRs by SHA 188 path: /opt/ci/claude-review/state/reviewed_shas.json 189 format: | 190 { 191 "owner/repo#pr": { 192 "sha": "abc123", 193 "reviewed_at": "2026-01-06T12:00:00Z", 194 "result": "approved|changes_requested" 195 } 196 } 197 198 # ============================================================ 199 # PHASE 3: DEPLOYMENT 200 # ============================================================ 201 phase_3_deploy: 202 name: Deploy to CI Server 203 host: ci.ac-dc.network 204 205 tasks: 206 3_1_create_directories: 207 action: Create service directories 208 commands: 209 - ssh -p 2584 devops@ci.ac-dc.network "mkdir -p /opt/ci/claude-review" 210 - ssh -p 2584 devops@ci.ac-dc.network "mkdir -p /opt/ci/claude-review/state" 211 note: Using /opt/ci/ which is writable by devops (verified) 212 213 3_2_copy_script: 214 action: Deploy script to server 215 commands: 216 - scp -P 2584 tools/claude-review-service.py devops@ci.ac-dc.network:/opt/ci/claude-review/ 217 - ssh -p 2584 devops@ci.ac-dc.network "chmod +x /opt/ci/claude-review/claude-review-service.py" 218 219 3_3_create_systemd_service: 220 action: Create systemd service unit 221 path: /etc/systemd/system/claude-review.service 222 note: Requires sudo to write to /etc/systemd/system/ 223 content: | 224 [Unit] 225 Description=Claude PR Review Service 226 After=network.target 227 228 [Service] 229 Type=oneshot 230 User=devops 231 WorkingDirectory=/opt/ci/claude-review 232 ExecStart=/usr/bin/python3 /opt/ci/claude-review/claude-review-service.py 233 Environment=FORGEJO_URL=https://source.ac-dc.network 234 Environment=FORGEJO_TOKEN=2f14498863920f9853e56e554a817654a5ddc917 235 Environment=ORG_NAME=alpha-delta-network 236 Environment=STATE_FILE=/opt/ci/claude-review/state/reviewed_shas.json 237 238 [Install] 239 WantedBy=multi-user.target 240 241 3_4_create_systemd_timer: 242 action: Create systemd timer unit 243 path: /etc/systemd/system/claude-review.timer 244 content: | 245 [Unit] 246 Description=Run Claude PR Review every 5 minutes 247 248 [Timer] 249 OnBootSec=2min 250 OnUnitActiveSec=5min 251 252 [Install] 253 WantedBy=timers.target 254 255 3_5_enable_timer: 256 action: Enable and start timer 257 commands: 258 - ssh -p 2584 devops@ci.ac-dc.network "sudo systemctl daemon-reload" 259 - ssh -p 2584 devops@ci.ac-dc.network "sudo systemctl enable claude-review.timer" 260 - ssh -p 2584 devops@ci.ac-dc.network "sudo systemctl start claude-review.timer" 261 verify: systemctl status claude-review.timer 262 263 # ============================================================ 264 # PHASE 4: BRANCH PROTECTION 265 # ============================================================ 266 phase_4_protect: 267 name: Configure Branch Protection 268 note: Manual in Forgejo UI for each repo 269 270 tasks: 271 4_1_protection_rules: 272 action: Set branch protection on main 273 location: Forgejo UI > Repo Settings > Branches > main 274 settings: 275 - enable_push_protection: true 276 - require_status_checks: true 277 - required_checks: [claude-review] 278 - require_approvals: 1 279 - dismiss_stale_reviews: true 280 281 4_2_alternative_label_gate: 282 action: Alternative - require label for merge 283 note: If status checks not flexible enough 284 rule: Require "claude-approved" label before merge allowed 285 286 # ============================================================ 287 # VERIFICATION 288 # ============================================================ 289 verification: 290 test_cases: 291 - name: Service runs without error 292 command: sudo systemctl start claude-review.service 293 expect: exit 0, no errors in journal 294 295 - name: Timer is active 296 command: systemctl is-active claude-review.timer 297 expect: active 298 299 - name: Test PR gets reviewed 300 steps: 301 - Create test PR with minor issue 302 - Wait 5 minutes or trigger manually 303 - Verify comment posted 304 - Verify label applied 305 306 - name: Approved PR can merge 307 steps: 308 - Create clean test PR 309 - Wait for Claude approval 310 - Verify admin can merge 311 312 # ============================================================ 313 # ROLLBACK 314 # ============================================================ 315 rollback: 316 steps: 317 - ssh -p 2584 devops@ci.ac-dc.network "sudo systemctl stop claude-review.timer" 318 - ssh -p 2584 devops@ci.ac-dc.network "sudo systemctl disable claude-review.timer" 319 - Remove branch protection rules in Forgejo UI 320 note: Labels and comments remain but have no effect 321 322 # ============================================================ 323 # FILES CREATED 324 # ============================================================ 325 files_created: 326 local: 327 - tools/claude-review-service.py 328 329 server: 330 - /opt/ci/claude-review/claude-review-service.py 331 - /opt/ci/claude-review/state/reviewed_shas.json 332 - /etc/systemd/system/claude-review.service # requires sudo 333 - /etc/systemd/system/claude-review.timer # requires sudo 334 335 # ============================================================ 336 # PREREQUISITES SUMMARY 337 # ============================================================ 338 prerequisites: 339 already_done: 340 - Python 3.12.3 installed 341 - requests package installed 342 - anthropic package installed 343 - Claude CLI installed at /usr/bin/claude 344 - /opt/ci/ directory exists and writable 345 - Forgejo API accessible with token 346 347 still_needed: 348 - Claude credentials: run "claude /login" as devops 349 - Create org labels: claude-approved, claude-changes-requested 350 - Branch protection rules in Forgejo UI