95 lines
3.2 KiB
Python
95 lines
3.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Configure GRM repository: branch protection + labels via Gitea REST API.
|
|
|
|
Usage:
|
|
REPO_TOKEN=<token> python3 scripts/configure_repo.py
|
|
"""
|
|
|
|
import http
|
|
import os
|
|
from typing import cast
|
|
|
|
import click
|
|
from dotenv import load_dotenv # pyright: ignore[reportMissingImports,reportUnknownVariableType]
|
|
|
|
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,
|
|
REPO_SETTINGS_CONFIG,
|
|
)
|
|
from gitea_runner_manager.exceptions import APIError
|
|
from gitea_runner_manager.i18n import _
|
|
|
|
load_dotenv(override=True)
|
|
|
|
|
|
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("REPO_TOKEN", "")
|
|
if not token:
|
|
raise click.ClickException(_("ERROR: REPO_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(_("Configuring repository settings..."))
|
|
client.update_repo_settings(cast(dict[str, object], REPO_SETTINGS_CONFIG))
|
|
click.echo(_(" - Auto-delete branch after merge: yes"))
|
|
|
|
click.echo("")
|
|
click.echo(_("Repository configuration complete."))
|
|
except APIError as e:
|
|
_handle_http_error(e)
|
|
|
|
|
|
if __name__ == "__main__": # pragma: no cover
|
|
main() # pragma: no cover
|