@spec-wave/cli 0.5.3 → 0.5.7
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/package.json +1 -1
- package/src/commands/code-review.mjs +4 -3
- package/src/commands/decompose.mjs +7 -4
- package/src/commands/generate-plan.mjs +1 -1
- package/src/commands/generate-spec.mjs +1 -1
- package/src/commands/qa.mjs +4 -3
- package/src/templates/workflows/code-review.yml +2 -1
- package/src/templates/workflows/decompose.yml +2 -1
- package/src/templates/workflows/generate-plan.yml +1 -1
- package/src/templates/workflows/generate-spec.yml +1 -1
- package/src/templates/workflows/qa.yml +2 -1
- package/src/templates/workflows/validate.yml +2 -1
package/package.json
CHANGED
|
@@ -69,6 +69,7 @@ async function setCodeReview(token, project, etapaField, statusField, nodeId) {
|
|
|
69
69
|
|
|
70
70
|
export async function codeReview({ prNumber }) {
|
|
71
71
|
const token = await resolveToken();
|
|
72
|
+
const projectToken = process.env.PROJECT_TOKEN || token;
|
|
72
73
|
const [envOwner, envRepo] = (process.env.GITHUB_REPOSITORY || '').split('/');
|
|
73
74
|
const cfgPath = path.join(process.cwd(), CONFIG_FILE);
|
|
74
75
|
let cfg = {};
|
|
@@ -110,8 +111,8 @@ export async function codeReview({ prNumber }) {
|
|
|
110
111
|
}
|
|
111
112
|
|
|
112
113
|
// Resolve campos uma vez, reutiliza em todas as Features.
|
|
113
|
-
const etapaField = await resolveField(
|
|
114
|
-
const statusField = await resolveField(
|
|
114
|
+
const etapaField = await resolveField(projectToken, project, 'Etapa').catch(() => null);
|
|
115
|
+
const statusField = await resolveField(projectToken, project, 'Status').catch(() => null);
|
|
115
116
|
|
|
116
117
|
const seen = new Set();
|
|
117
118
|
const updated = [];
|
|
@@ -121,7 +122,7 @@ export async function codeReview({ prNumber }) {
|
|
|
121
122
|
if (!feature || seen.has(feature.number)) continue;
|
|
122
123
|
seen.add(feature.number);
|
|
123
124
|
try {
|
|
124
|
-
await setCodeReview(
|
|
125
|
+
await setCodeReview(projectToken, project, etapaField, statusField, feature.node_id);
|
|
125
126
|
updated.push(`#${feature.number} ${feature.title}`);
|
|
126
127
|
console.log(`Feature #${feature.number} → "${CODE_REVIEW_STAGE}" / Status "${TODO_STATUS}".`);
|
|
127
128
|
} catch (err) {
|
|
@@ -65,6 +65,9 @@ Regras:
|
|
|
65
65
|
|
|
66
66
|
export async function decompose({ issueNumber }) {
|
|
67
67
|
const token = await resolveToken();
|
|
68
|
+
// PROJECT_TOKEN deve ter scope "project" para atualizar GitHub Projects v2.
|
|
69
|
+
// Fallback para GITHUB_TOKEN (só funciona em repos pessoais sem org restrictions).
|
|
70
|
+
const projectToken = process.env.PROJECT_TOKEN || token;
|
|
68
71
|
const [owner, repo] = (process.env.GITHUB_REPOSITORY || '').split('/');
|
|
69
72
|
|
|
70
73
|
if (!owner || !repo) {
|
|
@@ -83,7 +86,7 @@ export async function decompose({ issueNumber }) {
|
|
|
83
86
|
let statusField = null;
|
|
84
87
|
if (project?.id && READY_STAGE) {
|
|
85
88
|
try {
|
|
86
|
-
statusField = await resolveStatusField(
|
|
89
|
+
statusField = await resolveStatusField(projectToken, project);
|
|
87
90
|
} catch (err) {
|
|
88
91
|
console.warn(`Não foi possível resolver campo Status do board: ${err.message}`);
|
|
89
92
|
}
|
|
@@ -144,7 +147,7 @@ export async function decompose({ issueNumber }) {
|
|
|
144
147
|
|
|
145
148
|
// Move story para Ready no board.
|
|
146
149
|
try {
|
|
147
|
-
await moveToStage(
|
|
150
|
+
await moveToStage(projectToken, project, statusField, createdStory.nodeId, READY_STAGE);
|
|
148
151
|
} catch (err) {
|
|
149
152
|
console.warn(` Falha ao mover story #${createdStory.number} para "${READY_STAGE}": ${err.message}`);
|
|
150
153
|
}
|
|
@@ -164,7 +167,7 @@ export async function decompose({ issueNumber }) {
|
|
|
164
167
|
|
|
165
168
|
// Move task para Ready no board.
|
|
166
169
|
try {
|
|
167
|
-
await moveToStage(
|
|
170
|
+
await moveToStage(projectToken, project, statusField, createdTask.nodeId, READY_STAGE);
|
|
168
171
|
} catch (err) {
|
|
169
172
|
console.warn(` Falha ao mover task #${createdTask.number} para "${READY_STAGE}": ${err.message}`);
|
|
170
173
|
}
|
|
@@ -173,7 +176,7 @@ export async function decompose({ issueNumber }) {
|
|
|
173
176
|
|
|
174
177
|
// Move a própria Feature para Ready no board.
|
|
175
178
|
try {
|
|
176
|
-
await moveToStage(
|
|
179
|
+
await moveToStage(projectToken, project, statusField, featureNodeId, READY_STAGE);
|
|
177
180
|
if (project?.id && statusField) console.log(`Feature movida para "${READY_STAGE}" no board.`);
|
|
178
181
|
} catch (err) {
|
|
179
182
|
console.warn(`Falha ao mover Feature para "${READY_STAGE}": ${err.message}`);
|
|
@@ -85,7 +85,7 @@ export async function generatePlan({ issueNumber }) {
|
|
|
85
85
|
await commentOnIssue(
|
|
86
86
|
token, owner, repo, parseInt(issueNumber, 10),
|
|
87
87
|
`📋 **plan.md gerado automaticamente!**\n\n` +
|
|
88
|
-
`📄 Arquivo: [\`${filePath}\`](
|
|
88
|
+
`📄 Arquivo: [\`${filePath}\`](https://github.com/${owner}/${repo}/blob/main/${filePath})\n\n` +
|
|
89
89
|
`Revise o plano e, quando estiver pronto, valide a Feature: mova o card para **✅ Ready** ou use:\n` +
|
|
90
90
|
`\`\`\`\ngh issue edit ${issueNumber} --add-label "spec-wave:ready"\n\`\`\``
|
|
91
91
|
);
|
|
@@ -78,7 +78,7 @@ export async function generateSpec({ issueNumber }) {
|
|
|
78
78
|
await commentOnIssue(
|
|
79
79
|
token, owner, repo, parseInt(issueNumber, 10),
|
|
80
80
|
`📋 **spec.md gerado automaticamente!**\n\n` +
|
|
81
|
-
`📄 Arquivo: [\`${filePath}\`](
|
|
81
|
+
`📄 Arquivo: [\`${filePath}\`](https://github.com/${owner}/${repo}/blob/main/${filePath})\n\n` +
|
|
82
82
|
`Revise a especificação e, quando estiver pronto, gere o plano técnico: mova o card para **📋 Plan** ou use:\n` +
|
|
83
83
|
`\`\`\`\ngh issue edit ${issueNumber} --add-label "spec-wave:plan"\n\`\`\``
|
|
84
84
|
);
|
package/src/commands/qa.mjs
CHANGED
|
@@ -64,6 +64,7 @@ async function setQA(token, project, etapaField, statusField, nodeId) {
|
|
|
64
64
|
|
|
65
65
|
export async function qa({ prNumber }) {
|
|
66
66
|
const token = await resolveToken();
|
|
67
|
+
const projectToken = process.env.PROJECT_TOKEN || token;
|
|
67
68
|
const [envOwner, envRepo] = (process.env.GITHUB_REPOSITORY || '').split('/');
|
|
68
69
|
const cfgPath = path.join(process.cwd(), CONFIG_FILE);
|
|
69
70
|
let cfg = {};
|
|
@@ -103,8 +104,8 @@ export async function qa({ prNumber }) {
|
|
|
103
104
|
return;
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
const etapaField = await resolveField(
|
|
107
|
-
const statusField = await resolveField(
|
|
107
|
+
const etapaField = await resolveField(projectToken, project, 'Etapa').catch(() => null);
|
|
108
|
+
const statusField = await resolveField(projectToken, project, 'Status').catch(() => null);
|
|
108
109
|
|
|
109
110
|
const seen = new Set();
|
|
110
111
|
const updated = [];
|
|
@@ -114,7 +115,7 @@ export async function qa({ prNumber }) {
|
|
|
114
115
|
if (!feature || seen.has(feature.number)) continue;
|
|
115
116
|
seen.add(feature.number);
|
|
116
117
|
try {
|
|
117
|
-
await setQA(
|
|
118
|
+
await setQA(projectToken, project, etapaField, statusField, feature.node_id);
|
|
118
119
|
updated.push(`#${feature.number} ${feature.title}`);
|
|
119
120
|
console.log(`Feature #${feature.number} → "${QA_STAGE}" / Status "${TODO_STATUS}".`);
|
|
120
121
|
} catch (err) {
|
|
@@ -17,10 +17,11 @@ jobs:
|
|
|
17
17
|
|
|
18
18
|
- uses: actions/setup-node@v4
|
|
19
19
|
with:
|
|
20
|
-
node-version: '
|
|
20
|
+
node-version: '24'
|
|
21
21
|
|
|
22
22
|
- name: Move Feature to Code Review
|
|
23
23
|
run: npx @spec-wave/cli code-review --pr-number ${{ github.event.pull_request.number }}
|
|
24
24
|
env:
|
|
25
25
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
26
|
+
PROJECT_TOKEN: ${{ secrets.GH_PROJECT_TOKEN }}
|
|
26
27
|
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
@@ -19,12 +19,13 @@ jobs:
|
|
|
19
19
|
|
|
20
20
|
- uses: actions/setup-node@v4
|
|
21
21
|
with:
|
|
22
|
-
node-version: '
|
|
22
|
+
node-version: '24'
|
|
23
23
|
|
|
24
24
|
- name: Decompose into Stories and Tasks
|
|
25
25
|
run: npx @spec-wave/cli decompose --issue-number ${{ github.event.issue.number }}
|
|
26
26
|
env:
|
|
27
27
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
28
|
+
PROJECT_TOKEN: ${{ secrets.GH_PROJECT_TOKEN }}
|
|
28
29
|
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
29
30
|
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
|
|
30
31
|
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
@@ -18,10 +18,11 @@ jobs:
|
|
|
18
18
|
|
|
19
19
|
- uses: actions/setup-node@v4
|
|
20
20
|
with:
|
|
21
|
-
node-version: '
|
|
21
|
+
node-version: '24'
|
|
22
22
|
|
|
23
23
|
- name: Move Feature to QA
|
|
24
24
|
run: npx @spec-wave/cli qa --pr-number ${{ github.event.pull_request.number }}
|
|
25
25
|
env:
|
|
26
26
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
27
|
+
PROJECT_TOKEN: ${{ secrets.GH_PROJECT_TOKEN }}
|
|
27
28
|
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
@@ -12,13 +12,14 @@ jobs:
|
|
|
12
12
|
runs-on: ubuntu-latest
|
|
13
13
|
permissions:
|
|
14
14
|
issues: write
|
|
15
|
+
contents: read
|
|
15
16
|
|
|
16
17
|
steps:
|
|
17
18
|
- uses: actions/checkout@v4
|
|
18
19
|
|
|
19
20
|
- uses: actions/setup-node@v4
|
|
20
21
|
with:
|
|
21
|
-
node-version: '
|
|
22
|
+
node-version: '24'
|
|
22
23
|
|
|
23
24
|
- name: Validate spec and plan
|
|
24
25
|
run: npx @spec-wave/cli validate --issue-number ${{ github.event.issue.number }}
|