#!/usr/bin/env python3 """Add a label to a pull request (idempotent). Commonly used to add the ``ready-to-merge`` label after CI passes and review is complete. The operation is idempotent — if the label is already attached, it succeeds without error. Usage:: # Add ready-to-merge to PR #42 python -m devx.tools.pr_label --pr 42 --label ready-to-merge # Add label to current branch's PR python -m devx.tools.pr_label --label ready-to-merge # Add multiple labels python -m devx.tools.pr_label --pr 42 --label ready-to-merge --label reviewed The repository is auto-detected from ``DEVX_REPO_OWNER`` / ``DEVX_REPO_NAME`` or ``GITHUB_REPOSITORY`` environment variables. """ from __future__ import annotations import click from dotenv import load_dotenv from devx.api_clients import GiteaClient from devx.config import GITEA_API_URL, REPO_OWNER from devx.i18n import _ from devx.tokens import get_developer_token from devx.tools.create_pr import get_repo_name from devx.tools.pr_status import _get_current_branch_pr load_dotenv() @click.command() @click.option("--pr", "pr_number", type=int, default=None, help="PR number (default: auto-detect from current branch).") @click.option("--label", "labels", multiple=True, required=True, help="Label name(s) to add (can be repeated).") @click.option("--owner", default=None, help="Repository owner (default: DEVX_REPO_OWNER).") @click.option("--repo", default=None, help="Repository name (default: DEVX_REPO_NAME or GITHUB_REPOSITORY).") def cli( pr_number: int | None, labels: tuple[str, ...], owner: str | None, repo: str | None, ) -> None: """Add one or more labels to a pull request (idempotent).""" try: token = get_developer_token() except click.ClickException: raise click.ClickException(_("CI_GITEA_TOKEN is not set.")) from None repo_owner = owner or REPO_OWNER if not repo_owner: raise click.ClickException(_("Repository owner not set. Use --owner or DEVX_REPO_OWNER env var.")) repo_name = repo or get_repo_name() client = GiteaClient(GITEA_API_URL, token, repo_owner, repo_name) if pr_number is None: pr_number = _get_current_branch_pr(client) label_list = list(labels) existing = client.get_pr_label_names(pr_number) to_add = [lbl for lbl in label_list if lbl not in existing] already = [lbl for lbl in label_list if lbl in existing] if already: for lbl in already: click.echo(_("Label '{label}' already on PR #{pr}.", label=lbl, pr=pr_number)) if to_add: client.add_pr_label(pr_number, to_add) for lbl in to_add: click.echo(_("Added label '{label}' to PR #{pr}.", label=lbl, pr=pr_number)) if __name__ == "__main__": # pragma: no cover cli() # pragma: no cover