Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Python
__pycache__/
*.py[cod]
*$py.class
.venv/
venv/
ENV/
env/
.env
.venv

# Node
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# IDE / Editor
.idea/
.vscode/
*.suo
*.ntvs*
*.njsproj
*.sln
*.swp
*~

# OS files
.DS_Store
Thumbs.db
118 changes: 118 additions & 0 deletions org-tools/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# GitHub Label Synchronization Tool

A local Python CLI utility to synchronize label configurations from central YAML files to GitHub organization repositories.

Note that this script only changes the Label name/color/description and avoids any manipulation of label assignment to issues or pull requests.

---

## 📝 Configuration Format

Each YAML configuration file expects a list of label objects:

```yaml
- name: "type/bug"
color: "d73a4a"
description: "Something is broken or not working as expected"
aliases:
- "bug"
- "defect"
```

### Fields:

- **`name`** (Required): The final target name for the label on GitHub.
- **`color`** (Required): A 6-character hex code without a leading `#` (e.g., `"d73a4a"`).
- **`description`** (Optional): A short description of the label.
- **`aliases`** (Optional): A list of previous names. If found, the tool will perform an in-place rename to the target `name` on GitHub, preserving all existing Issue/PR assignments.
Comment thread
pemamian marked this conversation as resolved.

> **Conflict Validation Policy:**
>
> | Config Scenario | Example Case | Result |
> | :--------------------- | :----------------------------------------------------------- | :----------------------------------- |
> | **Duplicate Names** | Label `bug` in File A and Label `bug` in File B | ❌ **Forbidden** (Duplicate Error) |
> | **Name-Alias Overlap** | Label `type/bug` has Alias `bug`, AND Label `bug` is defined | ❌ **Forbidden** (Conflict Error) |
> | **Shared Aliases** | Label `type/bug` and `defect` both have Alias `issue` | ❌ **Forbidden** (Conflict Error) |
> | **Cyclic Redirects** | Label A has alias B, Label B has alias A | ❌ **Forbidden** (Cyclic Loop Error) |

### 🔄 In-Place Label Renaming Example

If you want to rename an existing label (e.g., from `bug` to `type/bug`) without losing any of the issues or PRs currently associated with it:

1. Define the new target **`name`** (e.g. `type/bug`) that does not exist already.
2. Add the old label name (e.g. `bug`) inside the **`aliases`** list:

```yaml
- name: "type/bug"
color: "d73a4a"
description: "Something is broken or not working as expected"
aliases:
- "bug"
```

**How it works under the hood:**

- **If `type/bug` does NOT exist in the repository, but `bug` DOES exist:** The script will rename `bug` to `type/bug` in-place. All issues and pull requests previously tagged with `bug` will now be automatically tagged with `type/bug`!
- **If `type/bug` ALREADY exists in the repository:** The script will update `type/bug` (color/description) to match your configuration. However, to prevent destructive API failures, it **will not** automatically delete `bug`.
- **What to do if BOTH exist on GitHub:**
This script does not support merging labels because of destructive side effects.
If both `bug` and `type/bug` already exist, the rename call is safely skipped to prevent API errors. If you want to merge them:
1. In GitHub, filter issues by `label:bug`, select all, and bulk-add the `type/bug` label.
2. Go to GitHub's repository label settings and manually delete the old `bug` label.
This will prevent any accidental merge of labels which could have sever consequences on underlying issues or pull requests.

> [!NOTE]
> **Why this safe approach?**
> By keeping this transition explicit and avoiding automated destructive merges or deletions, the tool guarantees that no label configurations are merged by accident in the future if configuration files are modified or copy-pasted incorrectly. This safety mechanism is specifically designed to safeguard your data when both the new standardized label and the old alias label already exist and have active issues or pull requests assigned to them.

---

## 🚀 Running the CLI

This tool is designed to run easily with **`uv`**, which handles dependencies automatically.

### 🔑 Prerequisites (Token Permissions)

Before running the tool, ensure you have a [GitHub Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) (`--token`) with proper access to the organization and its repositories to manage labels.

### 1. Dry Run (Preview Changes)

By default, the tool runs in Dry-Run mode to preview operations safely without making live changes:

```bash
uv run org-tools/sync_labels.py \
--token "YOUR_GITHUB_TOKEN" \
Comment thread
pemamian marked this conversation as resolved.
--org "YOUR_ORGANIZATION" \
--repos "demo-repository"
```

### 2. Targeting Specific Repositories (Filter)

Use the `--repos` flag to specify which repositories to sync, or `--all-repos` with `--exclude-repos` to filter specific ones out:

```bash
# Sync specific repositories
uv run org-tools/sync_labels.py \
--token "YOUR_GITHUB_TOKEN" \
--org "YOUR_ORGANIZATION" \
--repos "repo-a,repo-b" \
--apply

# Sync all repositories except excluded ones
uv run org-tools/sync_labels.py \
--token "YOUR_GITHUB_TOKEN" \
--org "YOUR_ORGANIZATION" \
--all-repos \
--exclude-repos ".github,sandbox" \
--apply
```

---

## 🧪 Running Unit Tests Offline

To run the offline test suite:

```bash
uv run org-tools/test_sync_labels.py
```
55 changes: 55 additions & 0 deletions org-tools/labels/general-labels.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
- name: bug
color: "d73a4a"
description: Something isn't working

- name: dependencies
color: "0366d6"
description: Pull requests that update a dependency file

- name: devops
color: "eb376c"

- name: documentation
color: "0075ca"
description: Improvements or additions to documentation

- name: duplicate
color: "cfd3d7"
description: This issue or pull request already exists

- name: enhancement
color: "a2eeef"
description: New feature or request

- name: github_actions
color: "000000"
description: Pull requests that update GitHub Actions code

- name: governance
color: "7dd2d6"

- name: payments
color: "2504F2"

- name: python:uv
color: "2b67c6"
description: Pull requests that update python:uv code

- name: question
color: "d876e3"
description: Further information is requested

- name: TC review
Comment thread
pemamian marked this conversation as resolved.
color: "88b91e"
description: Ready for TC review

- name: Triage
Comment thread
pemamian marked this conversation as resolved.
color: "f1d66a"

- name: WIP
Comment thread
pemamian marked this conversation as resolved.
color: "d5854f"

- name: wontfix
color: "ffffff"
description: This will not be worked on
39 changes: 39 additions & 0 deletions org-tools/labels/triage-labels.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
- name: status:needs-triage
color: "FBCA04"
Comment thread
pemamian marked this conversation as resolved.
description: Signal that the PR is ready for human triage

- name: status:under-review
color: "1D76DB"

- name: status:stale-review
color: "6F7A8A"
description: Applied if a PR is waiting on a reviewer for too long

- name: status:blocked
color: "D93F0B"

- name: status:ready-to-merge
color: "0E8A16"
description: Signaling to the DevOps team that it can be safely merged

- name: status:stale
color: "6F7A8A"
description: Applied when PR is waiting for author response for 30 days

- name: status:merged
color: "6F42C1"
description: Signifies PR completion and provides visibility for reporting

- name: area:payments
color: "0052CC"

- name: gov:needs-tc-review
color: "D93F0B"

- name: gov:needs-gc-review
color: "FDE5BE"

- name: gov:approved
color: "C2E0C6"
description: Triggers the final code ownership checks
Loading
Loading