Gitea's push-mirror cannot push to a non-existent remote — it just runs 'git push' against whatever URL it's given. So a project_create flow that only configures the mirror leaves the GitHub side as an unfulfillable URL. New internal/githubclient package: single-purpose client that POSTs /user/repos to create an empty private repo (auto_init=false so the first mirror push doesn't conflict with a generated README). Treats 422 'name already exists' as idempotent success via ErrAlreadyExists. 401/403 are surfaced as 'PAT missing repo scope or invalid' so the operator sees the real cause instead of a vague upstream error. Skill wiring: - New stepCreateGitHub between stepCreateRepo and stepMirror in the orchestrator. - Skipped entirely when Config.GitHub is nil (degraded mode — the routing pod runs without GITHUB_PAT, mirror config still lands, but the actual sync to github fails until the repo exists). - cmd/routing/main.go constructs githubclient.New(GitHubPAT) only when the PAT is set; the skill receives nil otherwise. Tests: - happy path: fake github 201 + assertions that the 'reached' array is [create_repo, create_github_repo, mirror, infra_commit, issue]. - github 422 already-exists: idempotent, all gitea steps still run. - github 401: returns failed_step=create_github_repo, no mirror or later steps. - degraded mode (Config.GitHub nil): reached omits create_github_repo, rest of the flow runs unchanged. Updated existing tests to read [skill, gh] from newSkill instead of just skill, and adjusted reached-array expectations to include the new step. Tracks #10.
11 KiB
11 KiB