fix(project_create): commit staging namespace directly to infra main
Drops the intermediate `staging/<name>` branch so Flux begins reconciling the namespace within ~60s of `project_create` instead of waiting on a human PR merge. Consistent with project-wide trunk-based development. Rationale: ADR 2026-05-18 in DECISIONS.md. Closes hyperguild#14 (item 1). Item 2 (GITEA_MCP_TOKEN in SOPS) verified already-present in infra@408a527 secrets.enc.yaml. Note: TestRoutingPodEndToEnd is failing on main pre-existing this commit (context deadline waiting for port 33310 in <5s). Not caused by this change; project skill tests pass. To track in a separate issue.
This commit is contained in:
21
DECISIONS.md
21
DECISIONS.md
@@ -118,3 +118,24 @@ When berget.ai tokens run out, flip `BRAIN_LLM_PRIMARY_URL` to iguana.
|
|||||||
**Decision**: The root context-sync generates a `mathias.md` prompt and `mathias.toml` agent config in `~/.vibe/`. This is the one tool that needs a custom adapter path.
|
**Decision**: The root context-sync generates a `mathias.md` prompt and `mathias.toml` agent config in `~/.vibe/`. This is the one tool that needs a custom adapter path.
|
||||||
|
|
||||||
**Consequences**: Run `vibe --agent mathias` to use your conventions. Other Vibe users on the machine aren't affected.
|
**Consequences**: Run `vibe --agent mathias` to use your conventions. Other Vibe users on the machine aren't affected.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2026-05-18 — project_create commits staging namespace directly to infra main
|
||||||
|
|
||||||
|
**Context:** `project_create` writes a k8s namespace manifest into the infra
|
||||||
|
repo so Flux brings up a staging environment for the new project. Initial
|
||||||
|
implementation pushed to a `staging/<name>` branch, which required manual PR
|
||||||
|
merge before Flux saw the namespace — defeating the "one tool call, project
|
||||||
|
exists, staging reconciling within 60s" goal.
|
||||||
|
|
||||||
|
**Decision:** Option A — commit directly to `main`. `callInfraCommit` passes
|
||||||
|
`branch: "main"` to gitea-mcp's `file_write_branch`; no PR, no merge step.
|
||||||
|
|
||||||
|
**Consequences:** Staging namespace appears in cluster within ~60s of the
|
||||||
|
`project_create` call. Consistent with project-wide TBD policy (CLAUDE.md):
|
||||||
|
commit directly to main, every commit deployable. Acceptable because the
|
||||||
|
manifest is a fresh namespace under `k3s/staging/<name>/` — isolated, low
|
||||||
|
blast-radius, and Flux will simply recreate it if the file is bad. Manual
|
||||||
|
review gating was friction for no compensating safety gain on experiment
|
||||||
|
namespaces.
|
||||||
|
|||||||
@@ -97,8 +97,7 @@ func (s *Skill) handleCreate(ctx context.Context, raw json.RawMessage) (json.Raw
|
|||||||
|
|
||||||
// Step 3: commit staging namespace manifest to infra repo. Done before
|
// Step 3: commit staging namespace manifest to infra repo. Done before
|
||||||
// the issue so the staging env is reconciling by the time the issue lands.
|
// the issue so the staging env is reconciling by the time the issue lands.
|
||||||
branch := fmt.Sprintf("staging/%s", args.Name)
|
if err := s.callInfraCommit(ctx, args.Name); err != nil {
|
||||||
if err := s.callInfraCommit(ctx, args.Name, branch); err != nil {
|
|
||||||
if !isConflict(err) {
|
if !isConflict(err) {
|
||||||
return marshalPartial(res, stepInfraCommit, err)
|
return marshalPartial(res, stepInfraCommit, err)
|
||||||
}
|
}
|
||||||
@@ -171,17 +170,16 @@ func (s *Skill) callMirror(ctx context.Context, name string) error {
|
|||||||
}, nil)
|
}, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// callInfraCommit writes the staging namespace manifest into the infra repo
|
// callInfraCommit writes the staging namespace manifest directly to infra
|
||||||
// on a dedicated branch. Flux picks it up after merge.
|
// main. Flux reconciles within ~60s. See DECISIONS.md 2026-05-18.
|
||||||
func (s *Skill) callInfraCommit(ctx context.Context, name, branch string) error {
|
func (s *Skill) callInfraCommit(ctx context.Context, name string) error {
|
||||||
manifest := stagingNamespaceManifest(name, time.Now().UTC().Format(time.RFC3339))
|
manifest := stagingNamespaceManifest(name, time.Now().UTC().Format(time.RFC3339))
|
||||||
return s.cfg.Client.CallTool(ctx, "file_write_branch", map[string]any{
|
return s.cfg.Client.CallTool(ctx, "file_write_branch", map[string]any{
|
||||||
"owner": s.cfg.GiteaOwner,
|
"owner": s.cfg.GiteaOwner,
|
||||||
"name": s.cfg.InfraRepo,
|
"name": s.cfg.InfraRepo,
|
||||||
"path": fmt.Sprintf("k3s/staging/%s/namespace.yaml", name),
|
"path": fmt.Sprintf("k3s/staging/%s/namespace.yaml", name),
|
||||||
"content": manifest,
|
"content": manifest,
|
||||||
"branch": branch,
|
"branch": "main",
|
||||||
"base": "main",
|
|
||||||
"message": fmt.Sprintf("feat(staging): add namespace for %s\n\nGenerated by hyperguild project_create.", name),
|
"message": fmt.Sprintf("feat(staging): add namespace for %s\n\nGenerated by hyperguild project_create.", name),
|
||||||
}, nil)
|
}, nil)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user