101 lines
3.8 KiB
Python
101 lines
3.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
forgejo_setup.py
|
|
----------------
|
|
Creates labels and milestones on your Forgejo repo via the API.
|
|
|
|
Usage:
|
|
python3 tools/forgejo_setup.py \
|
|
--url https://your-forgejo.example.com \
|
|
--token YOUR_API_TOKEN \
|
|
--owner YOUR_USERNAME \
|
|
--repo squadron-td
|
|
|
|
Get a token: Forgejo → Settings → Applications → Generate Token (needs repo scope).
|
|
"""
|
|
|
|
import argparse
|
|
import sys
|
|
import urllib.request
|
|
import urllib.error
|
|
import json
|
|
|
|
def api(base_url, token, method, path, body=None):
|
|
url = f"{base_url}/api/v1{path}"
|
|
data = json.dumps(body).encode() if body else None
|
|
req = urllib.request.Request(url, data=data, method=method)
|
|
req.add_header("Authorization", f"token {token}")
|
|
req.add_header("Content-Type", "application/json")
|
|
try:
|
|
with urllib.request.urlopen(req) as resp:
|
|
return json.loads(resp.read())
|
|
except urllib.error.HTTPError as e:
|
|
body = e.read().decode()
|
|
# 422 = already exists — safe to ignore
|
|
if e.code == 422:
|
|
print(f" (already exists, skipping)")
|
|
return None
|
|
print(f" ERROR {e.code}: {body}")
|
|
return None
|
|
|
|
LABELS = [
|
|
{"name": "type: feature", "color": "#0075ca"},
|
|
{"name": "type: fix", "color": "#d73a4a"},
|
|
{"name": "type: data", "color": "#e4e669"},
|
|
{"name": "type: chore", "color": "#cccccc"},
|
|
{"name": "type: docs", "color": "#0052cc"},
|
|
{"name": "scope: towers", "color": "#b60205"},
|
|
{"name": "scope: economy", "color": "#fbca04"},
|
|
{"name": "scope: waves", "color": "#006b75"},
|
|
{"name": "scope: ui", "color": "#e99695"},
|
|
{"name": "scope: ai", "color": "#c5def5"},
|
|
{"name": "scope: multiplayer","color": "#bfd4f2"},
|
|
{"name": "priority: high", "color": "#b60205"},
|
|
{"name": "priority: low", "color": "#eeeeee"},
|
|
{"name": "status: blocked", "color": "#e4e669"},
|
|
{"name": "good first issue", "color": "#7057ff"},
|
|
]
|
|
|
|
MILESTONES = [
|
|
{"title": "v0.1 — Prototype", "description": "Single lane, 1 race, 10 waves, no economy"},
|
|
{"title": "v0.2 — Economy", "description": "Workers, minerals, gas, send system"},
|
|
{"title": "v0.3 — Full Waves", "description": "All 31 waves with data-driven definitions"},
|
|
{"title": "v0.4 — All Races", "description": "4 builder races with full tower trees"},
|
|
{"title": "v0.5 — Multiplayer", "description": "2-player co-op over local network"},
|
|
{"title": "v1.0 — Release", "description": "Polished, tested, exportable build"},
|
|
]
|
|
|
|
def main():
|
|
p = argparse.ArgumentParser()
|
|
p.add_argument("--url", required=True, help="Forgejo base URL (no trailing slash)")
|
|
p.add_argument("--token", required=True, help="API token")
|
|
p.add_argument("--owner", required=True, help="Repo owner (username or org)")
|
|
p.add_argument("--repo", required=True, help="Repo name")
|
|
args = p.parse_args()
|
|
|
|
repo_path = f"/repos/{args.owner}/{args.repo}"
|
|
|
|
print("=== Creating labels ===")
|
|
for label in LABELS:
|
|
print(f" {label['name']} ...", end=" ")
|
|
result = api(args.url, args.token, "POST", f"{repo_path}/labels", label)
|
|
if result:
|
|
print(f"created (id={result['id']})")
|
|
|
|
print("\n=== Creating milestones ===")
|
|
for ms in MILESTONES:
|
|
print(f" {ms['title']} ...", end=" ")
|
|
result = api(args.url, args.token, "POST", f"{repo_path}/milestones", ms)
|
|
if result:
|
|
print(f"created (id={result['id']})")
|
|
|
|
print("\n=== Setting default branch to 'develop' ===")
|
|
result = api(args.url, args.token, "PATCH", f"{repo_path}",
|
|
{"default_branch": "develop"})
|
|
if result:
|
|
print(f" Default branch set to: {result.get('default_branch')}")
|
|
|
|
print("\nDone! Visit your repo to verify.")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|