Files
grm/scripts/configure_repo.py
T
emil 9c51c8b62c
CI / lint (push) Has been cancelled
CI / unit-tests (push) Has been cancelled
CI / molecule-tests (push) Has been cancelled
Post-merge Vikunja update / vikunja (push) Has been cancelled
GRM-25: feat: auto-delete branch after merge in configure_repo script
2026-06-19 21:46:45 +00:00

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