Skip to content

Commit 26fcbde

Browse files
ci(e2e): bootstrap behaviour job on main for pull_request_target
The e2e workflow runs on pull_request_target, so GitHub loads the workflow definition from the PR base branch (main), not the PR head. PR #1982 adds the full Gherkin behaviour suite and workflow wiring on its branch, but those workflow changes cannot execute in CI until they land on main. This minimal bootstrap PR merges first: a behaviour job in e2e.yml, a make behaviour-test target, and a placeholder TestBehaviourCIWiring test so the job compiles and passes. Once this is on main, PR #1982 will run real behaviour tests against its head under the new job. Signed-off-by: Barak Korren <bkorren@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 8c4c52e commit 26fcbde

3 files changed

Lines changed: 118 additions & 3 deletions

File tree

.github/workflows/e2e.yml

Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,29 @@ permissions: {}
99
on:
1010
push:
1111
branches: [main]
12-
# SYNC-WITH: grep regex in "Check for e2e-relevant changes" step in the e2e job
12+
# SYNC-WITH: grep in "Check for e2e-relevant changes" (e2e job) and
13+
# "Check for behaviour-relevant changes" (behaviour job)
1314
paths:
1415
- '**/*.go'
1516
- 'go.mod'
1617
- 'go.sum'
1718
- 'e2e/**'
19+
- 'e2e/behaviour/**'
1820
- 'internal/scaffold/fullsend-repo/**'
1921
- 'internal/security/hooks/**'
2022
- 'internal/dispatch/gcf/mintsrc/**'
2123
- 'internal/sentencetoken/english.json'
24+
- 'internal/runtime/**'
25+
- 'internal/sandbox/**'
26+
- 'internal/config/**'
27+
- 'internal/cli/github.go'
28+
- 'internal/cli/run.go'
29+
- 'internal/layers/**'
30+
- 'internal/forge/**'
31+
- 'internal/harness/**'
32+
- 'internal/dispatch/**'
33+
- 'internal/mintclient/**'
34+
- 'cmd/fullsend/**'
2235
- 'Makefile'
2336
- '.github/workflows/e2e.yml'
2437
- '.github/actions/check-e2e-authorization/**'
@@ -113,7 +126,7 @@ jobs:
113126
exit 0
114127
}
115128
fi
116-
if echo "$FILES" | grep -qE '\.go$|^go\.(mod|sum)$|^e2e/|^internal/scaffold/fullsend-repo/|^internal/security/hooks/|^internal/dispatch/gcf/mintsrc/|^internal/sentencetoken/english\.json$|^Makefile$|^\.github/workflows/e2e\.yml$|^\.github/actions/check-e2e-authorization/|^scripts/check-e2e-authorization\.sh$'; then
129+
if echo "$FILES" | grep -qE '\.go$|^go\.(mod|sum)$|^e2e/|^e2e/behaviour/|^internal/scaffold/fullsend-repo/|^internal/security/hooks/|^internal/dispatch/gcf/mintsrc/|^internal/sentencetoken/english\.json$|^Makefile$|^\.github/workflows/e2e\.yml$|^\.github/actions/check-e2e-authorization/|^scripts/check-e2e-authorization\.sh$'; then
117130
echo "relevant=true" >> "$GITHUB_OUTPUT"
118131
else
119132
echo "::notice::No e2e-relevant files changed — skipping tests"
@@ -156,3 +169,92 @@ jobs:
156169
path: ${{ runner.temp }}/e2e-screenshots/
157170
if-no-files-found: ignore
158171
retention-days: 5
172+
173+
behaviour:
174+
# Same gate authorization as e2e — checks out untrusted PR head with secrets.
175+
needs: gate
176+
if: >-
177+
!cancelled() &&
178+
(github.event_name != 'pull_request_target' || needs.gate.outputs.authorized == 'true')
179+
runs-on: ubuntu-24.04
180+
timeout-minutes: 30
181+
permissions:
182+
contents: read
183+
id-token: write
184+
steps:
185+
- name: Check for behaviour-relevant changes
186+
id: changes
187+
if: github.event_name == 'pull_request_target' || github.event_name == 'merge_group'
188+
env:
189+
GH_TOKEN: ${{ github.token }}
190+
EVENT_NAME: ${{ github.event_name }}
191+
PR_NUMBER: ${{ github.event.pull_request.number }}
192+
REPO: ${{ github.repository }}
193+
MERGE_GROUP_BASE: ${{ github.event.merge_group.base_sha }}
194+
MERGE_GROUP_HEAD: ${{ github.event.merge_group.head_sha }}
195+
# SYNC-WITH: push.paths behaviour entries above
196+
run: |
197+
if [ "$EVENT_NAME" = "merge_group" ]; then
198+
FILES=$(gh api "repos/${REPO}/compare/${MERGE_GROUP_BASE}...${MERGE_GROUP_HEAD}" --jq '.files[].filename') || {
199+
echo "::warning::Failed to fetch merge group files — running behaviour tests as a precaution"
200+
echo "relevant=true" >> "$GITHUB_OUTPUT"
201+
exit 0
202+
}
203+
FILE_COUNT=$(echo "$FILES" | wc -l)
204+
if [ "$FILE_COUNT" -ge 300 ]; then
205+
echo "::warning::Compare API returned $FILE_COUNT files (possible truncation at 300) — running behaviour tests as a precaution"
206+
echo "relevant=true" >> "$GITHUB_OUTPUT"
207+
exit 0
208+
fi
209+
else
210+
FILES=$(gh api "repos/${REPO}/pulls/${PR_NUMBER}/files" --paginate --jq '.[].filename') || {
211+
echo "::warning::Failed to fetch PR files — running behaviour tests as a precaution"
212+
echo "relevant=true" >> "$GITHUB_OUTPUT"
213+
exit 0
214+
}
215+
fi
216+
if echo "$FILES" | grep -qE '^e2e/behaviour/|^e2e/admin/|^internal/runtime/|^internal/sandbox/|^internal/config/|^internal/cli/github\.go$|^internal/cli/run\.go$|^internal/layers/|^internal/scaffold/|^internal/forge/|^internal/harness/|^internal/dispatch/|^internal/security/hooks/|^internal/mintclient/|^cmd/fullsend/|^go\.(mod|sum)$|^Makefile$|^\.github/workflows/e2e\.yml$|^\.github/actions/check-e2e-authorization/|^scripts/check-e2e-authorization\.sh$'; then
217+
echo "relevant=true" >> "$GITHUB_OUTPUT"
218+
else
219+
echo "::notice::No behaviour-relevant files changed — skipping behaviour tests"
220+
echo "relevant=false" >> "$GITHUB_OUTPUT"
221+
fi
222+
223+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
224+
if: steps.changes.outputs.relevant != 'false'
225+
with:
226+
ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }}
227+
persist-credentials: false
228+
allow-unsafe-pr-checkout: ${{ github.event_name == 'pull_request_target' }}
229+
230+
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
231+
if: steps.changes.outputs.relevant != 'false'
232+
with:
233+
go-version-file: go.mod
234+
235+
- name: Authenticate to GCP
236+
if: steps.changes.outputs.relevant != 'false'
237+
uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0
238+
with:
239+
workload_identity_provider: ${{ secrets.E2E_GCP_WIF_PROVIDER }}
240+
service_account: ${{ secrets.E2E_GCP_SERVICE_ACCOUNT }}
241+
242+
- name: Run behaviour tests
243+
if: steps.changes.outputs.relevant != 'false'
244+
run: make behaviour-test
245+
env:
246+
BEHAVIOUR_SCM: github
247+
BEHAVIOUR_CI: githubactions
248+
BEHAVIOUR_INSTALL_MODE: per-repo
249+
BEHAVIOUR_ARTIFACT_DIR: ${{ runner.temp }}/behaviour-artifacts
250+
E2E_GCP_PROJECT_ID: ${{ secrets.E2E_GCP_PROJECT_ID }}
251+
E2E_GCP_WIF_PROVIDER: ${{ secrets.E2E_GCP_WIF_PROVIDER }}
252+
253+
- name: Upload behaviour debug artifacts
254+
if: failure() && steps.changes.outputs.relevant != 'false'
255+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
256+
with:
257+
name: behaviour-artifacts-${{ github.event_name == 'pull_request_target' && github.event.pull_request.number || github.run_id }}
258+
path: ${{ runner.temp }}/behaviour-artifacts/
259+
if-no-files-found: ignore
260+
retention-days: 5

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
.PHONY: help bootstrap lint lint-all check fmt \
33
mindmap go-build go-test go-lint go-fmt go-vet go-tidy \
44
lint-md-links script-test test \
5-
e2e-test lint-eval-cases functional-tests
5+
e2e-test behaviour-test lint-eval-cases functional-tests
66

77
# Let Go automatically download the toolchain version required by go.mod.
88
# This ensures local builds use the right version without manual intervention.
@@ -28,6 +28,7 @@ help:
2828
@echo " script-test - Run shell script tests (post-triage, post-code, post-review, pre-fetch-prior-review, reconcile-repos, validate-output-schema)"
2929
@echo " test - Run all checks: lint-all, go-test, script-test, lint-eval-cases"
3030
@echo " e2e-test - Run admin e2e tests (CI: OIDC mint; local: gh auth login or GH_TOKEN)"
31+
@echo " behaviour-test - Run Gherkin behaviour tests (CI: OIDC mint; local: gh auth login or GH_TOKEN)"
3132
@echo " lint-eval-cases - Lint eval case definitions (annotations.yaml completeness)"
3233
@echo " functional-tests - Run functional agent tests (requires EVAL_ORG, FULLSEND_DIR, GH_TOKEN, GCP creds)"
3334

@@ -135,6 +136,9 @@ test: lint-all go-test script-test lint-eval-cases
135136
e2e-test:
136137
go test -tags e2e -v -count=1 -timeout 30m ./e2e/admin/
137138

139+
behaviour-test:
140+
cd e2e/behaviour && go test -tags behaviour -v -count=1 -timeout 30m .
141+
138142
# Functional agent evals — run agents against ephemeral GitHub repos and judge results.
139143
# Required env: EVAL_ORG (GitHub org for ephemeral repos), plus GCP creds for Vertex AI.
140144
# GH_TOKEN defaults to `gh auth token` if not set.

e2e/behaviour/suite_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//go:build behaviour
2+
3+
package behaviour_test
4+
5+
import "testing"
6+
7+
// TestBehaviourCIWiring is a placeholder until the full Gherkin suite lands.
8+
// It verifies the behaviour build tag, Makefile target, and e2e workflow job compile and run.
9+
func TestBehaviourCIWiring(t *testing.T) {}

0 commit comments

Comments
 (0)