Files
grm/scripts/configure_repo.py
T
Emil Simeonov fefddda715 GRM-20: refactor(scripts): centralize constants, API clients, and HTTP status codes
- Add shared config.py with API URLs, regexes, timeouts, pagination
- Add GiteaClient and VikunjaClient in api_clients.py with pooled sessions
- Add APIError exception for unified HTTP error handling
- Refactor all scripts to use shared modules and http.HTTPStatus
- Rewrite unit tests to mock clients and use HTTPStatus constants
- Add tests for api_clients and config modules
- Achieve 100% test coverage
2026-06-19 21:00:21 +02:00

86 lines
2.9 KiB
Python

#!/usr/bin/env python3
"""Configure GRM repository: branch protection + labels via Gitea REST API.
Usage:
GITEA_ADMIN_TOKEN=<token> python3 scripts/configure_repo.py
"""
import http
import os
from typing import cast
import click
from gitea_runner_manager.api_clients import GiteaClient
from gitea_runner_manager.config import (
BRANCH_PROTECTION_CONFIG,
GITEA_API_URL,
LABEL_CONFIG,
REPO_NAME,
REPO_OWNER,
)
from gitea_runner_manager.exceptions import APIError
from gitea_runner_manager.i18n import _
def _handle_http_error(e: APIError) -> None:
"""Raise a user-friendly Click exception for HTTP errors."""
if e.status == http.HTTPStatus.FORBIDDEN:
raise click.ClickException(
_(
"HTTP {status} Forbidden — your token lacks admin rights.\n"
"Make sure the token belongs to a repo owner or organisation admin.\n"
"Alternatively, configure branch protection manually in Settings → Branches.",
status=e.status,
)
)
raise click.ClickException(
_("HTTP error: {status}{message}", status=e.status, message=e.message)
)
def main() -> None:
token = os.environ.get("GITEA_ADMIN_TOKEN", "")
if not token:
raise click.ClickException(_("ERROR: GITEA_ADMIN_TOKEN is not set."))
client = GiteaClient(GITEA_API_URL, token, REPO_OWNER, REPO_NAME)
try:
click.echo(_("Configuring branch protection for {branch}...", branch="master"))
client.ensure_branch_protection("master", BRANCH_PROTECTION_CONFIG)
click.echo(_(" - Direct pushes: BLOCKED (require PR)"))
click.echo(
_(
" - Required approvals: {count}",
count=BRANCH_PROTECTION_CONFIG["required_approvals"],
)
)
click.echo(_(" - Dismiss stale approvals: yes"))
click.echo(_(" - Block outdated branches: yes"))
click.echo(_(" - Block rejected reviews: yes"))
checks = ", ".join(cast(list[str], BRANCH_PROTECTION_CONFIG["status_check_contexts"]))
click.echo(_(" - Required status checks: {checks}", checks=checks))
click.echo("")
label_name = cast(str, LABEL_CONFIG["name"])
click.echo(_("Creating {label} label...", label=label_name))
result = client.ensure_label(
name=cast(str, LABEL_CONFIG["name"]),
color=cast(str, LABEL_CONFIG["color"]),
description=cast(str, LABEL_CONFIG["description"]),
)
if result is None:
click.echo(_(" Label '{label}' already exists.", label=label_name))
else:
click.echo(_(" Label '{label}' created.", label=label_name))
click.echo("")
click.echo(_("Repository configuration complete."))
except APIError as e:
_handle_http_error(e)
if __name__ == "__main__": # pragma: no cover
main()