test: end-to-end mirror flow — repo_create + repo_mirror_push → GitHub #19

Closed
opened 2026-05-14 14:40:26 +00:00 by mathias · 2 comments
Owner

Summary

Once repo_create (#13) and repo_mirror_push (#16) are implemented, they should be tested together end-to-end to verify the full Gitea → GitHub mirror flow before implementing the composite project_create tool in hyperguild.

Test sequence (from claude.ai chat)

Step 1: Create test repo on Gitea

repo_create(owner=mathias, name=test-mirror-flow, private=true, auto_init=true)

Expected: repo appears at gitea.d-ma.be/mathias/test-mirror-flow

Step 2: Configure push mirror to GitHub

repo_mirror_push_add(
  owner=mathias,
  name=test-mirror-flow,
  remote_address=https://github.com/mathiasb/test-mirror-flow.git,
  remote_username=mathiasb,
  remote_password=<PAT>,
  sync_on_commit=true
)

Expected: mirror configured in Gitea settings

Step 3: Verify GitHub repo appears

  • Wait up to 60s
  • Check github.com/mathiasb/test-mirror-flow exists
  • Verify initial commit is present

Step 4: Test sync on commit

file_write_branch(name=test-mirror-flow, path=TEST.md, content="mirror test", message="test: verify mirror sync", branch=main)

Expected: commit appears on GitHub within 60s

Step 5: Cleanup

repo_delete(owner=mathias, name=test-mirror-flow, confirm=test-mirror-flow)

Delete from GitHub manually (repo_delete only covers Gitea).

Success criteria

  • GitHub repo created automatically via mirror, no manual GitHub API call needed
  • Commits sync within 60s
  • Flow works end-to-end from claude.ai chat session

Dependency

Requires #13 (repo_create) and #16 (repo_mirror_push) to be implemented first.
Also requires #11 (repo_delete) for cleanup step.

Why this matters

This is the foundation of hyperguild new-project — the entire project creation flow
depends on this mirror mechanism working reliably from claude.ai.

## Summary Once repo_create (#13) and repo_mirror_push (#16) are implemented, they should be tested together end-to-end to verify the full Gitea → GitHub mirror flow before implementing the composite `project_create` tool in hyperguild. ## Test sequence (from claude.ai chat) **Step 1: Create test repo on Gitea** ``` repo_create(owner=mathias, name=test-mirror-flow, private=true, auto_init=true) ``` Expected: repo appears at gitea.d-ma.be/mathias/test-mirror-flow **Step 2: Configure push mirror to GitHub** ``` repo_mirror_push_add( owner=mathias, name=test-mirror-flow, remote_address=https://github.com/mathiasb/test-mirror-flow.git, remote_username=mathiasb, remote_password=<PAT>, sync_on_commit=true ) ``` Expected: mirror configured in Gitea settings **Step 3: Verify GitHub repo appears** - Wait up to 60s - Check github.com/mathiasb/test-mirror-flow exists - Verify initial commit is present **Step 4: Test sync on commit** ``` file_write_branch(name=test-mirror-flow, path=TEST.md, content="mirror test", message="test: verify mirror sync", branch=main) ``` Expected: commit appears on GitHub within 60s **Step 5: Cleanup** ``` repo_delete(owner=mathias, name=test-mirror-flow, confirm=test-mirror-flow) ``` Delete from GitHub manually (repo_delete only covers Gitea). ## Success criteria - [ ] GitHub repo created automatically via mirror, no manual GitHub API call needed - [ ] Commits sync within 60s - [ ] Flow works end-to-end from claude.ai chat session ## Dependency Requires #13 (repo_create) and #16 (repo_mirror_push) to be implemented first. Also requires #11 (repo_delete) for cleanup step. ## Why this matters This is the foundation of `hyperguild new-project` — the entire project creation flow depends on this mirror mechanism working reliably from claude.ai.
Author
Owner

Parked for now — capturing prerequisites so this is ready to run later.

GitHub PAT scope needed

The PAT is the push credential for the Gitea → GitHub push-mirror (passed as remote_password).

  • Classic PAT: repo scope — simplest single choice. Covers git-push to the target repo (private or public) AND creating the repo via the GitHub API. (public_repo alone suffices only if the mirror target is always public.)
  • Fine-grained PAT equivalent: target repo(s) → Contents: Read and write (push); add Administration: Read and write only if the PAT must also create repos.

Secret handling: consume the PAT only inside op run/env vars — never in argv, logs, or a committed file.

Correction: mirror does NOT auto-create the GitHub repo

Step 3's success criterion ("GitHub repo created automatically via mirror, no manual GitHub API call needed") is incorrect. git push does not create repositories on GitHub — a Gitea push-mirror pushes to an existing remote. If github.com/<user>/<repo> doesn't exist, the mirror push fails.

So the corrected flow needs a pre-create step before configuring the mirror:

Step 1b (new): create the GitHub repo first — e.g.
POST https://api.github.com/user/repos {"name":"test-mirror-flow","private":true} with the repo-scoped PAT (or create it manually in the GitHub UI). Only then does Step 2 (repo_mirror_push_add) have a target to push into.

Updated test sequence

  1. repo_create on Gitea (already works — verified #33).
    1b. Create the empty GitHub repo via API (or UI) — the mirror won't create it.
  2. repo_mirror_push_add(..., remote_password=<PAT>, sync_on_commit=true).
  3. Verify commits appear on GitHub within ~60s.
  4. file_write_branch on Gitea → commit appears on GitHub within ~60s (sync-on-commit).
  5. Cleanup: repo_delete (Gitea) + delete the GitHub repo manually (repo_delete only covers Gitea).

Still blocked on

A repo-scoped GitHub PAT for mathiasb, provisioned into the environment (1Password → env). Once that's available this is runnable end-to-end.

Parked for now — capturing prerequisites so this is ready to run later. ## GitHub PAT scope needed The PAT is the **push credential** for the Gitea → GitHub push-mirror (passed as `remote_password`). - **Classic PAT: `repo` scope** — simplest single choice. Covers git-push to the target repo (private or public) AND creating the repo via the GitHub API. (`public_repo` alone suffices only if the mirror target is always public.) - **Fine-grained PAT equivalent:** target repo(s) → **Contents: Read and write** (push); add **Administration: Read and write** only if the PAT must also create repos. Secret handling: consume the PAT only inside `op run`/env vars — never in argv, logs, or a committed file. ## Correction: mirror does NOT auto-create the GitHub repo Step 3's success criterion ("GitHub repo created automatically via mirror, no manual GitHub API call needed") is **incorrect**. `git push` does not create repositories on GitHub — a Gitea push-mirror pushes to an **existing** remote. If `github.com/<user>/<repo>` doesn't exist, the mirror push **fails**. So the corrected flow needs a **pre-create step** before configuring the mirror: **Step 1b (new): create the GitHub repo first** — e.g. `POST https://api.github.com/user/repos {"name":"test-mirror-flow","private":true}` with the `repo`-scoped PAT (or create it manually in the GitHub UI). Only then does Step 2 (`repo_mirror_push_add`) have a target to push into. ## Updated test sequence 1. `repo_create` on Gitea (already works — verified #33). 1b. **Create the empty GitHub repo** via API (or UI) — the mirror won't create it. 2. `repo_mirror_push_add(..., remote_password=<PAT>, sync_on_commit=true)`. 3. Verify commits appear on GitHub within ~60s. 4. `file_write_branch` on Gitea → commit appears on GitHub within ~60s (sync-on-commit). 5. Cleanup: `repo_delete` (Gitea) + delete the GitHub repo manually (repo_delete only covers Gitea). ## Still blocked on A `repo`-scoped GitHub PAT for `mathiasb`, provisioned into the environment (1Password → env). Once that's available this is runnable end-to-end.
Author
Owner

Verified end-to-end 2026-07-04 with a valid repo-scoped PAT. The Gitea → GitHub push-mirror works.

What ran (all cleaned up):

  1. repo_create → Gitea mathias/test-mirror-flow (private, auto-init). ✓
  2. Pre-created GitHub mathiasb/test-mirror-flow (private) via POST /user/repos — required, see finding #1.
  3. Configured push-mirror via gitea REST (POST .../push_mirrors, sync_on_commit=true) — see finding #3. → 200.
  4. Triggered POST .../push_mirrors-sync → initial commit appeared on GitHub (count=1, "Initial commit"). ✓
  5. Wrote TEST.md on Gitea mainauto-propagated to GitHub within 30s via sync_on_commit (count=2, "test: verify mirror sync-on-commit", TEST.md 200 on GitHub). ✓
  6. Cleanup: Gitea repo deleted. GitHub repo delete → 403 (PAT lacks delete_repo) → left for manual deletion.

Findings (correct the original assumptions):

  1. Mirror does NOT auto-create the GitHub repo (as flagged earlier) — the GitHub repo must be pre-created; git push to a non-existent GitHub repo fails.
  2. Existing commits don't push on mirror-add — configuring the mirror does not retroactively push the current HEAD; you must trigger push_mirrors-sync once (or make a new commit). sync_on_commit then handles subsequent commits automatically.
  3. repo_mirror_push MCP tool takes remote_password as a plain arg → the PAT would land in the tool-call transcript (→ claudewatcher → brain). I deliberately used the gitea REST API inside op run instead so the PAT stayed in the subprocess. Filed a separate security issue to fix the tool's secret handling.
  4. GitHub repo cleanup needs delete_repo scope (this PAT has read:org, repo, workflow).

Manual cleanup for you: delete github.com/mathiasb/test-mirror-flow (my PAT couldn't — no delete_repo).

Closing — mirror flow proven.

✅ **Verified end-to-end 2026-07-04** with a valid `repo`-scoped PAT. The Gitea → GitHub push-mirror works. **What ran (all cleaned up):** 1. `repo_create` → Gitea `mathias/test-mirror-flow` (private, auto-init). ✓ 2. **Pre-created** GitHub `mathiasb/test-mirror-flow` (private) via `POST /user/repos` — required, see finding #1. 3. Configured push-mirror via gitea REST (`POST .../push_mirrors`, `sync_on_commit=true`) — see finding #3. → 200. 4. Triggered `POST .../push_mirrors-sync` → initial commit appeared on GitHub (`count=1, "Initial commit"`). ✓ 5. Wrote `TEST.md` on Gitea `main` → **auto-propagated to GitHub within 30s** via `sync_on_commit` (`count=2, "test: verify mirror sync-on-commit"`, `TEST.md` 200 on GitHub). ✓ 6. Cleanup: Gitea repo deleted. GitHub repo delete → **403** (PAT lacks `delete_repo`) → left for manual deletion. **Findings (correct the original assumptions):** 1. **Mirror does NOT auto-create the GitHub repo** (as flagged earlier) — the GitHub repo must be pre-created; `git push` to a non-existent GitHub repo fails. 2. **Existing commits don't push on mirror-add** — configuring the mirror does not retroactively push the current HEAD; you must trigger `push_mirrors-sync` once (or make a new commit). `sync_on_commit` then handles subsequent commits automatically. 3. **`repo_mirror_push` MCP tool takes `remote_password` as a plain arg** → the PAT would land in the tool-call transcript (→ claudewatcher → brain). I deliberately used the **gitea REST API inside `op run`** instead so the PAT stayed in the subprocess. Filed a separate security issue to fix the tool's secret handling. 4. GitHub repo cleanup needs `delete_repo` scope (this PAT has `read:org, repo, workflow`). **Manual cleanup for you:** delete `github.com/mathiasb/test-mirror-flow` (my PAT couldn't — no `delete_repo`). Closing — mirror flow proven.
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mathias/gitea-mcp#19