147 lines
4.7 KiB
YAML
147 lines
4.7 KiB
YAML
# Epic Runner — Composition Primitives Example
|
|
#
|
|
# Demonstrates: iterate (sequential), gate (ci_pass), forge template variables
|
|
#
|
|
# Execution flow:
|
|
#
|
|
# fetch-children ← persona step: fetch parent issue, emit child URLs as JSON
|
|
# │
|
|
# implement-children ← iterate (sequential): runs impl-issue for each child URL
|
|
# │
|
|
# ci-gate ← gate (ci_pass): block until CI is green across all PRs
|
|
# │
|
|
# summarise ← persona step: post a completion comment on the epic
|
|
|
|
kind: WavePipeline
|
|
metadata:
|
|
name: ops-implement-epic
|
|
description: "Implement all child issues from a parent epic, gate on CI, then summarise"
|
|
category: composition
|
|
release: true
|
|
|
|
requires:
|
|
tools:
|
|
- gh
|
|
|
|
input:
|
|
source: cli
|
|
example: "https://github.com/re-cinq/wave/issues/184"
|
|
schema:
|
|
type: string
|
|
description: "Parent epic URL (e.g. https://github.com/owner/repo/issues/N)"
|
|
|
|
steps:
|
|
# ── Step 1: fetch parent issue, emit child issue URLs ─────────────────────
|
|
- id: fetch-children
|
|
persona: "gitea-analyst"
|
|
workspace:
|
|
mount:
|
|
- source: ./
|
|
target: /project
|
|
mode: readonly
|
|
exec:
|
|
type: prompt
|
|
source: |
|
|
Input: {{ input }}
|
|
|
|
You are given a parent epic URL. Your job is to extract all child issue URLs
|
|
listed in the epic body.
|
|
|
|
1. Parse the URL to get repo (owner/repo) and issue number.
|
|
2. Fetch the issue:
|
|
{{ forge.cli_tool }} issue view <NUMBER> --repo <REPO> \
|
|
--json number,title,body,url
|
|
3. Scan the body for linked child issues. Look for patterns like:
|
|
- Checkbox lists: `- [ ] #123` or `- [ ] https://github.com/…/issues/123`
|
|
- "Closes #N" / "Part of #N" references
|
|
- Bulleted task lists pointing to issue URLs
|
|
4. For each child issue URL found, verify it is open:
|
|
{{ forge.cli_tool }} issue view <NUMBER> --repo <REPO> --json state,url
|
|
Include only open issues.
|
|
5. Output a JSON object with:
|
|
{
|
|
"parent_url": "<epic_url>",
|
|
"repo": "<owner/repo>",
|
|
"child_urls": ["https://…/issues/N", …]
|
|
}
|
|
|
|
Write this JSON to .wave/output/epic-children.json.
|
|
output_artifacts:
|
|
- name: children
|
|
path: .wave/output/epic-children.json
|
|
type: json
|
|
required: true
|
|
retry:
|
|
policy: aggressive
|
|
max_attempts: 2
|
|
handover:
|
|
contract:
|
|
type: json_schema
|
|
source: .wave/output/epic-children.json
|
|
schema_path: .wave/contracts/epic-children.schema.json
|
|
must_pass: true
|
|
on_failure: retry
|
|
|
|
# ── Step 2: iterate over child issues, run impl-issue for each ───────────
|
|
- id: implement-children
|
|
dependencies: [fetch-children]
|
|
pipeline: impl-issue
|
|
input: "{{ item }}"
|
|
iterate:
|
|
over: "{{ fetch-children.output.child_urls }}"
|
|
mode: sequential
|
|
max_concurrent: 3
|
|
|
|
# ── Step 3: gate — wait for CI to pass across all opened PRs ─────────────
|
|
- id: ci-gate
|
|
dependencies: [implement-children]
|
|
gate:
|
|
type: ci_pass
|
|
timeout: 2h
|
|
message: "Waiting for CI to pass on all PRs opened by child-issue implementations"
|
|
|
|
# ── Step 4: post a summary comment on the parent epic ────────────────────
|
|
- id: summarise
|
|
persona: "gitea-commenter"
|
|
dependencies: [ci-gate]
|
|
memory:
|
|
inject_artifacts:
|
|
- step: fetch-children
|
|
artifact: children
|
|
as: epic_children
|
|
workspace:
|
|
mount:
|
|
- source: ./
|
|
target: /project
|
|
mode: readonly
|
|
exec:
|
|
type: prompt
|
|
source: |
|
|
Input: {{ input }}
|
|
|
|
All child issues have been implemented and CI has passed.
|
|
|
|
Read .wave/artifacts/epic_children to get the parent epic URL and repo.
|
|
|
|
Post a completion comment on the parent epic:
|
|
{{ forge.cli_tool }} issue comment <NUMBER> --repo <REPO> --body-file /tmp/summary.md
|
|
|
|
The comment should include:
|
|
- A completion header: "All child issues implemented — CI green"
|
|
- A checkbox list of every child URL that was processed (mark each done)
|
|
- A note to reviewers about next steps (merge the PRs in dependency order)
|
|
|
|
Write the comment body to /tmp/summary.md before posting.
|
|
output_artifacts:
|
|
- name: epic-summary
|
|
path: .wave/output/epic-summary.json
|
|
type: json
|
|
outcomes:
|
|
- type: url
|
|
extract_from: .wave/output/epic-summary.json
|
|
json_path: .comment_url
|
|
label: "Epic Summary Comment"
|
|
retry:
|
|
policy: aggressive
|
|
max_attempts: 2
|