feat(gitea): create Renovate labels for a new repo
This commit is contained in:
@@ -17,4 +17,30 @@ newproject ~/projects/my-thing --parts backend,frontend,caddy --backend python -
|
||||
|
||||
One part alone is rendered at the root of the project; two parts live in `backend/` and `frontend/`. After rendering, `make env` creates `.env` and every `docker-compose.override.yml` from their examples. `updateproject` needs a clean working tree and commits each part's update separately, so the next part starts from a clean tree again; conflicts stay in those commits for you to resolve. Templates are cloned from `https://git.kotikot.com/templates` unless `TEMPLATES_DIR` points at a directory with local checkouts; `TEMPLATES_REF=HEAD` renders their working trees instead of the latest tag.
|
||||
|
||||
## Renovate
|
||||
|
||||
A new repo needs the `renovate`, `wait-3d` and `deps-code` labels before the bot
|
||||
ever runs against it: Renovate fails on a label that does not exist, and until
|
||||
today these were created by hand for every repo.
|
||||
|
||||
```sh
|
||||
giteaproject ms-agents/my-thing
|
||||
```
|
||||
|
||||
Then drop a `renovate.jsonc` into the repo root with nothing but the shared
|
||||
preset:
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": ["local>templates/renovate"]
|
||||
}
|
||||
```
|
||||
|
||||
**Extending the preset does not subscribe the repo to anything.** The bot walks
|
||||
an explicit list, so the repo also has to be added to `repositories` in
|
||||
`projects/personal/renovate/renovate-config.js` of `infra/komodo`, and the
|
||||
`renovate` team of its organization needs write access to it. Miss that step and
|
||||
the config sits there doing nothing, silently.
|
||||
|
||||
Requires `uv`; `bun`, `docker` and `pre-commit` are used by the generated projects.
|
||||
|
||||
@@ -6,3 +6,4 @@ fi
|
||||
|
||||
newproject() { uv run --script "$TEMPLATES_HOME/templates.py" new "$@"; }
|
||||
updateproject() { uv run --script "$TEMPLATES_HOME/templates.py" update "$@"; }
|
||||
giteaproject() { uv run --script "$TEMPLATES_HOME/templates.py" gitea "$@"; }
|
||||
|
||||
@@ -112,6 +112,58 @@ def update(args: argparse.Namespace) -> None:
|
||||
print(f"committed {file.stem} update")
|
||||
|
||||
|
||||
GITEA = os.environ.get("GITEA_URL", "https://git.kotikot.com").rstrip("/")
|
||||
RENOVATE_LABELS = [
|
||||
("renovate", "1f6feb", "Pull request from the Renovate bot"),
|
||||
("wait-3d", "d29922", "Waits three days: the registry has no release timestamp, the age gate merges it"),
|
||||
("deps-code", "7d8590", "Code dependencies: pull requests are collected, nothing merges itself"),
|
||||
]
|
||||
|
||||
|
||||
def gitea_token() -> str:
|
||||
token = os.environ.get("GITEA_TOKEN", "")
|
||||
if token:
|
||||
return token
|
||||
path = Path.home() / ".config/gitea/token"
|
||||
if path.exists():
|
||||
return path.read_text(encoding="utf-8").strip()
|
||||
sys.exit("no Gitea token: set GITEA_TOKEN or write ~/.config/gitea/token")
|
||||
|
||||
|
||||
def gitea(args: argparse.Namespace) -> None:
|
||||
"""Prepare a Gitea repo for Renovate: the labels it fails without."""
|
||||
import json
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
|
||||
token = gitea_token()
|
||||
for name, color, description in RENOVATE_LABELS:
|
||||
body = json.dumps({"name": name, "color": color, "description": description}).encode()
|
||||
request = urllib.request.Request(
|
||||
f"{GITEA}/api/v1/repos/{args.repo}/labels",
|
||||
data=body,
|
||||
method="POST",
|
||||
headers={"Authorization": f"token {token}", "Content-Type": "application/json"},
|
||||
)
|
||||
try:
|
||||
urllib.request.urlopen(request, timeout=30)
|
||||
print(f"label {name}: created")
|
||||
except urllib.error.HTTPError as error:
|
||||
if error.code in (409, 422):
|
||||
print(f"label {name}: already there")
|
||||
else:
|
||||
sys.exit(f"label {name}: {error.code} {error.read()[:200]!r}")
|
||||
|
||||
print(
|
||||
"\nLabels done. Two things are still manual, and neither happens by itself:\n"
|
||||
f" 1. renovate.jsonc in {args.repo} with"
|
||||
' {"extends": ["local>templates/renovate"]}\n'
|
||||
" 2. the repo added to `repositories` in renovate-config.js of infra/komodo,\n"
|
||||
" plus the bot given write access to it. Extending the preset subscribes\n"
|
||||
" nothing: the bot only visits repos named in that list."
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(prog="templates")
|
||||
sub = parser.add_subparsers(dest="command", required=True)
|
||||
@@ -130,6 +182,9 @@ def main() -> None:
|
||||
u.add_argument("--ask", action="store_true", help="ask every question again")
|
||||
u.add_argument("--defaults", action="store_true")
|
||||
u.set_defaults(func=update)
|
||||
g = sub.add_parser("gitea", help="Create the Renovate labels a repo needs")
|
||||
g.add_argument("repo", help="org/name on Gitea")
|
||||
g.set_defaults(func=gitea)
|
||||
args = parser.parse_args()
|
||||
args.func(args)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user