| """Adds a label to a GitLab merge requests or issues.""" |
| |
| import os |
| import sys |
| import argparse |
| import requests |
| |
| EIGEN_PROJECT_ID = 15462818 # Taken from the gitlab project page. |
| |
| |
| def add_label_to_mr(private_token: str, mr_iid: int, label: str): |
| """ |
| Adds a label to a specific merge request in a GitLab project. |
| |
| Args: |
| private_token: The user's private GitLab API token. |
| mr_iid: The internal ID (IID) of the merge request. |
| label: The label to add. |
| """ |
| api_url = ( |
| f"https://gitlab.com/api/v4/projects/{EIGEN_PROJECT_ID}/merge_requests/{mr_iid}" |
| ) |
| headers = {"PRIVATE-TOKEN": private_token} |
| # Using 'add_labels' ensures we don't overwrite existing labels. |
| payload = {"add_labels": label} |
| |
| try: |
| response = requests.put(api_url, headers=headers, json=payload) |
| response.raise_for_status() # Raises an HTTPError for bad responses (4xx or 5xx) |
| print(f"✅ Successfully added label '{label}' to Merge Request !{mr_iid}.") |
| except requests.exceptions.RequestException as e: |
| print(f"❌ Error updating Merge Request !{mr_iid}: {e}", file=sys.stderr) |
| if hasattr(e, "response") and e.response is not None: |
| print(f" Response: {e.response.text}", file=sys.stderr) |
| |
| |
| def add_label_to_issue(private_token: str, issue_iid: int, label: str): |
| """ |
| Adds a label to a specific issue in a GitLab project. |
| |
| Args: |
| private_token: The user's private GitLab API token. |
| issue_iid: The internal ID (IID) of the issue. |
| label: The label to add. |
| """ |
| api_url = ( |
| f"https://gitlab.com/api/v4/projects/{EIGEN_PROJECT_ID}/issues/{issue_iid}" |
| ) |
| headers = {"PRIVATE-TOKEN": private_token} |
| payload = {"add_labels": label} |
| |
| try: |
| response = requests.put(api_url, headers=headers, json=payload) |
| response.raise_for_status() |
| print(f"✅ Successfully added label '{label}' to Issue #{issue_iid}.") |
| except requests.exceptions.RequestException as e: |
| print(f"❌ Error updating Issue #{issue_iid}: {e}", file=sys.stderr) |
| if hasattr(e, "response") and e.response is not None: |
| print(f" Response: {e.response.text}", file=sys.stderr) |
| |
| |
| def main(): |
| """ |
| Main function to parse arguments and trigger the labelling process. |
| """ |
| parser = argparse.ArgumentParser( |
| description="Add a label to GitLab merge requests and issues.", |
| formatter_class=argparse.RawTextHelpFormatter, |
| ) |
| parser.add_argument("label", help="The label to add.") |
| parser.add_argument( |
| "--mrs", |
| nargs="+", |
| type=int, |
| help="A space-separated list of Merge Request IIDs.", |
| ) |
| parser.add_argument( |
| "--issues", nargs="+", type=int, help="A space-separated list of Issue IIDs." |
| ) |
| parser.add_argument( |
| "--gitlab_private_token", |
| help="Your GitLab private access token. \n(Best practice is to use the GITLAB_PRIVATE_TOKEN environment variable instead.)", |
| ) |
| args = parser.parse_args() |
| |
| # Prefer environment variable for the token for better security. |
| gitlab_private_token = args.gitlab_private_token or os.environ.get( |
| "GITLAB_PRIVATE_TOKEN" |
| ) |
| if not gitlab_private_token: |
| print("Error: GitLab private token not found.", file=sys.stderr) |
| print( |
| "Please provide it using the --token argument or by setting the GITLAB_PRIVATE_TOKEN environment variable.", |
| file=sys.stderr, |
| ) |
| sys.exit(1) |
| |
| if not args.mrs and not args.issues: |
| print( |
| "Error: You must provide at least one merge request (--mrs) or issue (--issues) ID.", |
| file=sys.stderr, |
| ) |
| sys.exit(1) |
| |
| print("-" * 30) |
| |
| if args.mrs: |
| print(f"Processing {len(args.mrs)} merge request(s)...") |
| for mr_iid in args.mrs: |
| add_label_to_mr(gitlab_private_token, mr_iid, args.label) |
| |
| if args.issues: |
| print(f"\nProcessing {len(args.issues)} issue(s)...") |
| for issue_iid in args.issues: |
| add_label_to_issue(gitlab_private_token, issue_iid, args.label) |
| |
| print("-" * 30) |
| print("Script finished.") |
| |
| |
| if __name__ == "__main__": |
| main() |