keycloak / keycloak/keycloak-github-bot
Upstream Issue Migration via kind/upstream-issue Label
- Dominant language
- Java
- Stars
- 9
- Forks
- 11
- Avg merge
- 2d 16h
- Merged PRs (30d)
- 2
Description
### Summary
The keycloak-github-bot should automatically migrate issues from keycloak/keycloak-private to keycloak/keycloak when the kind/upstream-issue label is applied. All migrated issues receive the priority/important label regardless of their kind (bug, cve, or enhancement).
### Problem Statement
Today, moving issues from the private repository to the public upstream is a manual process assisted by a standalone script based on the status/lift-embargo label. This workflow lives outside the bot. The trigger label name (status/lift-embargo) is also tied to the embargo/CVE workflow and doesn't clearly communicate intent when the migration is for non-security issues that simply belong in the public tracker.
### Proposed Solution
Add a new event handler to the keycloak-github-bot that reacts to the kind/upstream-issue label being applied to an issue in keycloak/keycloak-private. The bot should:
1. Trigger on kind/upstream-issue — when this label is added to an open issue in keycloak/keycloak-private, begin the migration workflow.
2. Validate before migrating (gates):
- Abort if the issue has the status/triage label.
- Abort if the issue has no area/* label.
- Abort if the issue has more than one of kind/bug, kind/cve, kind/enhancement, or none of them.
- Abort if the actor who applied kind/upstream-issue is not listed in SECURITY_OWNERS.md.
3. Create the issue in keycloak/keycloak with:
- The original title and body (appending a note that it was migrated from the private repository and by whom).
- The matching kind/* label (kind/bug, kind/cve, or kind/enhancement). From what I'm aware it is not simple to apply the Type though GitHub API, but we can try.
- All other labels from the source issue that exist in the target repo, except: kind/upstream-issue (trigger) and severity/* labels (not migrated).
4. Clean up the source issue:
- Comment on the source issue with a link to the new upstream issue, noting it was moved to the upstream repository.
- Write a comment to the original reporter providing the link to the issue. For example
```
@security reply
The issue is now tracked in the upstream #ISSUEID.
```
- Close the source issue as duplicate.
- Remove the kind/upstream-issue label.
- Lock the source issue with reason "Duplicate".
### Value & Benefits
| Benefit | Who benefits from it | Impact |
|---|---|---|
| Integrated into the bot | Maintainers, security team | No standalone scripts to maintain; same reliability and observability as other bot workflows |
| Clearer trigger semantics | Security team, maintainers | kind/upstream-issue communicates intent better than status/lift-embargo |
| Consistent prioritization | Triagers, maintainers | Every migrated issue gets priority/important, ensuring nothing falls through the cracks |
| Uniform workflow | Security team | One label handles bugs, CVEs, and enhancements the same way |
### User Stories / Scenarios
> "As a security team member, I receive a report in keycloak-private that turns out to be a non-security bug. I label it kind/upstream-issue along with kind/bug and the relevant area/* label. The bot creates the issue in keycloak/keycloak with kind/bug, priority/important, and the area labels, then closes and locks the private issue."
> "As a maintainer, I identify an enhancement request in the private repo that should be tracked publicly. I add kind/upstream-issue and kind/enhancement. The bot migrates it upstream with priority/important so it gets attention in the next triage cycle."
### Flow
```mermaid
flowchart TD
A["kind/upstream-issue label applied"] --> B{"status/triage present?"}
B -- Yes --> X1["ABORT: Blocker present"]
B -- No --> C{"Has area/* label?"}
C -- No --> X2["ABORT: Missing area label"]
C -- Yes --> D{"Exactly one kind/* label?"}
D -- No --> X3["ABORT: Multiple or missing kind labels"]
D -- Yes --> E{"Issue Type matches kind/* label?"}
E -- No --> X4["ABORT: Type mismatch"]
E -- Yes --> F{"Actor authorized?"}
F -- No --> X5["ABORT: Unauthorized actor"]
F -- Yes --> G["Create issue in keycloak/keycloak"]
G --> H["Apply kind/* + priority/important + cloned labels"]
H --> I["Set Issue Type via GraphQL"]
I --> J["Comment on source, close as duplicate, remove label, lock"]
```
### Acceptance Criteria
- Bot reacts to kind/upstream-issue label being applied in keycloak/keycloak-private
- All validation gates are enforced (triage blocker, area label, kind exclusivity, type verification, authorization via SECURITY_OWNERS.md)
- All migrated issues (bug, cve, enhancement) receive priority/important in the target repo
- Label cloning skips kind/upstream-issue, kind/* (handled explicitly), and severity/*
- Reporter receives an update with the link to the issue
- Source issue is commented with a link to the upstream issue, closed as duplicate, trigger label removed, and locked
### Out of Scope
- Changing the source/target repositories
- Modifying the authorization model (SECURITY_OWNERS.md)
- Automating the trigger (label is still applied manually by an authorized actor)
### Discussion
_No response_
### Motivation
_No response_
### Details
_No response_
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by locating the bot's label-added event handler and reviewing SECURITY_OWNERS.md, then trace the existing migration workflow or standalone script described in the issue. The work is done when validation gates, GitHub GraphQL issue-type handling, label cloning, reporter notification, source closure, label removal, and locking all match the acceptance criteria.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- github, java
- Domain
- devtools
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100