Agrega gitea_skill: skill para operar Gitea self-hosted (scripts API BOM-safe + push headless sin persistir token, SKILL/TOOLS/api-index). Actualiza CLAUDE.md, README.md, .env.example.
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
# Gitea — Tooling
|
||||
|
||||
All commands assume PowerShell from the project root. Load env first:
|
||||
|
||||
```powershell
|
||||
. .\.env.local.ps1
|
||||
```
|
||||
|
||||
Required env vars (in `.env.local.ps1`, gitignored):
|
||||
|
||||
- `GITEA_URL` — base URL, e.g. `https://gitea-hjwh0svsoo9p5w5kj2j6b1bd.urieljareth.org`.
|
||||
- `GITEA_USER` — auth user (informational; `GITEA_TOKEN` encodes the identity).
|
||||
- `GITEA_TOKEN` — app token with `read:repository`, `write:repository`,
|
||||
`read:user` scopes (generate at `$GITEA_URL/user/settings/applications`).
|
||||
|
||||
## Smoke test
|
||||
|
||||
```powershell
|
||||
.\gitea_skill\scripts\Test-GiteaConnection.ps1
|
||||
```
|
||||
|
||||
Calls `/version`, `/user`, `/settings/api`, `/repos/search`. Exits 1 on any
|
||||
FAIL — gate operational work on this.
|
||||
|
||||
## Read-only
|
||||
|
||||
```powershell
|
||||
# Who am I?
|
||||
.\gitea_skill\scripts\Invoke-GiteaApi.ps1 -Path "/user"
|
||||
|
||||
# List visible repos
|
||||
.\gitea_skill\scripts\Get-GiteaRepo.ps1 -List
|
||||
|
||||
# Get one repo (owner defaults to auth user)
|
||||
.\gitea_skill\scripts\Get-GiteaRepo.ps1 -Name Proxmox-Coolify-Manager
|
||||
.\gitea_skill\scripts\Get-GiteaRepo.ps1 -Owner urieljareth -Name MP-Manager
|
||||
|
||||
# Search
|
||||
.\gitea_skill\scripts\Get-GiteaRepo.ps1 -Search manager
|
||||
|
||||
# Branches + tags
|
||||
.\gitea_skill\scripts\Invoke-GiteaApi.ps1 -Path "/repos/urieljareth/MP-Manager/branches"
|
||||
.\gitea_skill\scripts\Invoke-GiteaApi.ps1 -Path "/repos/urieljareth/MP-Manager/tags"
|
||||
```
|
||||
|
||||
## Create a repo (idempotent)
|
||||
|
||||
```powershell
|
||||
.\gitea_skill\scripts\New-GiteaRepo.ps1 -Name my-app -Description "demo" [-Private] [-NoAutoInit]
|
||||
```
|
||||
|
||||
If the repo already exists, prints its URL and returns the existing object
|
||||
(no failure). `-NoAutoInit` skips the Gitea-side README so you can push an
|
||||
existing local history without conflicts.
|
||||
|
||||
## Push a local repo to Gitea (headless, token NOT persisted)
|
||||
|
||||
```powershell
|
||||
.\gitea_skill\scripts\Sync-GiteaRemote.ps1 `
|
||||
-AppPath .\my-app `
|
||||
-Name my-app `
|
||||
-RemoteName gitea `
|
||||
-CreateIfMissing [-Private] [-Force]
|
||||
```
|
||||
|
||||
What it does:
|
||||
|
||||
1. Ensures `urieljareth/<Name>` exists (creates if `-CreateIfMissing`).
|
||||
2. Adds (or updates) the `gitea` remote with the **clean** HTTPS URL — **no
|
||||
token in `.git/config`**.
|
||||
3. Pushes the current branch with a **one-shot** `http.extraHeader=Authorization:
|
||||
token <T>` and a blanked `credential.helper`. The token never reaches disk.
|
||||
|
||||
`-RemoteName gitea` (default) coexists with a GitHub `origin`. To replace an
|
||||
existing `origin` that already points at Gitea (as in this manager repo),
|
||||
pass `-RemoteName origin`.
|
||||
|
||||
### If you prefer wincred for interactive pushes (one-time)
|
||||
|
||||
```powershell
|
||||
cmdkey /generic:"git:$env:GITEA_URL" /user:"$env:GITEA_USER" /pass:"$env:GITEA_TOKEN"
|
||||
```
|
||||
|
||||
After that, plain `git push` works. The skill scripts do NOT require this —
|
||||
they work headlessly out of the box.
|
||||
|
||||
## Low-level API
|
||||
|
||||
```powershell
|
||||
# GET
|
||||
.\gitea_skill\scripts\Invoke-GiteaApi.ps1 -Path "/repos/urieljareth/MP-Manager/releases"
|
||||
|
||||
# POST with body
|
||||
$body = @{ name = "v1.0.0"; tag_name = "v1.0.0" } | ConvertTo-Json -Compress
|
||||
.\gitea_skill\scripts\Invoke-GiteaApi.ps1 -Method POST `
|
||||
-Path "/repos/urieljareth/MP-Manager/releases" -BodyJson $body
|
||||
|
||||
# Raw (status + headers + body string)
|
||||
.\gitea_skill\scripts\Invoke-GiteaApi.ps1 -Path "/user" -Raw
|
||||
```
|
||||
|
||||
`Invoke-GiteaApi.ps1` uses `curl.exe --data-binary @<tmpfile>` (UTF-8 no BOM)
|
||||
so Gitea's JSON parser never trips on a BOM — same pattern as
|
||||
`Invoke-GitHubApi.ps1`.
|
||||
|
||||
## Commands that always require confirmation
|
||||
|
||||
- Creating a repo (`New-GiteaRepo.ps1` warns if it already exists).
|
||||
- Any `git push` (`Sync-GiteaRemote.ps1` asks unless `-Force`).
|
||||
- Any Gitea `POST`/`PATCH`/`DELETE` (repo, release, hook, branch protection).
|
||||
- Mirror/migrate operations.
|
||||
- Deleting a repo (no Coolify-side recycle bin — data is gone).
|
||||
|
||||
`-Force` skips the interactive prompts. Use only after manually reviewing the plan.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Likely cause | Fix |
|
||||
|---------|--------------|-----|
|
||||
| `GITEA_TOKEN not set` | `.env.local.ps1` not loaded | `. .\.env.local.ps1` |
|
||||
| `401`/`403` on writes | Token lacks `write:repository` | Regenerate token with the right scope at `$GITEA_URL/user/settings/applications` |
|
||||
| `invalid character '\u00ef'` | Body sent with a BOM | Already handled by `Invoke-GiteaApi.ps1` (uses `[IO.File]::WriteAllText` no-BOM); do not switch to `Set-Content -Encoding utf8` |
|
||||
| `git push` prompts for credentials | The one-shot header was overridden by a stored helper | The script blanks `credential.helper` for the push; if you configured wincred manually, that's fine too. If a different helper intercepts, run from a clean shell. |
|
||||
| `404` creating repo under an org | Org does not exist or token lacks access | Create the org first at `$GITEA_URL/org/create` |
|
||||
| Cloudflare 5xx on Gitea URL | Tunnel routing or the Gitea container is down | `coolify_skill/scripts/Get-CoolifyDockerStatus.ps1 -Filter gitea`; tunnel is dashboard-managed, see `docs/runbooks/cloudflare-tunnel.md` |
|
||||
Reference in New Issue
Block a user