@stdd/plugin 0.9.1 → 0.10.0
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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/package.json +1 -1
- package/runtime/adapters/README.md +23 -12
- package/runtime/cli/check.mjs +1 -1
- package/runtime/cli/generated-files.mjs +37 -13
- package/runtime/cli/init.mjs +5 -59
- package/runtime/cli/status.mjs +14 -4
- package/runtime/cli/stdd.mjs +2 -21
- package/runtime/method/README.md +63 -13
- package/runtime/method/reference-commands.md +7 -1
- package/runtime/method/reference-integration.md +55 -50
- package/runtime/package.json +1 -1
- package/runtime/playbooks/brainstorming.md +56 -37
- package/runtime/playbooks/delegate-slice.md +7 -1
- package/runtime/playbooks/finish-change.md +10 -3
- package/runtime/playbooks/investigation.md +11 -5
- package/runtime/playbooks/planning.md +5 -1
- package/runtime/playbooks/start-change.md +30 -16
- package/runtime/sdk/adapters.mjs +18 -66
- package/runtime/sdk/index.d.ts +0 -9
- package/runtime/sdk/index.mjs +0 -4
- package/skills/stdd-brainstorming/SKILL.md +56 -37
- package/skills/stdd-debugging/SKILL.md +1 -1
- package/skills/stdd-delegate-slice/SKILL.md +8 -2
- package/skills/stdd-finish-change/SKILL.md +11 -4
- package/skills/stdd-implement/SKILL.md +1 -1
- package/skills/stdd-investigation/SKILL.md +11 -5
- package/skills/stdd-planning/SKILL.md +6 -2
- package/skills/stdd-pr-green/SKILL.md +1 -1
- package/skills/stdd-start-change/SKILL.md +30 -16
- package/skills/stdd-worktrees/SKILL.md +1 -1
- package/runtime/templates/github-stdd.yml +0 -42
- package/runtime/templates/gitlab-stdd.yml +0 -72
|
@@ -1,48 +1,67 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: stdd-brainstorming
|
|
3
|
-
description: "
|
|
3
|
+
description: "Explore future behavior and hypothetical approaches without forcing action. Use when: Asked for opinions, ideation, future behavior, or a hypothetical implementation approach, with no explicit intent to persist or modify the repository."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- generated by stdd plugin build v0.
|
|
6
|
+
<!-- generated by stdd plugin build v0.10.0 — do not edit -->
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
# Brainstorming
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
The
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
11
|
+
Use Brainstorming as an adaptive conversational stance, not a fixed interview.
|
|
12
|
+
The goal is useful clarity about **what** and **why** before anyone commits to
|
|
13
|
+
action. Clarity, deciding not to act, and continuing later are all successful
|
|
14
|
+
outcomes.
|
|
15
|
+
|
|
16
|
+
## Contract
|
|
17
|
+
|
|
18
|
+
- Stay read-only: create no task, ledger event, persisted artifact, or
|
|
19
|
+
repository mutation.
|
|
20
|
+
- Ground the discussion in current docs or code when materially useful. If
|
|
21
|
+
unknown current facts materially affect the design, invoke
|
|
22
|
+
`stdd-investigation` first; ordinary reading here is not Investigation.
|
|
23
|
+
- A hypothetical plan shown in chat remains Brainstorming. Explicit intent to
|
|
24
|
+
persist an artifact or modify the repository crosses into Start Change when
|
|
25
|
+
no action boundary is active. Within an active change, do not invoke Start
|
|
26
|
+
Change again; proceed to Planning or Implement as the agreed action requires.
|
|
27
|
+
|
|
28
|
+
## Conversation
|
|
29
|
+
|
|
30
|
+
1. **Understand the real need.** Let the user provide context in their own
|
|
31
|
+
shape. Challenge assumptions and decompose ideas that are larger than the
|
|
32
|
+
need; apply YAGNI rather than rewarding scope.
|
|
33
|
+
2. **Ask only decision-bearing questions.** Ask at most one per turn, and only
|
|
34
|
+
when its answer is needed to proceed. Prefer a concise closed choice when
|
|
35
|
+
the answer space is known. Use a question batch only when the user requests
|
|
36
|
+
one.
|
|
37
|
+
3. **Offer useful alternatives.** Once context is sufficient, present two or
|
|
38
|
+
three materially distinct approaches, state the trade-off that matters, and
|
|
39
|
+
lead with a recommendation. Do not manufacture alternatives when only one
|
|
40
|
+
approach is sensible.
|
|
41
|
+
4. **Validate incrementally.** Check substantive decisions as they emerge
|
|
42
|
+
instead of withholding all validation for a final ceremony. An optional
|
|
43
|
+
recap may state the problem, preferred approach, and unresolved questions.
|
|
44
|
+
|
|
45
|
+
## Outcomes
|
|
46
|
+
|
|
47
|
+
Follow the user's intent without forcing a three-option menu:
|
|
48
|
+
|
|
49
|
+
- **No action:** summarize if useful, then stop. Do not pressure the user to
|
|
50
|
+
formalize or implement anything.
|
|
51
|
+
- **Defer:** leave a portable backlog note in chat. Persist it only when the
|
|
52
|
+
user explicitly chooses a destination; if no action boundary is active,
|
|
53
|
+
invoke `stdd-start-change` before writing it.
|
|
54
|
+
- **Act now:** when the user explicitly chooses persisted or
|
|
55
|
+
repository-changing action, invoke `stdd-start-change` if no action boundary
|
|
56
|
+
is active. Within an active change, proceed directly to Planning or Implement
|
|
57
|
+
as appropriate.
|
|
42
58
|
|
|
43
59
|
## Anti-patterns
|
|
44
60
|
|
|
45
|
-
-
|
|
46
|
-
- Asking
|
|
47
|
-
-
|
|
48
|
-
-
|
|
61
|
+
- Turning exploration into a mandatory interview or checklist.
|
|
62
|
+
- Asking stacked questions when one decision would unlock progress.
|
|
63
|
+
- Jumping into code or artifact creation without explicit action intent.
|
|
64
|
+
- Treating every conversation as a change that must converge on docs, a plan,
|
|
65
|
+
or a PR.
|
|
66
|
+
- Presenting options without an opinion, or inventing options to satisfy a
|
|
67
|
+
quota.
|
|
@@ -3,7 +3,7 @@ name: stdd-debugging
|
|
|
3
3
|
description: "Find and fix the root cause of a defect, not its symptom. Use when: A bug, crash, failing test, or unexplained behavior is reported."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- generated by stdd plugin build v0.
|
|
6
|
+
<!-- generated by stdd plugin build v0.10.0 — do not edit -->
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
# Debugging
|
|
@@ -3,7 +3,7 @@ name: stdd-delegate-slice
|
|
|
3
3
|
description: "Hand a slice of work to a worker session with a declared scope, a ledger handoff, and a reviewed result. Use when: Before implementing a multi-step change whose steps are independent — hand slices to worker sessions (subagent, second CLI, teammate) instead of implementing everything inline; also whenever a worker's result comes back for review."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- generated by stdd plugin build v0.
|
|
6
|
+
<!-- generated by stdd plugin build v0.10.0 — do not edit -->
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
# Delegate a Slice
|
|
@@ -21,11 +21,17 @@ compaction, its recorded events do.
|
|
|
21
21
|
sandbox when the worker does not need Git authority:
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
|
|
24
|
+
mkdir -p ../.stdd-workers
|
|
25
|
+
stdd worker create ../.stdd-workers/billing \
|
|
25
26
|
--frozen "docs/**,migrations/**" \
|
|
26
27
|
--allowed "src/billing/**,test/billing/**"
|
|
27
28
|
```
|
|
28
29
|
|
|
30
|
+
A sandbox cannot live inside the checkout or inside any Git repository, so
|
|
31
|
+
it goes beside the project — in one hidden container, not as a visible
|
|
32
|
+
sibling per slice. A directory of projects collects one `.stdd-workers/`
|
|
33
|
+
however many slices you delegate, and deleting it removes every sandbox.
|
|
34
|
+
|
|
29
35
|
Use `stdd slice new --frozen ... --allowed ...` only when the worker must
|
|
30
36
|
operate in an existing isolated checkout. `--frozen` names globs the worker
|
|
31
37
|
must not touch. `--allowed` names the only paths it may change. At least one
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: stdd-finish-change
|
|
3
|
-
description: "Close an implemented change with
|
|
3
|
+
description: "Close an implemented change with the review, PR evidence, terminal CI, and runtime verification its delivery boundary requires. Use when: Implementation is locally verified and the change is ready for review, delivery, or handoff."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- generated by stdd plugin build v0.
|
|
6
|
+
<!-- generated by stdd plugin build v0.10.0 — do not edit -->
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
# Finish change
|
|
@@ -11,8 +11,10 @@ description: "Close an implemented change with independent review, PR evidence,
|
|
|
11
11
|
Close the current checkout in this order:
|
|
12
12
|
|
|
13
13
|
1. Run the complete affected local verification.
|
|
14
|
-
2. Finish every plan item
|
|
15
|
-
|
|
14
|
+
2. Finish every plan item. Run the independent closing review when the plan
|
|
15
|
+
carries a `[review:]` item or a slice was delegated, and the capability
|
|
16
|
+
profile supports it; a single slice makes no review claim and is not asked
|
|
17
|
+
for one.
|
|
16
18
|
`stdd review --via subagent` prints the brief path for a fresh read-only
|
|
17
19
|
subagent; feed its JSON back with `stdd review --result <file>`.
|
|
18
20
|
3. Generate the PR evidence with `stdd evidence`; never hand-author a claim
|
|
@@ -25,6 +27,11 @@ Close the current checkout in this order:
|
|
|
25
27
|
6. Run `stdd task finish` only after the requested delivery boundary is
|
|
26
28
|
actually complete.
|
|
27
29
|
|
|
30
|
+
Steps 3 and 4 apply when that delivery boundary is a PR. A change the user
|
|
31
|
+
asked for as a local edit is complete after step 2 and closes at step 6 —
|
|
32
|
+
opening a PR for it is work nobody requested. Step 5 is not a PR step: any
|
|
33
|
+
delivery carrying a runtime effect gets that verification, PR or not.
|
|
34
|
+
|
|
28
35
|
An `approved` verdict freezes the checkout. Anything you notice afterwards —
|
|
29
36
|
a stale comment, a better name, one more edge case — is deferred with
|
|
30
37
|
`stdd defer`, not edited in. Editing discards the approval rather than
|
|
@@ -3,7 +3,7 @@ name: stdd-implement
|
|
|
3
3
|
description: "Execute one agreed behavior slice through docs, genuine red, implementation, and fresh verification. Use when: The behavior contract is agreed and production changes are ready to begin."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- generated by stdd plugin build v0.
|
|
6
|
+
<!-- generated by stdd plugin build v0.10.0 — do not edit -->
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
# Implement
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: stdd-investigation
|
|
3
|
-
description: "Read-only diagnosis — evidence-backed findings, no changes. Use when: Asked
|
|
3
|
+
description: "Read-only current-state diagnosis — evidence-backed findings, no changes. Use when: Asked a factual question about current behavior, or to diagnose or triage it, WITHOUT changing anything."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- generated by stdd plugin build v0.
|
|
6
|
+
<!-- generated by stdd plugin build v0.10.0 — do not edit -->
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
# Investigation
|
|
@@ -15,9 +15,12 @@ it.
|
|
|
15
15
|
|
|
16
16
|
## Contract
|
|
17
17
|
|
|
18
|
-
- No file
|
|
18
|
+
- No task, ledger event, persisted artifact, file edit, or state-changing side
|
|
19
|
+
effect — reads only.
|
|
19
20
|
- Every claim in the report is backed by evidence you actually observed,
|
|
20
21
|
or labeled as unverified with the blocker named.
|
|
22
|
+
- Opinions, future behavior, and hypothetical implementation approaches belong
|
|
23
|
+
in Brainstorming, not Investigation.
|
|
21
24
|
|
|
22
25
|
## Process
|
|
23
26
|
|
|
@@ -31,5 +34,8 @@ it.
|
|
|
31
34
|
you could not test, report as an explicitly unverified hypothesis with
|
|
32
35
|
the blocker that prevented the test.
|
|
33
36
|
3. **Deliver the report**: the diagnosis (or ranked hypotheses) with its
|
|
34
|
-
evidence, the blockers, and the narrowest next step
|
|
35
|
-
|
|
37
|
+
evidence, the blockers, and the narrowest useful next step.
|
|
38
|
+
4. **Hand off only when the prompt needs design.** If unknown current facts
|
|
39
|
+
materially affect requested future behavior, finish the factual diagnosis
|
|
40
|
+
and then invoke `stdd-brainstorming`. Merely reading docs or code during
|
|
41
|
+
Brainstorming does not require a separate Investigation.
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: stdd-planning
|
|
3
|
-
description: "Turn an agreed behavior contract into an executable, verifiable sequence of work. Use when: The behavior contract is agreed (docs edit drafted or committed) and the change is
|
|
3
|
+
description: "Turn an agreed behavior contract into an executable, verifiable sequence of work. Use when: The behavior contract is agreed (docs edit drafted or committed) and the change is more than one slice — a second independent outcome, an ordering dependency between parts, work to hand to another session, or an unresolved design decision — before the first implementation edit, to fix the execution mode and delivery boundary."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- generated by stdd plugin build v0.
|
|
6
|
+
<!-- generated by stdd plugin build v0.10.0 — do not edit -->
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
# Planning
|
|
10
10
|
|
|
11
|
+
A single-slice change does not come here: it goes straight to
|
|
12
|
+
`stdd-implement`. Planning starts when a second slice appears, which is
|
|
13
|
+
usually mid-work rather than at classification time.
|
|
14
|
+
|
|
11
15
|
A plan is a disposable working artifact: it guides one execution and is thrown
|
|
12
16
|
away. It is never committed as a file — its home is the PR description (for
|
|
13
17
|
the durable summary) and `.stdd/plan.md` (for the working copy: per checkout,
|
|
@@ -3,7 +3,7 @@ name: stdd-pr-green
|
|
|
3
3
|
description: "A PR is done only when its required checks settle terminal-green on the current head. Use when: A PR/MR exists, or is about to be opened, for the current branch."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- generated by stdd plugin build v0.
|
|
6
|
+
<!-- generated by stdd plugin build v0.10.0 — do not edit -->
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
# PR Green
|
|
@@ -1,29 +1,26 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: stdd-start-change
|
|
3
|
-
description: "
|
|
3
|
+
description: "Open durable task state and route work after explicit intent to persist or modify the repository. Use when: The user explicitly wants a persisted work artifact or repository change."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- generated by stdd plugin build v0.
|
|
6
|
+
<!-- generated by stdd plugin build v0.10.0 — do not edit -->
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
# Start change
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
- known defect without a diagnosis → invoke `stdd-debugging`;
|
|
18
|
-
- small agreed change → invoke `stdd-implement` directly.
|
|
11
|
+
Start Change is the action boundary. Invoke it only after explicit intent to
|
|
12
|
+
persist a work artifact or modify the repository. Read-only factual diagnosis
|
|
13
|
+
routes directly to `stdd-investigation`; opinions, future behavior, and
|
|
14
|
+
hypothetical implementation approaches route directly to `stdd-brainstorming`.
|
|
15
|
+
Neither needs a task. A hypothetical plan shown only in chat remains
|
|
16
|
+
Brainstorming.
|
|
19
17
|
|
|
20
18
|
Run `stdd policy show` before asking anything: it may already answer which
|
|
21
19
|
agent owns this area, which standing permission covers the work, and what this
|
|
22
20
|
repository treats as routine rather than a decision. Read it through the
|
|
23
21
|
command, never as raw markdown — the command is where the rules are applied.
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
carrying state across prompts:
|
|
23
|
+
Open one task boundary before carrying action state across prompts:
|
|
27
24
|
|
|
28
25
|
```bash
|
|
29
26
|
stdd task start "<short change name>"
|
|
@@ -33,7 +30,24 @@ stdd status --local
|
|
|
33
30
|
If another task is active, do not reset it silently. Finish it, continue it,
|
|
34
31
|
or ask the user which task owns the checkout.
|
|
35
32
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
Then route. The default is one slice: invoke `stdd-implement` directly. A
|
|
34
|
+
change is one slice when, at the moment of deciding, it has one agreed
|
|
35
|
+
observable outcome, one coherent implementation boundary, one acceptance check,
|
|
36
|
+
and no known dependency on another independently verifiable change.
|
|
37
|
+
|
|
38
|
+
Escalate from that default only on a named trigger:
|
|
39
|
+
|
|
40
|
+
- a second independent outcome or an ordering dependency between parts →
|
|
41
|
+
invoke `stdd-planning`;
|
|
42
|
+
- work to hand to another session → invoke `stdd-planning`, then
|
|
43
|
+
`stdd-delegate-slice`;
|
|
44
|
+
- a design decision nobody has made yet → invoke `stdd-brainstorming` within
|
|
45
|
+
the active change boundary;
|
|
46
|
+
- a known defect without a diagnosis → invoke `stdd-debugging`.
|
|
47
|
+
|
|
48
|
+
Any of them may appear mid-work. Escalating then is the normal case, not a
|
|
49
|
+
failed classification.
|
|
50
|
+
|
|
51
|
+
Read `.stdd/method.md` and the canonical docs governing the touched behavior.
|
|
52
|
+
The classification is a routing decision, not ceremony: skip workflows that do
|
|
53
|
+
not apply, but never skip a mechanical contract that does.
|
|
@@ -3,7 +3,7 @@ name: stdd-worktrees
|
|
|
3
3
|
description: "Work in an isolated workspace without fighting the platform's native isolation. Use when: Starting implementation work that should not disturb the user's current checkout."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- generated by stdd plugin build v0.
|
|
6
|
+
<!-- generated by stdd plugin build v0.10.0 — do not edit -->
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
# Isolated Workspaces
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
# __STAMP__
|
|
2
|
-
#
|
|
3
|
-
# Validates the PR body fetched LIVE from the API, not the event payload —
|
|
4
|
-
# the payload is frozen at trigger time, so a body-only edit would never be
|
|
5
|
-
# re-checked. The `edited` trigger re-runs this workflow on body changes.
|
|
6
|
-
name: STDD
|
|
7
|
-
on:
|
|
8
|
-
pull_request:
|
|
9
|
-
types: [opened, edited, synchronize, reopened]
|
|
10
|
-
|
|
11
|
-
permissions:
|
|
12
|
-
contents: read
|
|
13
|
-
pull-requests: read
|
|
14
|
-
|
|
15
|
-
jobs:
|
|
16
|
-
stdd:
|
|
17
|
-
name: STDD Contract
|
|
18
|
-
runs-on: ubuntu-latest
|
|
19
|
-
steps:
|
|
20
|
-
- uses: actions/checkout@v4
|
|
21
|
-
with:
|
|
22
|
-
fetch-depth: 0 # check-pr --base diffs against the base ref
|
|
23
|
-
- uses: actions/setup-node@v4
|
|
24
|
-
with:
|
|
25
|
-
node-version: 22
|
|
26
|
-
- name: stdd check
|
|
27
|
-
run: npx --yes @stdd/cli@__VERSION__ check .
|
|
28
|
-
- name: PR docs evidence (live body)
|
|
29
|
-
env:
|
|
30
|
-
GH_TOKEN: ${{ github.token }}
|
|
31
|
-
PR_NUMBER: ${{ github.event.pull_request.number }}
|
|
32
|
-
# node, not gh: node is already required for stdd, while self-hosted
|
|
33
|
-
# runners often lack the gh CLI. pipefail: a failed fetch must fail
|
|
34
|
-
# the gate as a fetch error, not feed check-pr an empty body.
|
|
35
|
-
run: |
|
|
36
|
-
set -o pipefail
|
|
37
|
-
node --input-type=module -e '
|
|
38
|
-
const url = "https://api.github.com/repos/" + process.env.GITHUB_REPOSITORY + "/pulls/" + process.env.PR_NUMBER;
|
|
39
|
-
const res = await fetch(url, { headers: { authorization: "Bearer " + process.env.GH_TOKEN, accept: "application/vnd.github+json" } });
|
|
40
|
-
if (!res.ok) { console.error("GitHub API " + res.status + " for " + url); process.exit(1); }
|
|
41
|
-
process.stdout.write((await res.json()).body ?? "");
|
|
42
|
-
' | npx --yes @stdd/cli@__VERSION__ check-pr - --base "origin/$GITHUB_BASE_REF"
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# __STAMP__
|
|
2
|
-
#
|
|
3
|
-
# Include this file from the repository's root .gitlab-ci.yml:
|
|
4
|
-
# include:
|
|
5
|
-
# - local: .gitlab/stdd.gitlab-ci.yml
|
|
6
|
-
#
|
|
7
|
-
# The job defaults to GitLab's reserved .pre stage, so this include stays valid
|
|
8
|
-
# when a consumer defines custom stages without "test". To run STDD in an
|
|
9
|
-
# existing consumer stage, override the included job in the root .gitlab-ci.yml.
|
|
10
|
-
# The override must name a stage declared by that pipeline:
|
|
11
|
-
#
|
|
12
|
-
# stdd:
|
|
13
|
-
# stage: verify
|
|
14
|
-
#
|
|
15
|
-
# Same-project merge requests use CI_JOB_TOKEN. A fork pipeline runs in its
|
|
16
|
-
# source project, so the target must allowlist that project under CI/CD job
|
|
17
|
-
# token permissions. Only for a controlled, trusted source project, an
|
|
18
|
-
# optional masked and hidden STDD_GITLAB_READ_API_TOKEN may carry a
|
|
19
|
-
# target-project access token with read_api. Never expose a target token to
|
|
20
|
-
# untrusted fork code.
|
|
21
|
-
stdd:
|
|
22
|
-
stage: .pre
|
|
23
|
-
image: node:22
|
|
24
|
-
variables:
|
|
25
|
-
GIT_DEPTH: "0"
|
|
26
|
-
rules:
|
|
27
|
-
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
|
28
|
-
script:
|
|
29
|
-
- npx --yes @stdd/cli@__VERSION__ check .
|
|
30
|
-
- |
|
|
31
|
-
set -o pipefail
|
|
32
|
-
node --input-type=module -e '
|
|
33
|
-
const targetProjectId = process.env.CI_MERGE_REQUEST_PROJECT_ID;
|
|
34
|
-
const pipelineProjectId = process.env.CI_PROJECT_ID;
|
|
35
|
-
const crossProject = Boolean(
|
|
36
|
-
pipelineProjectId && targetProjectId && pipelineProjectId !== targetProjectId
|
|
37
|
-
);
|
|
38
|
-
const readApiToken = crossProject
|
|
39
|
-
? process.env.STDD_GITLAB_READ_API_TOKEN
|
|
40
|
-
: "";
|
|
41
|
-
const headers = readApiToken
|
|
42
|
-
? { "PRIVATE-TOKEN": readApiToken, accept: "application/json" }
|
|
43
|
-
: { "JOB-TOKEN": process.env.CI_JOB_TOKEN, accept: "application/json" };
|
|
44
|
-
const url = process.env.CI_API_V4_URL + "/projects/" +
|
|
45
|
-
encodeURIComponent(targetProjectId) + "/merge_requests/" +
|
|
46
|
-
process.env.CI_MERGE_REQUEST_IID;
|
|
47
|
-
const res = await fetch(url, { headers });
|
|
48
|
-
if (!res.ok) {
|
|
49
|
-
console.error("GitLab API " + res.status + " for " + url);
|
|
50
|
-
if (crossProject && !readApiToken) {
|
|
51
|
-
console.error(
|
|
52
|
-
"Fork or cross-project MR pipeline project " + pipelineProjectId +
|
|
53
|
-
" cannot read target project " + targetProjectId +
|
|
54
|
-
". Add pipeline project " + pipelineProjectId +
|
|
55
|
-
" to the target CI/CD job token allowlist, or only for a trusted source project " +
|
|
56
|
-
"define masked and hidden STDD_GITLAB_READ_API_TOKEN with target-project read_api."
|
|
57
|
-
);
|
|
58
|
-
} else if (crossProject) {
|
|
59
|
-
console.error(
|
|
60
|
-
"STDD_GITLAB_READ_API_TOKEN cannot read target project " + targetProjectId +
|
|
61
|
-
"; verify that it is a target-project token with read_api."
|
|
62
|
-
);
|
|
63
|
-
} else {
|
|
64
|
-
console.error(
|
|
65
|
-
"The same-project CI_JOB_TOKEN cannot read this merge request; " +
|
|
66
|
-
"verify the triggering user and job-token permissions."
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
process.exit(1);
|
|
70
|
-
}
|
|
71
|
-
process.stdout.write((await res.json()).description ?? "");
|
|
72
|
-
' | npx --yes @stdd/cli@__VERSION__ check-pr - --base "$CI_MERGE_REQUEST_DIFF_BASE_SHA"
|