Files
claude-foundations/claude/source-control.md
Paul O'Reilly 091fae73e8 Pre-flight: check ssh-add -l before asking user to load a key
Keys are often pre-loaded. Added explicit check-first guidance and
a note to use grep -i (case-insensitive) — a case-sensitive grep
will silently miss keys whose comments use different capitalisation.
2026-07-18 11:00:52 +12:00

50 lines
2.9 KiB
Markdown

# Source Control
## Hosts and orgs
- All projects on **Gitea** (`gitea.oreillyit.nz`) as primary remote — prefer this hostname over `gitea.homelab.internal` (same instance, the public name enables external access)
- Migrate existing remotes from `gitea.homelab.internal` to `gitea.oreillyit.nz` when convenient
- **`skynet`** org: AI-focused projects. Owned by `ai_enablement`.
- **`homelab`** org: infrastructure projects (cluster-bootstrap, etc.). Owned by `cluster-administrator`.
- **`oreillyit`** org: non-AI internal O'Reilly IT tools. Owned by `ai_enablement`.
- Optionally push-mirror to GitHub for public visibility.
## SSH aliases
Pattern: `gitea.oreillyit.nz-<username>`.
- `gitea.oreillyit.nz-homelab` → authenticates as `cluster-administrator` (key: `~/.ssh/gitea-cluster-admin`)
- `gitea.oreillyit.nz-ai-enablement` → authenticates as `ai_enablement` (key: `~/.ssh/gitea.ai-enablement`)
- `gitea.oreillyit.nz-accelerators` → (key: `~/.ssh/gitea.accelerators.2026`)
Git remote URL format: `git@gitea.oreillyit.nz-<user>:<org>/<repo>.git`
- Example: `git@gitea.oreillyit.nz-ai-enablement:skynet/custom-claude-skills.git`
## SSH agent pre-flight
Before the first push of a session:
1. Derive the alias: `git remote get-url origin` — the host segment is the SSH alias.
2. Run `ssh-add -l` and read the **full output**. Keys are often pre-loaded — check before asking. Use `grep -i <keyname>` (case-insensitive) to find the relevant entry; a case-sensitive grep will miss keys whose comments use different capitalisation.
3. If the key is present, proceed. Only ask the user to `ssh-add ~/.ssh/<keyfile>` if it is genuinely absent. Claude cannot answer a passphrase prompt.
4. Confirm auth: `ssh -T git@<alias>` — expect a Gitea welcome message.
In non-interactive contexts (CI, container agents, unattended loops), use `GIT_SSH_COMMAND='ssh -o BatchMode=yes' git push` so a missing credential fails fast instead of hanging on a passphrase prompt.
## Push failure recovery
| Symptom | Likely cause |
|---|---|
| `Permission denied (publickey)` | Key not loaded, or wrong alias in remote URL |
| Push hangs silently | Passphrase prompt in non-interactive context — use `BatchMode=yes` |
| 403 after API-created repo | SSH user not added as collaborator — add via Gitea UI or API |
Commit locally first, surface the failure explicitly, and never end a session with finished work unpushed and unmentioned. Record the recovery step in CONTEXT.md.
## Working rules
- **Always pull before planning work** — run `git pull --ff-only` when entering a project. Work may have been pushed from another machine or by container agents. If the pull fails (diverged history, uncommitted changes), warn the user before proceeding.
- Meaningful commit messages; prefer small, focused commits over large batches.
- Enable pre-commit hooks where appropriate (secret detection, linting, formatting).
- Never commit secrets in plaintext — use SOPS + age or equivalent encryption.