feat: add mirror_refs.sh for bidirectional ref syncing
- mirror_refs.sh: additive branch+tag mirroring between dadeschools (HTTPS) and prgs (SSH:2222). Dry-run default, --apply to execute, --force for diverged branches. Uses bare repo cache for isolation. - test_mirror_refs.py: flag parsing, safety defaults, brace-delimited refspec validation, and local bare-repo integration tests (FF detection, branch/tag comparison). - README.md: document mirror_refs.sh, test suite, and multi-instance auth.
This commit is contained in:
@@ -11,20 +11,23 @@ A collection of Python and Bash scripts to automate interactions with Gitea inst
|
||||
|
||||
## Authentication
|
||||
|
||||
These scripts securely extract tokens from the macOS keychain to avoid hardcoding secrets.
|
||||
Scripts extract credentials from the macOS keychain automatically — no tokens on the command line.
|
||||
|
||||
Credentials are retrieved via `git credential fill` for the target host. Ensure you have
|
||||
logged in via Git over HTTPS at least once so the keychain caches your credentials.
|
||||
- **dadeschools** — HTTPS via `git credential fill` (SSH:2222 is flaky)
|
||||
- **prgs** — SSH via `ssh://git@gitea-ssh.prgs.cc:2222` (SSH is reliable here)
|
||||
|
||||
Ensure you've logged in via Git over HTTPS at least once so the keychain caches your credentials.
|
||||
|
||||
## Available Scripts
|
||||
|
||||
| Script | Description |
|
||||
|---------------------|-----------------------------------------------------|
|
||||
| `create_issue.py` | Create an issue (`--remote`, `--title`, `--body`) |
|
||||
| `create_pr.py` | Open a Pull Request (`--remote`, `--title`, `--head`, `--base`) |
|
||||
| `close_issue.sh` | Close a specific issue (dadeschools only) |
|
||||
| `mark_issue.sh` | Claim/release an issue via `status:in-progress` label |
|
||||
| `manage_labels.py` | Create label set and apply label mappings (`--dry` to preview) |
|
||||
| Script | Description |
|
||||
|---------------------|--------------------------------------------------------------------|
|
||||
| `create_issue.py` | Create an issue (`--remote`, `--title`, `--body`, `--body-file`) |
|
||||
| `create_pr.py` | Open a Pull Request (`--remote`, `--title`, `--head`, `--base`) |
|
||||
| `close_issue.sh` | Close a specific issue (dadeschools only) |
|
||||
| `mark_issue.sh` | Claim/release an issue via `status:in-progress` label |
|
||||
| `manage_labels.py` | Create label set and apply label mappings (`--dry` to preview) |
|
||||
| `mirror_refs.sh` | Mirror branches + tags between dadeschools ⇄ prgs |
|
||||
|
||||
### Quick Examples
|
||||
|
||||
@@ -32,6 +35,9 @@ logged in via Git over HTTPS at least once so the keychain caches your credentia
|
||||
# Create an issue
|
||||
./create_issue.py --title "Fix PDF output" --body "Blank on Safari"
|
||||
|
||||
# Create an issue on the prgs instance
|
||||
./create_issue.py --remote prgs --title "Add tests" --body-file description.md
|
||||
|
||||
# Create a PR
|
||||
./create_pr.py --title "feat: add validation" --head feat/validation --body "Closes #12"
|
||||
|
||||
@@ -43,6 +49,41 @@ logged in via Git over HTTPS at least once so the keychain caches your credentia
|
||||
|
||||
# Release when done
|
||||
./mark_issue.sh 10 done
|
||||
|
||||
# Mirror refs (dry-run by default)
|
||||
./mirror_refs.sh
|
||||
|
||||
# Actually push the refs
|
||||
./mirror_refs.sh --apply
|
||||
```
|
||||
|
||||
Use `--help` on any Python script for full usage details.
|
||||
Use `--help` on any Python script or shell script for full usage details.
|
||||
|
||||
## Mirror Refs
|
||||
|
||||
`mirror_refs.sh` keeps branches and tags in sync between dadeschools and prgs:
|
||||
|
||||
- **Additive only** — never deletes branches or tags
|
||||
- **Dry-run by default** — pass `--apply` to actually push
|
||||
- **Divergence protection** — shared branches that have diverged are skipped with a warning; pass `--force` to override
|
||||
- Uses a bare repo cache in `/tmp/gitea-mirror-Timesheet` for isolation
|
||||
- Won't auto-close or merge anything — just ref mirroring
|
||||
|
||||
## Tests
|
||||
|
||||
Run the full test suite:
|
||||
|
||||
```bash
|
||||
python3 -m pytest tests/ -v
|
||||
```
|
||||
|
||||
| Test file | Covers |
|
||||
|--------------------------|---------------------------------------------------------|
|
||||
| `test_create_issue.py` | Arg parsing, remote resolution, payload, auth, errors |
|
||||
| `test_create_pr.py` | Arg parsing, remote resolution, payload, auth, errors |
|
||||
| `test_credentials.py` | `get_credentials()` parsing edge cases |
|
||||
| `test_manage_labels.py` | Label create/skip, dry run, mapping, constant validation|
|
||||
| `test_shell_scripts.py` | `close_issue.sh` + `mark_issue.sh` arg validation |
|
||||
| `test_mirror_refs.py` | Flags, safety defaults, local integration tests |
|
||||
|
||||
All tests mock network and keychain access — no real API calls are made.
|
||||
|
||||
Reference in New Issue
Block a user