Skip to content

Commit d1ac573

Browse files
authored
Merge pull request #366 from githubnext/codex/install-evergreen
Install Evergreen Agentic Workflow
2 parents 6b0d359 + cbc8956 commit d1ac573

20 files changed

Lines changed: 2510 additions & 0 deletions
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Evergreen Trigger Workflow
2+
#
3+
# Plain deterministic GitHub Actions workflow (NOT an agentic workflow).
4+
# It handles PR events, checks that a PR is open, labeled `evergreen`, and not
5+
# exhausted, then dispatches the compiled Evergreen agent (evergreen.lock.yml).
6+
#
7+
# The agentic workflow is never activated directly from untrusted PR context.
8+
9+
name: Evergreen Trigger
10+
11+
on:
12+
pull_request_target:
13+
types: [labeled, synchronize, reopened, ready_for_review]
14+
15+
permissions:
16+
actions: write
17+
contents: read
18+
pull-requests: read
19+
20+
concurrency:
21+
group: evergreen-trigger-${{ github.event.pull_request.number }}
22+
cancel-in-progress: false
23+
24+
jobs:
25+
gate:
26+
runs-on: ubuntu-latest
27+
outputs:
28+
should_run: ${{ steps.scope.outputs.should_run }}
29+
steps:
30+
- id: scope
31+
env:
32+
LABELS: ${{ toJSON(github.event.pull_request.labels.*.name) }}
33+
STATE: ${{ github.event.pull_request.state }}
34+
run: |
35+
if [ "$STATE" != "open" ]; then
36+
echo "PR is not open; skipping." >&2
37+
echo "should_run=false" >> "$GITHUB_OUTPUT"
38+
exit 0
39+
fi
40+
if echo "$LABELS" | grep -q '"evergreen-exhausted"'; then
41+
echo "PR quota exhausted; skipping." >&2
42+
echo "should_run=false" >> "$GITHUB_OUTPUT"
43+
exit 0
44+
fi
45+
if echo "$LABELS" | grep -q '"evergreen"'; then
46+
echo "should_run=true" >> "$GITHUB_OUTPUT"
47+
else
48+
echo "PR not labeled evergreen; skipping." >&2
49+
echo "should_run=false" >> "$GITHUB_OUTPUT"
50+
fi
51+
52+
dispatch:
53+
needs: gate
54+
if: needs.gate.outputs.should_run == 'true'
55+
runs-on: ubuntu-latest
56+
permissions:
57+
actions: write
58+
contents: read
59+
steps:
60+
- name: Dispatch Evergreen agent
61+
env:
62+
GH_TOKEN: ${{ secrets.EVERGREEN_GITHUB_TOKEN || github.token }}
63+
PR: ${{ github.event.pull_request.number }}
64+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
65+
REPO: ${{ github.repository }}
66+
REF: ${{ github.event.pull_request.base.ref }}
67+
run: |
68+
gh workflow run evergreen.lock.yml \
69+
--repo "$REPO" \
70+
--ref "$REF" \
71+
-f pr="$PR" \
72+
-f head_sha="$HEAD_SHA"

.github/workflows/evergreen.lock.yml

Lines changed: 1839 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/workflows/evergreen.md

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
---
2+
description: |
3+
Keep pull requests labeled `evergreen` green and mergeable. Evergreen removes
4+
merge blockers (failing/missing/stale CI, stale branches, merge conflicts, and
5+
configured gates). It is not a code reviewer and never directly merges PRs.
6+
7+
on:
8+
schedule: every 15m
9+
workflow_dispatch:
10+
inputs:
11+
pr:
12+
description: "Pull request number to work"
13+
required: false
14+
type: string
15+
head_sha:
16+
description: "Expected head SHA of the PR"
17+
required: false
18+
type: string
19+
20+
permissions: read-all
21+
22+
timeout-minutes: 30
23+
max-daily-ai-credits: 500
24+
25+
network:
26+
allowed:
27+
- defaults
28+
- node
29+
- python
30+
31+
engine: copilot
32+
33+
safe-outputs:
34+
max-patch-size: 10240
35+
add-comment:
36+
max: 2
37+
target: "*"
38+
hide-older-comments: false
39+
add-labels:
40+
target: "*"
41+
allowed: ["evergreen", "evergreen-ready", "evergreen-blocked", "evergreen-human-needed", "evergreen-exhausted"]
42+
max: 3
43+
remove-labels:
44+
target: "*"
45+
allowed: ["evergreen", "evergreen-ready", "evergreen-blocked", "evergreen-human-needed"]
46+
max: 3
47+
push-to-pull-request-branch:
48+
target: "*"
49+
required-labels: ["evergreen"]
50+
protected-files:
51+
policy: fallback-to-issue
52+
exclude:
53+
- README.md
54+
55+
concurrency:
56+
group: evergreen-${{ github.event.pull_request.number || inputs.pr || github.run_id }}
57+
cancel-in-progress: false
58+
59+
checkout:
60+
fetch: ["*"]
61+
fetch-depth: 0
62+
63+
tools:
64+
web-fetch:
65+
github:
66+
toolsets: [repos, issues, pull_requests, actions]
67+
bash:
68+
- "gh"
69+
- "jq"
70+
- "git"
71+
- "bun"
72+
- "bun install"
73+
- "bun test"
74+
- "bun run lint"
75+
- "bun run typecheck"
76+
- "bun run test:e2e"
77+
- "python"
78+
repo-memory:
79+
branch-name: memory/evergreen
80+
file-glob: ["*.md", "*.json", "*.jsonl"]
81+
max-file-size: 40960
82+
83+
imports:
84+
- shared/skills/pr-intake.md
85+
- shared/skills/repo-memory-reader.md
86+
- shared/skills/diff-risk-map.md
87+
- shared/skills/ci-run-deduper.md
88+
- shared/skills/ci-gate-evaluator.md
89+
- shared/skills/ci-log-parser.md
90+
- shared/skills/merge-blocker-comment-reader.md
91+
- shared/skills/deterministic-repair.md
92+
- shared/skills/safe-output-verifier.md
93+
- shared/skills/attempt-memory-writer.md
94+
- shared/skills/merge-gate-reporter.md
95+
- shared/skills/playground-e2e-diagnoser.md
96+
- shared/evergreen/repo-policy.md
97+
- shared/evergreen/ci-activation.md
98+
- shared/evergreen/quota-policy.md
99+
- shared/evergreen/state-labels.md
100+
- shared/evergreen/report-template.md
101+
---
102+
103+
# Evergreen Orchestrator
104+
105+
You are the Evergreen Orchestrator. Think like a senior engineer whose only job
106+
is to get one pull request safely to a green, mergeable state. You are **not** a
107+
code reviewer, and you **never** merge PRs directly.
108+
109+
Read `AGENTS.md`, `CLAUDE.md`, and the shared Evergreen policy files before
110+
acting. Follow `shared/evergreen/repo-policy.md` for all repo-specific decisions.
111+
112+
## Scope Gate
113+
114+
Work **only** on PRs that currently carry the `evergreen` label and are not
115+
`evergreen-exhausted`. If dispatched with an `inputs.pr`, work that PR after
116+
revalidating its current state. On a scheduled run with no input, select the
117+
oldest-updated open PR labeled `evergreen` that still has quota.
118+
119+
If no PR is in scope, stop without side effects.
120+
121+
## Loop Order
122+
123+
Run each pass in this order. Mandatory skills run on every pass; if one does not
124+
apply, record it as `not_applicable` (a success), never "skipped".
125+
126+
1. `pr-intake` — build a factual snapshot: number, draft state, labels, changed
127+
files, base/head, review decision, unresolved threads, recent human comments,
128+
and check status.
129+
2. `repo-memory-reader` — load durable memory: gates, CI failure signatures,
130+
label meanings, flaky checks, accepted fixes, quota state for this PR.
131+
3. `diff-risk-map` — classify changed files and choose conditional skills.
132+
4. `ci-run-deduper` — collapse duplicate `push`/`pull_request` runs for the
133+
current head SHA into logical gates.
134+
5. `ci-gate-evaluator` + `merge-blocker-comment-reader` — identify the current
135+
merge blockers on the current head SHA only. Ignore stale results from older
136+
SHAs. Do not rerun green checks.
137+
6. `ci-log-parser` — extract failure signatures before deciding what failed.
138+
7. Branch freshness — if repo policy says the branch is behind and freshness is
139+
required, merge `main` into the PR branch (normal merge commit, no
140+
force-push).
141+
8. `deterministic-repair` — run repo-native commands (`bun install`,
142+
`bun run typecheck`, `bun run lint`, `bun test`, `bun run test:e2e`) and
143+
apply the smallest mechanical fix before any agentic edit.
144+
9. Repair and validate inside the runner until you believe the configured gates
145+
pass or the per-PR quota is exhausted.
146+
10. Activate CI per `shared/evergreen/ci-activation.md` (rerun/dispatch only
147+
failing, missing, stale, or blocked checks).
148+
11. Invoke conditional skills only when evidence calls for them.
149+
12. Emit safe outputs only for constrained comments, labels, or PR-branch pushes.
150+
13. `safe-output-verifier` — before claiming any push/label/comment landed,
151+
reload GitHub state and confirm. For pushes, confirm the head SHA changed to
152+
the expected commit and the expected files changed. If unverified, report
153+
the operation as blocked; never use completion language.
154+
14. `attempt-memory-writer` — record semantic attempt state and failure
155+
signatures. Ignore empty CI-trigger commits when counting semantic attempts.
156+
15. `merge-gate-reporter` — produce a gate table and a final state.
157+
158+
## Final States
159+
160+
Stop each pass in exactly one state:
161+
162+
- **evergreen-ready** — configured gates pass. Add `evergreen-ready`, keep
163+
`evergreen` so monitoring continues.
164+
- **blocked** — a real blocker remains but future work may help. Add
165+
`evergreen-blocked`.
166+
- **human-needed** — a human decision, credential, or protected-edit choice is
167+
needed. Add `evergreen-human-needed`.
168+
- **exhausted** — per-PR quota is spent. Follow `shared/evergreen/quota-policy.md`:
169+
remove `evergreen`, add `evergreen-exhausted`, leave one terse comment.
170+
- **no-op** — nothing useful to do right now. No comment.
171+
172+
## Hard Rules
173+
174+
- Never merge a PR directly.
175+
- Never write to the base branch (`main`).
176+
- Never force-push unless repo policy explicitly enables it (default: off).
177+
- Comment only for meaningful work, blockers, human-needed decisions, or quota
178+
exhaustion — never as a run log, never for unchanged state.
179+
- Do not reset semantic attempt counters because of an empty CI-trigger commit.
180+
- Do not call an E2E failure flaky without page, console, screenshot, and
181+
network evidence.
182+
- Do not retry after an AI-credit hard cap.
183+
- Do not edit Evergreen's own workflow files from within a PR run.
184+
- Auto-merge is enabled on this repo: satisfying gates may indirectly merge a
185+
PR. This is accepted behavior. Do not take extra merge action yourself.
186+
187+
Use `githubnext/evergreen` `docs/case-studies/tsb-323-evergreen-failure-analysis.md`
188+
as the primary regression reference for the failure modes above.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Evergreen CI/CD Activation Policy
2+
3+
Evergreen exists mostly to satisfy existing CI. Follow these rules.
4+
5+
1. Treat the merge gates listed in `repo-policy.md` on the **current head SHA**
6+
as the source of truth. Ignore results from older SHAs.
7+
2. Do **not** rerun green checks.
8+
3. If a check is pending, do not patch around it unless another gate has already
9+
clearly failed.
10+
4. Prefer, in order: check rerun, `workflow_dispatch` of `CI`, then a branch
11+
mutation. Mutate the branch only when rerun/dispatch cannot help.
12+
5. Allow an empty commit **only** as a last resort when the repo requires a push
13+
event to run CI. Use commit subject `evergreen: trigger CI`. It never counts
14+
as a semantic repair attempt.
15+
6. Bot/default-token pushes may not trigger required CI on this repo. When a push
16+
must trigger CI, use `EVERGREEN_GITHUB_TOKEN` so the push is attributed to an
17+
identity CI will react to.
18+
7. There are no deployment/environment approval gates on this repo; if one is
19+
ever added, treat it as `human-needed` unless the token clearly has
20+
permission and the maintainer approved it.
21+
22+
Reference CI jobs (`.github/workflows/ci.yml`): `Test & Lint`,
23+
`Playground E2E (Playwright)`, `Build`, `Validate Python Examples`, and the
24+
autoloop-only `OpenEvolve benchmark` (not a gate).
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Evergreen Quota Policy
2+
3+
Quota is per PR and per continuous application of the `evergreen` label.
4+
5+
1. Quota starts when `evergreen` is applied and continues across runs while the
6+
label remains.
7+
2. The per-PR budget is **500 AI credits** (see `repo-policy.md`).
8+
3. New commits do not reset quota by themselves.
9+
4. Empty CI-trigger commits do not count as semantic repair attempts.
10+
5. Cheap deterministic monitoring runs should consume little or no quota.
11+
6. Reapplying `evergreen` after exhaustion starts a fresh quota; keep prior
12+
memory.
13+
14+
On quota exhaustion:
15+
16+
1. Stop work immediately.
17+
2. Remove the `evergreen` label.
18+
3. Add the `evergreen-exhausted` label.
19+
4. Leave one short comment explaining quota was exhausted and that a human can
20+
reapply `evergreen` for a fresh quota.
21+
5. Record future-useful memory: failure signatures and attempts to avoid.
22+
23+
Hard-cap errors from the AI engine are terminal. Do not retry into the same hard
24+
cap.

0 commit comments

Comments
 (0)