spets 0.1.13 → 0.1.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -269,254 +269,10 @@ function createGitHubWorkflow(cwd) {
269
269
  const templateDir = join(cwd, ".github", "ISSUE_TEMPLATE");
270
270
  mkdirSync(workflowDir, { recursive: true });
271
271
  mkdirSync(templateDir, { recursive: true });
272
- writeFileSync(join(workflowDir, "spets.yml"), getGitHubWorkflow());
273
- writeFileSync(join(templateDir, "spets-task.yml"), getIssueTemplate());
274
- }
275
- function getIssueTemplate() {
276
- return `name: Spets Task
277
- description: Start a Spets workflow
278
- labels: ["spets"]
279
- body:
280
- - type: input
281
- id: task
282
- attributes:
283
- label: Task Description
284
- description: What do you want to accomplish?
285
- placeholder: "Add user authentication"
286
- validations:
287
- required: true
288
- - type: input
289
- id: branch
290
- attributes:
291
- label: Branch Name
292
- description: Leave empty to auto-generate (spets/<issue-number>)
293
- placeholder: "feature/my-feature"
294
- validations:
295
- required: false
296
- `;
297
- }
298
- function getGitHubWorkflow() {
299
- const gh = (expr) => `\${{ ${expr} }}`;
300
- return `# Spets GitHub Action
301
- # Handles workflow start from Issue creation and commands from comments
302
-
303
- name: Spets Workflow
304
-
305
- on:
306
- issues:
307
- types: [opened]
308
- issue_comment:
309
- types: [created]
310
-
311
- permissions:
312
- contents: write
313
- issues: write
314
- pull-requests: write
315
-
316
- jobs:
317
- # Start workflow when a spets Issue is created
318
- start-workflow:
319
- if: github.event.action == 'opened' && contains(github.event.issue.labels.*.name, 'spets')
320
- runs-on: ubuntu-latest
321
-
322
- steps:
323
- - name: Checkout
324
- uses: actions/checkout@v4
325
- with:
326
- fetch-depth: 1
327
- persist-credentials: false
328
-
329
- - name: Setup Git
330
- run: |
331
- git config user.name "github-actions[bot]"
332
- git config user.email "github-actions[bot]@users.noreply.github.com"
333
-
334
- - name: Parse Issue body
335
- id: parse
336
- env:
337
- ISSUE_BODY: ${gh("github.event.issue.body")}
338
- ISSUE_NUMBER: ${gh("github.event.issue.number")}
339
- run: |
340
- # Parse task description
341
- TASK=$(echo "$ISSUE_BODY" | sed -n '/### Task Description/,/###/{/###/!p;}' | sed '/^$/d' | head -1)
342
- echo "task=$TASK" >> $GITHUB_OUTPUT
343
-
344
- # Parse branch name (optional)
345
- BRANCH=$(echo "$ISSUE_BODY" | sed -n '/### Branch Name/,/###/{/###/!p;}' | sed '/^$/d' | head -1)
346
- if [ -z "$BRANCH" ]; then
347
- BRANCH="spets/$ISSUE_NUMBER"
348
- fi
349
- echo "branch=$BRANCH" >> $GITHUB_OUTPUT
350
-
351
- - name: Create and checkout branch
352
- run: |
353
- git remote set-url origin https://x-access-token:${gh("secrets.GITHUB_TOKEN")}@github.com/${gh("github.repository")}.git
354
- git checkout -b ${gh("steps.parse.outputs.branch")}
355
- git push -u origin ${gh("steps.parse.outputs.branch")}
356
-
357
- - name: Setup Node.js
358
- uses: actions/setup-node@v4
359
- with:
360
- node-version: '20'
361
- cache: 'npm'
362
-
363
- - name: Cache global npm packages
364
- uses: actions/cache@v4
365
- with:
366
- path: ~/.npm
367
- key: ${gh("runner.os")}-npm-global-${gh("hashFiles('package-lock.json')")}
368
- restore-keys: |
369
- ${gh("runner.os")}-npm-global-
370
-
371
- - name: Cache Claude Code
372
- id: cache-claude
373
- uses: actions/cache@v4
374
- with:
375
- path: /usr/local/lib/node_modules/@anthropic-ai/claude-code
376
- key: claude-code-${gh("runner.os")}-v1
377
-
378
- - name: Install Claude Code
379
- if: steps.cache-claude.outputs.cache-hit != 'true'
380
- run: npm install -g @anthropic-ai/claude-code
381
-
382
- - name: Install dependencies
383
- run: npm ci
384
-
385
- - name: Start Spets workflow
386
- run: |
387
- npx spets start "$TASK" --github --issue ${gh("github.event.issue.number")}
388
- env:
389
- TASK: ${gh("steps.parse.outputs.task")}
390
- CLAUDE_CODE_OAUTH_TOKEN: ${gh("secrets.CLAUDE_CODE_OAUTH_TOKEN")}
391
- GH_TOKEN: ${gh("secrets.GITHUB_TOKEN")}
392
-
393
- - name: Push changes
394
- run: |
395
- git remote set-url origin https://x-access-token:${gh("secrets.GITHUB_TOKEN")}@github.com/${gh("github.repository")}.git
396
- git add -A
397
- git diff --staged --quiet || git commit -m "Spets: Start workflow for #${gh("github.event.issue.number")}"
398
- git push
399
-
400
- # Handle commands from Issue/PR comments
401
- handle-command:
402
- if: |
403
- github.event.action == 'created' && (
404
- contains(github.event.comment.body, '/approve') ||
405
- contains(github.event.comment.body, '/revise') ||
406
- contains(github.event.comment.body, '/reject')
407
- )
408
- runs-on: ubuntu-latest
409
-
410
- steps:
411
- - name: Find branch from Issue or PR
412
- id: branch
413
- env:
414
- GH_TOKEN: ${gh("secrets.GITHUB_TOKEN")}
415
- run: |
416
- # Check if this is a PR (has pull_request field)
417
- PR_BRANCH=$(gh api repos/${gh("github.repository")}/issues/${gh("github.event.issue.number")} --jq '.pull_request.url // empty' 2>/dev/null)
418
-
419
- if [ -n "$PR_BRANCH" ]; then
420
- # It's a PR - get head branch directly
421
- BRANCH=$(gh api repos/${gh("github.repository")}/pulls/${gh("github.event.issue.number")} --jq '.head.ref')
422
- echo "Found PR head branch: $BRANCH"
423
- else
424
- # It's an Issue - try to parse branch name from body
425
- ISSUE_BODY=$(gh api repos/${gh("github.repository")}/issues/${gh("github.event.issue.number")} --jq '.body')
426
- CUSTOM_BRANCH=$(echo "$ISSUE_BODY" | sed -n '/### Branch Name/,/###/{/###/!p;}' | sed '/^$/d' | head -1)
427
-
428
- if [ -n "$CUSTOM_BRANCH" ]; then
429
- BRANCH="$CUSTOM_BRANCH"
430
- else
431
- BRANCH="spets/${gh("github.event.issue.number")}"
432
- fi
433
- fi
434
-
435
- echo "Checking for branch: $BRANCH"
436
-
437
- # Check if branch exists on remote using gh api
438
- if gh api "repos/${gh("github.repository")}/branches/$BRANCH" --silent 2>/dev/null; then
439
- echo "name=$BRANCH" >> $GITHUB_OUTPUT
440
- echo "exists=true" >> $GITHUB_OUTPUT
441
- echo "Branch $BRANCH found!"
442
- else
443
- echo "exists=false" >> $GITHUB_OUTPUT
444
- echo "expected=$BRANCH" >> $GITHUB_OUTPUT
445
- echo "::error::Branch $BRANCH not found. Start workflow first by creating an Issue with 'spets' label."
446
- fi
447
-
448
- - name: Post error comment
449
- if: steps.branch.outputs.exists == 'false'
450
- run: |
451
- gh issue comment ${gh("github.event.issue.number")} \\
452
- -R "${gh("github.repository")}" \\
453
- --body "\u274C **Spets Error**: Branch \\\`${gh("steps.branch.outputs.expected")}\\\` not found.
454
-
455
- Please make sure the workflow was started properly. You can:
456
- 1. Add the \\\`spets\\\` label to this issue to trigger the start workflow
457
- 2. Or manually create the branch and run \\\`spets start\\\`"
458
- env:
459
- GH_TOKEN: ${gh("secrets.GITHUB_TOKEN")}
460
-
461
- - name: Exit if branch not found
462
- if: steps.branch.outputs.exists == 'false'
463
- run: exit 1
464
-
465
- - name: Checkout
466
- uses: actions/checkout@v4
467
- with:
468
- ref: ${gh("steps.branch.outputs.name")}
469
- fetch-depth: 1
470
- persist-credentials: false
471
-
472
- - name: Setup Git
473
- run: |
474
- git config user.name "github-actions[bot]"
475
- git config user.email "github-actions[bot]@users.noreply.github.com"
476
-
477
- - name: Setup Node.js
478
- uses: actions/setup-node@v4
479
- with:
480
- node-version: '20'
481
- cache: 'npm'
482
-
483
- - name: Cache global npm packages
484
- uses: actions/cache@v4
485
- with:
486
- path: ~/.npm
487
- key: ${gh("runner.os")}-npm-global-${gh("hashFiles('package-lock.json')")}
488
- restore-keys: |
489
- ${gh("runner.os")}-npm-global-
490
-
491
- - name: Cache Claude Code
492
- id: cache-claude
493
- uses: actions/cache@v4
494
- with:
495
- path: /usr/local/lib/node_modules/@anthropic-ai/claude-code
496
- key: claude-code-${gh("runner.os")}-v1
497
-
498
- - name: Install Claude Code
499
- if: steps.cache-claude.outputs.cache-hit != 'true'
500
- run: npm install -g @anthropic-ai/claude-code
501
-
502
- - name: Install dependencies
503
- run: npm ci
504
-
505
- - name: Run Spets command
506
- run: |
507
- npx spets github --issue ${gh("github.event.issue.number")} --comment "$COMMENT"
508
- env:
509
- COMMENT: ${gh("github.event.comment.body")}
510
- CLAUDE_CODE_OAUTH_TOKEN: ${gh("secrets.CLAUDE_CODE_OAUTH_TOKEN")}
511
- GH_TOKEN: ${gh("secrets.GITHUB_TOKEN")}
512
-
513
- - name: Push changes
514
- run: |
515
- git remote set-url origin https://x-access-token:${gh("secrets.GITHUB_TOKEN")}@github.com/${gh("github.repository")}.git
516
- git add -A
517
- git diff --staged --quiet || git commit -m "Spets: Update from #${gh("github.event.issue.number")}"
518
- git push
519
- `;
272
+ const workflowTemplate = readFileSync(join(__dirname, "..", "templates", "github", "workflows", "spets.yml"), "utf-8");
273
+ const issueTemplate = readFileSync(join(__dirname, "..", "templates", "github", "ISSUE_TEMPLATE", "spets-task.yml"), "utf-8");
274
+ writeFileSync(join(workflowDir, "spets.yml"), workflowTemplate);
275
+ writeFileSync(join(templateDir, "spets-task.yml"), issueTemplate);
520
276
  }
521
277
 
522
278
  // src/commands/status.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spets",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "description": "Spec Driven Development Execution Framework",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -0,0 +1,20 @@
1
+ name: Spets Task
2
+ description: Start a Spets workflow
3
+ labels: ["spets"]
4
+ body:
5
+ - type: input
6
+ id: task
7
+ attributes:
8
+ label: Task Description
9
+ description: What do you want to accomplish?
10
+ placeholder: "Add user authentication"
11
+ validations:
12
+ required: true
13
+ - type: input
14
+ id: branch
15
+ attributes:
16
+ label: Branch Name
17
+ description: Leave empty to auto-generate (spets/<issue-number>)
18
+ placeholder: "feature/my-feature"
19
+ validations:
20
+ required: false
@@ -0,0 +1,213 @@
1
+ # Spets GitHub Action
2
+ # Handles workflow start from Issue creation and commands from comments
3
+
4
+ name: Spets Workflow
5
+
6
+ on:
7
+ issues:
8
+ types: [opened]
9
+ issue_comment:
10
+ types: [created]
11
+
12
+ permissions:
13
+ contents: write
14
+ issues: write
15
+ pull-requests: write
16
+
17
+ jobs:
18
+ # Start workflow when a spets Issue is created
19
+ start-workflow:
20
+ if: github.event.action == 'opened' && contains(github.event.issue.labels.*.name, 'spets')
21
+ runs-on: ubuntu-latest
22
+
23
+ steps:
24
+ - name: Checkout
25
+ uses: actions/checkout@v4
26
+ with:
27
+ fetch-depth: 1
28
+ persist-credentials: false
29
+
30
+ - name: Parse Issue body
31
+ id: parse
32
+ env:
33
+ ISSUE_BODY: ${{ github.event.issue.body }}
34
+ ISSUE_NUMBER: ${{ github.event.issue.number }}
35
+ run: |
36
+ # Parse task description
37
+ TASK=$(echo "$ISSUE_BODY" | sed -n '/### Task Description/,/###/{/###/!p;}' | sed '/^$/d' | head -1)
38
+ echo "task=$TASK" >> $GITHUB_OUTPUT
39
+
40
+ # Parse branch name (optional)
41
+ BRANCH=$(echo "$ISSUE_BODY" | sed -n '/### Branch Name/,/###/{/###/!p;}' | sed '/^$/d' | head -1)
42
+ if [ -z "$BRANCH" ]; then
43
+ BRANCH="spets/$ISSUE_NUMBER"
44
+ fi
45
+ echo "branch=$BRANCH" >> $GITHUB_OUTPUT
46
+
47
+ - name: Create and checkout branch
48
+ run: |
49
+ git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git
50
+ git checkout -b ${{ steps.parse.outputs.branch }}
51
+ git push -u origin ${{ steps.parse.outputs.branch }}
52
+
53
+ - name: Setup Node.js
54
+ uses: actions/setup-node@v4
55
+ with:
56
+ node-version: '20'
57
+ cache: 'npm'
58
+
59
+ - name: Cache global npm packages
60
+ uses: actions/cache@v4
61
+ with:
62
+ path: ~/.npm
63
+ key: ${{ runner.os }}-npm-global-${{ hashFiles('package-lock.json') }}
64
+ restore-keys: |
65
+ ${{ runner.os }}-npm-global-
66
+
67
+ - name: Cache Claude Code
68
+ id: cache-claude
69
+ uses: actions/cache@v4
70
+ with:
71
+ path: /usr/local/lib/node_modules/@anthropic-ai/claude-code
72
+ key: claude-code-${{ runner.os }}-v1
73
+
74
+ - name: Install Claude Code
75
+ if: steps.cache-claude.outputs.cache-hit != 'true'
76
+ run: npm install -g @anthropic-ai/claude-code
77
+
78
+ - name: Install dependencies
79
+ run: npm ci
80
+
81
+ - name: Start Spets workflow
82
+ run: |
83
+ npx spets start "$TASK" --github --issue ${{ github.event.issue.number }}
84
+ env:
85
+ TASK: ${{ steps.parse.outputs.task }}
86
+ CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
87
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
88
+
89
+ - name: Push changes
90
+ run: |
91
+ git config user.name "github-actions[bot]"
92
+ git config user.email "github-actions[bot]@users.noreply.github.com"
93
+ git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git
94
+ git add -A
95
+ git diff --staged --quiet || git commit -m "Spets: Start workflow for #${{ github.event.issue.number }}"
96
+ git push
97
+
98
+ # Handle commands from Issue/PR comments
99
+ handle-command:
100
+ if: |
101
+ github.event.action == 'created' && (
102
+ contains(github.event.comment.body, '/approve') ||
103
+ contains(github.event.comment.body, '/revise') ||
104
+ contains(github.event.comment.body, '/reject')
105
+ )
106
+ runs-on: ubuntu-latest
107
+
108
+ steps:
109
+ - name: Find branch from Issue or PR
110
+ id: branch
111
+ env:
112
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
113
+ run: |
114
+ # Check if this is a PR (has pull_request field)
115
+ PR_BRANCH=$(gh api repos/${{ github.repository }}/issues/${{ github.event.issue.number }} --jq '.pull_request.url // empty' 2>/dev/null)
116
+
117
+ if [ -n "$PR_BRANCH" ]; then
118
+ # It's a PR - get head branch directly
119
+ BRANCH=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.issue.number }} --jq '.head.ref')
120
+ echo "Found PR head branch: $BRANCH"
121
+ else
122
+ # It's an Issue - try to parse branch name from body
123
+ ISSUE_BODY=$(gh api repos/${{ github.repository }}/issues/${{ github.event.issue.number }} --jq '.body')
124
+ CUSTOM_BRANCH=$(echo "$ISSUE_BODY" | sed -n '/### Branch Name/,/###/{/###/!p;}' | sed '/^$/d' | head -1)
125
+
126
+ if [ -n "$CUSTOM_BRANCH" ]; then
127
+ BRANCH="$CUSTOM_BRANCH"
128
+ else
129
+ BRANCH="spets/${{ github.event.issue.number }}"
130
+ fi
131
+ fi
132
+
133
+ echo "Checking for branch: $BRANCH"
134
+
135
+ # Check if branch exists on remote using gh api
136
+ if gh api "repos/${{ github.repository }}/branches/$BRANCH" --silent 2>/dev/null; then
137
+ echo "name=$BRANCH" >> $GITHUB_OUTPUT
138
+ echo "exists=true" >> $GITHUB_OUTPUT
139
+ echo "Branch $BRANCH found!"
140
+ else
141
+ echo "exists=false" >> $GITHUB_OUTPUT
142
+ echo "expected=$BRANCH" >> $GITHUB_OUTPUT
143
+ echo "::error::Branch $BRANCH not found. Start workflow first by creating an Issue with 'spets' label."
144
+ fi
145
+
146
+ - name: Post error comment
147
+ if: steps.branch.outputs.exists == 'false'
148
+ run: |
149
+ gh issue comment ${{ github.event.issue.number }} \
150
+ -R "${{ github.repository }}" \
151
+ --body "❌ **Spets Error**: Branch \`${{ steps.branch.outputs.expected }}\` not found.
152
+
153
+ Please make sure the workflow was started properly. You can:
154
+ 1. Add the \`spets\` label to this issue to trigger the start workflow
155
+ 2. Or manually create the branch and run \`spets start\`"
156
+ env:
157
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
158
+
159
+ - name: Exit if branch not found
160
+ if: steps.branch.outputs.exists == 'false'
161
+ run: exit 1
162
+
163
+ - name: Checkout
164
+ uses: actions/checkout@v4
165
+ with:
166
+ ref: ${{ steps.branch.outputs.name }}
167
+ fetch-depth: 1
168
+ persist-credentials: false
169
+
170
+ - name: Setup Node.js
171
+ uses: actions/setup-node@v4
172
+ with:
173
+ node-version: '20'
174
+ cache: 'npm'
175
+
176
+ - name: Cache global npm packages
177
+ uses: actions/cache@v4
178
+ with:
179
+ path: ~/.npm
180
+ key: ${{ runner.os }}-npm-global-${{ hashFiles('package-lock.json') }}
181
+ restore-keys: |
182
+ ${{ runner.os }}-npm-global-
183
+
184
+ - name: Cache Claude Code
185
+ id: cache-claude
186
+ uses: actions/cache@v4
187
+ with:
188
+ path: /usr/local/lib/node_modules/@anthropic-ai/claude-code
189
+ key: claude-code-${{ runner.os }}-v1
190
+
191
+ - name: Install Claude Code
192
+ if: steps.cache-claude.outputs.cache-hit != 'true'
193
+ run: npm install -g @anthropic-ai/claude-code
194
+
195
+ - name: Install dependencies
196
+ run: npm ci
197
+
198
+ - name: Run Spets command
199
+ run: |
200
+ npx spets github --issue ${{ github.event.issue.number }} --comment "$COMMENT"
201
+ env:
202
+ COMMENT: ${{ github.event.comment.body }}
203
+ CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
204
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
205
+
206
+ - name: Push changes
207
+ run: |
208
+ git config user.name "github-actions[bot]"
209
+ git config user.email "github-actions[bot]@users.noreply.github.com"
210
+ git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git
211
+ git add -A
212
+ git diff --staged --quiet || git commit -m "Spets: Update from #${{ github.event.issue.number }}"
213
+ git push