Summary
Migrate behaviour tests from the current pool-of-12-orgs model to a single configurable org (fullsend-ai-test) with ephemeral UUID-named repos. This supersedes #6815, #6829, and PR #6820 — combining the single-org migration with pool machinery cleanup, vendoring removal, and driver simplification.
Motivation
The current infrastructure is:
- Complex: 12
halfsend-* orgs with distributed locking (e2e-lock repo), channel-based pool of fixed-name repos, singleflight-cached ensurer
- Slow: 50MB vendored binary pushed per repo via
github setup --vendor
- Fragile:
CreateRepo polls GetRepo (API-layer only) instead of GetRef (git-layer), causing 422 Tree SHA does not exist and 409 Git Repository is empty errors
Target Architecture
- One org via
BEHAVIOUR_ORG env var (default fullsend-ai-test)
- Ephemeral repos named
bt-{uuid[:8]}-{scenario-slug} (95-char limit to reserve 5 for -fork suffix)
repos install --fullsend-ref as the only install path — no vendoring, no github setup
- No pool: no channel, no semaphore, no pre-allocation, no outstanding tracking
- No enrollment: preview mint deploys with
PER_REPO_WIF_REPOS=*; repos install --mint-url writes the repo variable
- Simplified driver:
CreateRepo(ctx, hint) / DeleteRepo(ctx, name) / Finalize(ctx)
- Simplified ensurer: single
CreateRepo(ctx, org, hint) (name, error) method — generates name, creates repo, polls GetRef("heads/main") for git readiness, runs repos install, validates, waits for workflow
- Fork cleanup in scenario cleanup (
steps/cleanup.go), not driver
E2E_KEEP_REPOS=true to preserve repos for debugging
Changes
Infrastructure
- Add
BehaviourOrg() helper (BEHAVIOUR_ORG env var) to pkg/e2etest/testutil.go
- Export
tokenForOrg as TokenForOrg(cfg, org) in pkg/e2etest/auth.go
- Add
RunReposInstall to common/setup.go — temp manifest, --fullsend-ref, --mint-url
- Add
envFullsendRef() / prHeadSHAFromEvent() for ref resolution
- Add
ValidatePerRepoPostInstallRefPinned to validate.go
Ensurer (ensure.go)
- Rewrite with single
CreateRepo interface method
- Replace
awaitCreation (polls GetRepo) with awaitGitReady (polls GetRef("heads/main"))
- Remove:
ensured cache, singleflight.Group, InvalidateCache, resetRepo, awaitDeletion, ensureRepoExists
Driver (composed.go)
- Remove channel pool, outstanding map, slot generation
CreateRepo(ctx, hint) delegates to ensurer; DeleteRepo(ctx, name) calls client.DeleteRepo directly
Finalize tears down mint only
Factory
- Rename
repopool_cfmint_previews.go → factory_cfmint.go; NewRepoPoolCFMintPreviews → NewCFMintFactory
- Wildcard
perRepoWIFRepos: "*" and workflowHostRepos: "*"
- Remove
buildRepoList, envPoolSize, DefaultPoolSize
- Delete
repopool_external_mint.go (dead code)
Terminology
- Rename "enrolled" → "installed" in step definitions, error messages, and all 14 feature files
AllocateRepo/DeallocateRepo → CreateRepo/DeleteRepo on Driver interface
- Remove
LeasedRepoName from World — use RepoName
Cleanup
- Fix
resolveForkName and resolveHostRepoName for UUID names (remove hardcoded "test-repo" base)
- Add fork deletion to
steps/cleanup.go
- Remove
BEHAVIOUR_INSTALL_MODE / InstallMode / per-org tag handling
- Add
BEHAVIOUR_FULLSEND_REF to e2e.yml; remove BEHAVIOUR_INSTALL_MODE
- Update
docs/guides/dev/behaviour-testing.md
Not removed (still used by admin e2e)
RunGitHubSetup in common/setup.go
- Pool infrastructure in
pkg/e2etest/ (AcquireOrg, OrgPool, ReleaseLock)
Supersedes
Summary
Migrate behaviour tests from the current pool-of-12-orgs model to a single configurable org (
fullsend-ai-test) with ephemeral UUID-named repos. This supersedes #6815, #6829, and PR #6820 — combining the single-org migration with pool machinery cleanup, vendoring removal, and driver simplification.Motivation
The current infrastructure is:
halfsend-*orgs with distributed locking (e2e-lockrepo), channel-based pool of fixed-name repos, singleflight-cached ensurergithub setup --vendorCreateRepopollsGetRepo(API-layer only) instead ofGetRef(git-layer), causing422 Tree SHA does not existand409 Git Repository is emptyerrorsTarget Architecture
BEHAVIOUR_ORGenv var (defaultfullsend-ai-test)bt-{uuid[:8]}-{scenario-slug}(95-char limit to reserve 5 for-forksuffix)repos install --fullsend-refas the only install path — no vendoring, nogithub setupPER_REPO_WIF_REPOS=*;repos install --mint-urlwrites the repo variableCreateRepo(ctx, hint)/DeleteRepo(ctx, name)/Finalize(ctx)CreateRepo(ctx, org, hint) (name, error)method — generates name, creates repo, pollsGetRef("heads/main")for git readiness, runsrepos install, validates, waits for workflowsteps/cleanup.go), not driverE2E_KEEP_REPOS=trueto preserve repos for debuggingChanges
Infrastructure
BehaviourOrg()helper (BEHAVIOUR_ORGenv var) topkg/e2etest/testutil.gotokenForOrgasTokenForOrg(cfg, org)inpkg/e2etest/auth.goRunReposInstalltocommon/setup.go— temp manifest,--fullsend-ref,--mint-urlenvFullsendRef()/prHeadSHAFromEvent()for ref resolutionValidatePerRepoPostInstallRefPinnedtovalidate.goEnsurer (
ensure.go)CreateRepointerface methodawaitCreation(pollsGetRepo) withawaitGitReady(pollsGetRef("heads/main"))ensuredcache,singleflight.Group,InvalidateCache,resetRepo,awaitDeletion,ensureRepoExistsDriver (
composed.go)CreateRepo(ctx, hint)delegates to ensurer;DeleteRepo(ctx, name)callsclient.DeleteRepodirectlyFinalizetears down mint onlyFactory
repopool_cfmint_previews.go→factory_cfmint.go;NewRepoPoolCFMintPreviews→NewCFMintFactoryperRepoWIFRepos: "*"andworkflowHostRepos: "*"buildRepoList,envPoolSize,DefaultPoolSizerepopool_external_mint.go(dead code)Terminology
AllocateRepo/DeallocateRepo→CreateRepo/DeleteRepoon Driver interfaceLeasedRepoNamefrom World — useRepoNameCleanup
resolveForkNameandresolveHostRepoNamefor UUID names (remove hardcoded"test-repo"base)steps/cleanup.goBEHAVIOUR_INSTALL_MODE/InstallMode/ per-org tag handlingBEHAVIOUR_FULLSEND_REFtoe2e.yml; removeBEHAVIOUR_INSTALL_MODEdocs/guides/dev/behaviour-testing.mdNot removed (still used by admin e2e)
RunGitHubSetupincommon/setup.gopkg/e2etest/(AcquireOrg,OrgPool,ReleaseLock)Supersedes