|
| 1 | +# E2E smoke test — Copilot provider, every CI-compatible node type |
| 2 | +# Covers: prompt, command, loop (AI node types) + bash, script bun/uv |
| 3 | +# (deterministic node types) + depends_on / when / trigger_rule / $nodeId.output |
| 4 | +# (DAG features) + Copilot-specific options: effort, allowed_tools, |
| 5 | +# output_format (best-effort JSON via prompt augment + 2-tier parser). |
| 6 | +# Skipped: `approval:` — pauses for human input, incompatible with CI. |
| 7 | +# Auth: `gh auth login` OR `COPILOT_GITHUB_TOKEN`. |
| 8 | +# To use `GH_TOKEN` / `GITHUB_TOKEN`, also set `assistantConfig.useLoggedInUser: false`. |
| 9 | +# Requires an active GitHub Copilot subscription. |
| 10 | +name: e2e-copilot-all-nodes-smoke |
| 11 | +description: 'Copilot provider smoke across every CI-compatible node type plus Copilot-specific options.' |
| 12 | +provider: copilot |
| 13 | +model: gpt-5-mini |
| 14 | + |
| 15 | +nodes: |
| 16 | + # ─── AI node types ────────────────────────────────────────────────────── |
| 17 | + |
| 18 | + # 1. prompt: inline prompt + effort + allowed_tools (no tool calls). |
| 19 | + # Verifies reasoningEffort and availableTools=[] reach the SDK. |
| 20 | + - id: prompt-node |
| 21 | + prompt: "Reply with exactly the single word 'ok' and nothing else." |
| 22 | + allowed_tools: [] |
| 23 | + effort: low |
| 24 | + idle_timeout: 30000 |
| 25 | + |
| 26 | + # 2. command: named command file (.archon/commands/e2e-echo-command.md). |
| 27 | + # The command echoes back $ARGUMENTS (the workflow invocation message). |
| 28 | + - id: command-node |
| 29 | + command: e2e-echo-command |
| 30 | + allowed_tools: [] |
| 31 | + idle_timeout: 30000 |
| 32 | + |
| 33 | + # 3. loop: iterative AI prompt until completion signal. |
| 34 | + # Bounded by max_iterations: 2 so a misbehaving model can't hang CI. |
| 35 | + - id: loop-node |
| 36 | + loop: |
| 37 | + prompt: "Reply with exactly 'DONE' and nothing else." |
| 38 | + until: 'DONE' |
| 39 | + max_iterations: 2 |
| 40 | + allowed_tools: [] |
| 41 | + effort: low |
| 42 | + idle_timeout: 60000 |
| 43 | + |
| 44 | + # 4. output_format: Copilot's best-effort structured output path |
| 45 | + # (prompt augmented with schema + 2-tier JSON parser on result text). |
| 46 | + # Unique to Copilot/Pi vs. Claude/Codex native JSON mode — only an |
| 47 | + # E2E test catches "real model drifted around the schema". |
| 48 | + - id: structured-node |
| 49 | + prompt: | |
| 50 | + Return a JSON object with two fields, no fences and no prose: |
| 51 | + - "status": always "ok" (string) |
| 52 | + - "value": always 42 (number) |
| 53 | + allowed_tools: [] |
| 54 | + effort: low |
| 55 | + idle_timeout: 30000 |
| 56 | + output_format: |
| 57 | + type: object |
| 58 | + properties: |
| 59 | + status: |
| 60 | + type: string |
| 61 | + value: |
| 62 | + type: number |
| 63 | + required: [status, value] |
| 64 | + |
| 65 | + # ─── Deterministic node types (no AI) ─────────────────────────────────── |
| 66 | + |
| 67 | + # 5. bash: shell script with JSON output (enables $nodeId.output.status |
| 68 | + # dot-access downstream). |
| 69 | + - id: bash-json-node |
| 70 | + bash: 'echo ''{"status":"ok"}''' |
| 71 | + |
| 72 | + # 6. script: bun (TypeScript/JavaScript runtime) |
| 73 | + - id: script-bun-node |
| 74 | + script: echo-args |
| 75 | + runtime: bun |
| 76 | + timeout: 30000 |
| 77 | + |
| 78 | + # 7. script: uv (Python runtime) |
| 79 | + - id: script-python-node |
| 80 | + script: echo-py |
| 81 | + runtime: uv |
| 82 | + timeout: 30000 |
| 83 | + |
| 84 | + # ─── DAG features ─────────────────────────────────────────────────────── |
| 85 | + |
| 86 | + # 8. depends_on + $nodeId.output substitution |
| 87 | + - id: downstream |
| 88 | + bash: "echo 'downstream got: $prompt-node.output'" |
| 89 | + depends_on: [prompt-node] |
| 90 | + |
| 91 | + # 9. when: conditional (JSON dot-access on bash JSON output) |
| 92 | + - id: gated |
| 93 | + bash: "echo 'gated-ok'" |
| 94 | + depends_on: [bash-json-node] |
| 95 | + when: "$bash-json-node.output.status == 'ok'" |
| 96 | + |
| 97 | + # 10. when: conditional on AI structured output (proves output_format |
| 98 | + # parsed and dot-access works on the resulting object). |
| 99 | + - id: structured-check |
| 100 | + bash: "echo \"structured.status=$structured-node.output.status\"" |
| 101 | + depends_on: [structured-node] |
| 102 | + when: "$structured-node.output.status == 'ok'" |
| 103 | + |
| 104 | + # 11. trigger_rule: merge multiple deps (all_success semantics) |
| 105 | + - id: merge |
| 106 | + bash: "echo 'merge-ok'" |
| 107 | + depends_on: |
| 108 | + [downstream, gated, structured-check, script-bun-node, script-python-node] |
| 109 | + trigger_rule: all_success |
| 110 | + |
| 111 | + # ─── Final assertion ──────────────────────────────────────────────────── |
| 112 | + |
| 113 | + # 12. Verify every upstream node produced non-empty output, including |
| 114 | + # dot-access on the structured-output node (proves output_format |
| 115 | + # parsed and downstream consumers can index into it). |
| 116 | + # Note: value-equality on string fields is avoided on purpose — |
| 117 | + # shellQuote() wraps strings in literal single quotes, so a literal |
| 118 | + # `[ "$x" != "ok" ]` would always fail. Non-emptiness is the right |
| 119 | + # bar for a smoke; the `when:` gate on structured-check already |
| 120 | + # proved the value matched 'ok' to reach this node. |
| 121 | + - id: assert |
| 122 | + bash: | |
| 123 | + fail=0 |
| 124 | + check() { |
| 125 | + local name="$1" |
| 126 | + local value="$2" |
| 127 | + if [ -z "$value" ]; then |
| 128 | + echo "FAIL: $name produced empty output" |
| 129 | + fail=1 |
| 130 | + fi |
| 131 | + } |
| 132 | + check prompt-node "$prompt-node.output" |
| 133 | + check command-node "$command-node.output" |
| 134 | + check loop-node "$loop-node.output" |
| 135 | + check bash-json-node "$bash-json-node.output" |
| 136 | + check script-bun-node "$script-bun-node.output" |
| 137 | + check script-python-node "$script-python-node.output" |
| 138 | + check downstream "$downstream.output" |
| 139 | + check gated "$gated.output" |
| 140 | + check merge "$merge.output" |
| 141 | + check structured.status "$structured-node.output.status" |
| 142 | + check structured.value "$structured-node.output.value" |
| 143 | +
|
| 144 | + if [ "$fail" -eq 1 ]; then exit 1; fi |
| 145 | + echo "PASS: all node types + structured output verified" |
| 146 | + depends_on: [merge, loop-node, command-node] |
| 147 | + trigger_rule: all_success |
0 commit comments