Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include pull requests in the lottery for the triage/stale/stewardship categories #199

Merged
merged 1 commit into from
Dec 12, 2024
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
78 changes: 39 additions & 39 deletions README.adoc
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
= Quarkus GitHub Lottery

> A Quarkus-powered GitHub App that regularly sends short lists of GitHub issues for triagers/maintainers/stewards to consider.
> A Quarkus-powered GitHub App that regularly sends short lists of GitHub issues/PRs for triagers/maintainers/stewards to consider.

[[intro]]
== Introduction

This GitHub App is based on the https://github.com/quarkiverse/quarkus-github-app[Quarkus GitHub App framework].

It periodically extracts GitHub issues from one "source" GitHub repository (e.g. https://github.com/quarkusio/quarkus)
It periodically extracts GitHub issues/PRs from one "source" GitHub repository (e.g. https://github.com/quarkusio/quarkus)
and notifies maintainers about them by commenting on GitHub issues in another "notification" GitHub repository
(e.g. https://github.com/quarkusio/quarkus-github-lottery-reports).
That second "notification" repository <<admins-install,may be private>>,
Expand All @@ -20,10 +20,10 @@ each time its sends a notification.
That way, maintainers will get daily (or weekly) reports via email,
sent by GitHub when the comment is added.

Issues are randomly assigned among eligible maintainers up to a limit they define themselves,
Issues/PRs are randomly assigned among eligible maintainers up to a limit they define themselves,
so that everyone gets a chance to help according to the time they want to invest.

There are multiple categories of issues that one can be notified about;
There are multiple categories of issues/PRs that one can be notified about;
see <<maintainers>> for more information, but here's what an email notification may look like:

image::documentation/screenshots/notification.png[Example of an email notification,align="center"]
Expand All @@ -35,7 +35,7 @@ image::documentation/screenshots/notification.png[Example of an email notificati
=== Basics

As a Quarkus triager, a Quarkus core/extension maintainer, or a Quarkus steward,
in order to get notifications about Quarkus issues on GitHub:
in order to get notifications about Quarkus issues/PRs on GitHub:

* Make sure you have access to the https://github.com/quarkusio/quarkus-github-lottery-reports["notification" repository]
if not, request access to an admin of the https://github.com/quarkusio[quarkusio] organization.
Expand Down Expand Up @@ -98,7 +98,7 @@ See below for details about each section.
[[participants-triage]]
=== Triage

If the `triage` section is present, you will get notified about issues that haven't been assigned an area yet.
If the `triage` section is present, you will get notified about Issues/PRs that haven't been assigned an area yet.

Please add an area label, remove the "needs triage" (e.g. `triage/needs-triage`) label,
and ping the relevant maintainers if necessary.
Expand All @@ -123,19 +123,19 @@ On which days you wish to get notified about triage.
+
Array of ``WeekDay``s, mandatory, no default.
`maxIssues`::
How many issues, at most, you wish to be included in the "triage" category
How many issues/PRs, at most, you wish to be included in the "triage" category
for each notification.
+
Integer, mandatory, no default.

[[participants-maintenance]]
=== Maintenance

If the `maintenance` section is present, you will get notified about issues
If the `maintenance` section is present, you will get notified about issues/PRs
related to a specific area (e.g. `area/hibernate-orm`)
that may be stalled and require intervention from maintainers or reporters.

Issues in "maintenance" notifications will be split in three categories:
Issues/PRs in "maintenance" notifications will be split in three categories:

Feedback Needed::
Issues with missing reproducer/information.
Expand All @@ -146,13 +146,13 @@ Issues with newly provided reproducer/information.
+
Please have a closer look, possibly remove the "needs feedback" (e.g. `triage/needs-reproducer`) label, and plan further work.
Stale::
Issues last updated a long time ago.
Issues or PRs last updated a long time ago.
+
Please have a closer look, re-prioritize, ping someone, label as "on ice", close the issue, ...
Please have a closer look, re-prioritize, ping someone, label as "on ice", close the issue/PR, ...

Of course, in every situation, simply continuing the conversation,
pinging someone, or even doing nothing at all are perfectly acceptable responses:
it's all up to you, and issues that don't change will reappear in another notification, a few days later.
it's all up to you, and issues/PRs that don't change will reappear in another notification, a few days later.

The `maintenance` section will look like this:

Expand All @@ -174,26 +174,26 @@ participants:
----

`labels`::
The labels identifying issues you are interested in, as a maintainer.
Issues mentioned in notifications will have at least one of these labels.
The labels identifying issues/PRs you are interested in, as a maintainer.
Issues/PRs mentioned in notifications will have at least one of these labels.
+
Array of Strings, mandatory, no default.
`days`::
On which days you wish to get notified about maintenance.
+
Array of ``WeekDay``s, mandatory, no default.
`feedback.needed.maxIssues`::
How many issues, at most, you wish to be included in the "Feedback needed" category
How many issues/PRs, at most, you wish to be included in the "Feedback needed" category
for each notification.
+
Integer, mandatory, no default.
`feedback.provided.maxIssues`::
How many issues, at most, you wish to be included in the "Feedback provided" category
How many issues/PRs, at most, you wish to be included in the "Feedback provided" category
for each notification.
+
Integer, mandatory, no default.
`stale.maxIssues`::
How many issues, at most, you wish to be included in the "Stale" category
How many issues/PRs, at most, you wish to be included in the "Stale" category
for each notification.
+
Integer, mandatory, no default.
Expand All @@ -202,17 +202,17 @@ Integer, mandatory, no default.
=== Stewardship

IMPORTANT: This section should only be of interest to stewards:
core contributors who spend significant time working on GitHub issues.
core contributors who spend significant time working on GitHub issues/PRs.
If you don't already know what this section is about,
you probably don't want to use it.

If the `stewardship` section is present, you will get notified about Issues across all areas last updated a long time ago.
If the `stewardship` section is present, you will get notified about issues or PRs across all areas last updated a long time ago.

Please have a closer look, re-prioritize, ping someone, label as "on ice", close the issue, ...
Please have a closer look, re-prioritize, ping someone, label as "on ice", close the issue/PR, ...

NOTE: Notifications to stewards are sent independently of notifications to maintainers,
so that the work of maintainers won't be affected by the work of stewards.
It is entirely possible for a maintainer to be notified about an issue
It is entirely possible for a maintainer to be notified about an issue/PR
at the same time as a steward.

The `stewardship` section will look like this:
Expand All @@ -232,7 +232,7 @@ On which days you wish to get notified about stewardship.
+
Array of ``WeekDay``s, mandatory, no default.
`maxIssues`::
How many issues, at most, you wish to be included in the "stewardship" category
How many issues/PRs, at most, you wish to be included in the "stewardship" category
for each notification.
+
Integer, mandatory, no default.
Expand All @@ -253,7 +253,7 @@ See the footnote in the notifications you receive.

Here is a link to the application on GitHub: https://github.com/apps/quarkus-github-lottery

The application needs to be installed on both the "source" repository (the one issues are extracted from)
The application needs to be installed on both the "source" repository (the one issues/PRs are extracted from)
and the "notification" repository (the one "notification" issues are added to).

IMPORTANT: For security reasons,
Expand All @@ -266,11 +266,11 @@ The "notification" repository should ideally be private:

* This repository is only about notifying maintainers, so it does not provide any useful information to anyone else.
* Making the "notification" repository public would lead to publicly visible references to notifications
in the history of "source" issues, like this:
in the history of "source" issues/PRs, like this:
+
image::documentation/screenshots/notification-reference.png[Example of references to notifications in the GitHub issue history,align="center"]
image::documentation/screenshots/notification-reference.png[Example of references to notifications in the GitHub issue/PR history,align="center"]
+
Those add clutter to the history, and might create false hopes in issue reporters
Those add clutter to the history, and might create false hopes in issue/PR submitters
("someone is actively addressing my issue!").
====

Expand Down Expand Up @@ -315,16 +315,16 @@ The full name of the GitHub repository where "reports"/"notification issues" wil
+
String, mandatory, no default.
`buckets.triage.label`::
The label identifying GitHub issues that require triage.
The label identifying GitHub issues/PRs that require triage.
+
String, mandatory, no default.
`buckets.triage.delay`::
How much time to wait after the last update on an issue
How much time to wait after the last update on an issue/PR
before including it in the lottery in the "triage" bucket.
+
String in https://en.wikipedia.org/wiki/ISO_8601#Durations[ISO-8601 duration format], mandatory, no default.
`buckets.triage.timeout`::
How much time to wait after an issue was last notified about
How much time to wait after an issue/PR was last notified about
before including it again in the lottery in the "triage" bucket.
+
String in https://en.wikipedia.org/wiki/ISO_8601#Durations[ISO-8601 duration format], mandatory, no default.
Expand Down Expand Up @@ -353,33 +353,33 @@ before including it again in the lottery in the "feedback provided" bucket.
+
String in https://en.wikipedia.org/wiki/ISO_8601#Durations[ISO-8601 duration format], mandatory, no default.
`buckets.maintenance.stale.delay`::
How much time to wait after the last update on an issue
How much time to wait after the last update on an issue/PR
before including it in the lottery in the "stale" bucket.
+
String in https://en.wikipedia.org/wiki/ISO_8601#Durations[ISO-8601 duration format], mandatory, no default.
`buckets.maintenance.stale.ignoreLabels`::
The labels identifying GitHub issues that should be ignored for the "stale" bucket.
Issues with one of these labels will never be added to the bucket.
The labels identifying GitHub issues/PRs that should be ignored for the "stale" bucket.
Issues/PRs with one of these labels will never be added to the bucket.
+
Array of Strings, optional, defaults to an empty array.
`buckets.maintenance.stale.timeout`::
How much time to wait after an issue was last notified about
How much time to wait after an issue/PR was last notified about
before including it again in the lottery in the "stale" bucket.
+
String in https://en.wikipedia.org/wiki/ISO_8601#Durations[ISO-8601 duration format], mandatory, no default.
`buckets.stewardship.delay`::
How much time to wait after the last update on an issue
How much time to wait after the last update on an issue/PR
before including it in the lottery in the "stewardship" bucket.
+
String in https://en.wikipedia.org/wiki/ISO_8601#Durations[ISO-8601 duration format], mandatory, no default.
`buckets.stewardship.timeout`::
How much time to wait after an issue was last notified about
How much time to wait after an issue/PR was last notified about
before including it again in the lottery in the "stewardship" bucket.
+
String in https://en.wikipedia.org/wiki/ISO_8601#Durations[ISO-8601 duration format], mandatory, no default.
`buckets.stewardship.ignoreLabels`::
The labels identifying GitHub issues that should be ignored for the "stewardship" bucket.
Issues with one of these labels will never be added to the bucket.
The labels identifying GitHub issues/PRs that should be ignored for the "stewardship" bucket.
Issues/PRs with one of these labels will never be added to the bucket.
+
Array of Strings, optional, defaults to an empty array.

Expand Down Expand Up @@ -413,8 +413,8 @@ follow the steps outlined in https://quarkiverse.github.io/quarkiverse-docs/quar
When registering your app, request the following Repository permissions:

* Checks - `Read & Write`: to <<config-validation,validate configuration files>>.
* Issues - `Read & Write`: to list issues that should be notified, and create "notification" issues in another repository.
* Pull Requests - `Read & Write`: to react to <<commands,comment-based commands>>.
* Issues - `Read & Write`: to list issues that should be notified, and to create "notification" issues in another repository.
* Pull Requests - `Read & Write`: to list PRs that should be notified, and to react to <<commands,comment-based commands>>.

And subscribe to the following events:

Expand Down
6 changes: 3 additions & 3 deletions src/main/java/io/quarkus/github/lottery/draw/Lottery.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ void createDraws(GitHubRepository repo, LotteryHistory lotteryHistory, List<Draw
String label = config.triage().label();
var cutoff = now.minus(config.triage().notification().delay());
var history = lotteryHistory.triage();
draws.add(triage.bucket.createDraw(repo.issuesWithLabelLastUpdatedBefore(label, Set.of(), cutoff)
draws.add(triage.bucket.createDraw(repo.issuesOrPullRequestsWithLabelLastUpdatedBefore(label, Set.of(), cutoff)
.filter(issue -> history.lastNotificationTimedOutForIssueNumber(issue.number()))
.iterator(),
allWinnings));
Expand Down Expand Up @@ -159,7 +159,7 @@ void createDraws(GitHubRepository repo, LotteryHistory lotteryHistory, List<Draw
var ignoreLabels = new LinkedHashSet<>(config.maintenance().stale().ignoreLabels());
var history = lotteryHistory.stale();
draws.add(stale.createDraw(
repo.issuesWithLabelLastUpdatedBefore(areaLabel, ignoreLabels, cutoff)
repo.issuesOrPullRequestsWithLabelLastUpdatedBefore(areaLabel, ignoreLabels, cutoff)
.filter(issue -> history.lastNotificationTimedOutForIssueNumber(issue.number()))
.iterator(),
allWinnings));
Expand All @@ -181,7 +181,7 @@ void createDraws(GitHubRepository repo, LotteryHistory lotteryHistory, List<Draw
var ignoreLabels = new LinkedHashSet<>(config.stewardship().ignoreLabels());
var history = lotteryHistory.stewardship();
draws.add(bucket.createDraw(
repo.issuesLastUpdatedBefore(ignoreLabels, cutoff)
repo.issuesOrPullRequestsLastUpdatedBefore(ignoreLabels, cutoff)
.filter(issue -> history.lastNotificationTimedOutForIssueNumber(issue.number()))
.iterator(),
allWinnings));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,17 @@ private GHRepository repository() throws IOException {
return repository;
}

private GHIssueSearchBuilder searchIssues() {
private GHIssueSearchBuilder searchIssuesOnly() {
return client().searchIssues()
.q(repo(ref))
.q(isIssue());
}

private GHIssueSearchBuilder searchIssuesOrPullRequests() {
return client().searchIssues()
.q(repo(ref));
}

private DynamicGraphQLClient graphQLClient() {
if (graphQLClient == null) {
graphQLClient = clientProvider.getInstallationGraphQLClient(ref.installationRef().installationId());
Expand All @@ -120,15 +125,15 @@ public Optional<LotteryConfig> fetchLotteryConfig() throws IOException {
}

/**
* Lists issues that were last updated before the given instant.
* Lists issues or pull requests that were last updated before the given instant.
*
* @param ignoreLabels GitHub labels. Issues assigned with any of these labels are ignored (not returned).
* @param updatedBefore An instant; all returned issues must have been last updated before that instant.
* @return A lazily populated stream of matching issues.
* @throws java.io.UncheckedIOException In case of I/O failure.
*/
public Stream<Issue> issuesLastUpdatedBefore(Set<String> ignoreLabels, Instant updatedBefore) {
var builder = searchIssues()
public Stream<Issue> issuesOrPullRequestsLastUpdatedBefore(Set<String> ignoreLabels, Instant updatedBefore) {
var builder = searchIssuesOrPullRequests()
.isOpen()
.q(updatedBefore(updatedBefore))
.sort(GHIssueSearchBuilder.Sort.UPDATED)
Expand All @@ -140,16 +145,17 @@ public Stream<Issue> issuesLastUpdatedBefore(Set<String> ignoreLabels, Instant u
}

/**
* Lists issues with the given label that were last updated before the given instant.
* Lists issues or pull requests with the given label that were last updated before the given instant.
*
* @param label A GitHub label; if non-null, all returned issues must have been assigned that label.
* @param ignoreLabels GitHub labels. Issues assigned with any of these labels are ignored (not returned).
* @param updatedBefore An instant; all returned issues must have been last updated before that instant.
* @return A lazily populated stream of matching issues.
* @throws java.io.UncheckedIOException In case of I/O failure.
*/
public Stream<Issue> issuesWithLabelLastUpdatedBefore(String label, Set<String> ignoreLabels, Instant updatedBefore) {
var builder = searchIssues()
public Stream<Issue> issuesOrPullRequestsWithLabelLastUpdatedBefore(String label, Set<String> ignoreLabels,
Instant updatedBefore) {
var builder = searchIssuesOrPullRequests()
.isOpen()
.q(label(label))
.q(updatedBefore(updatedBefore))
Expand All @@ -175,7 +181,7 @@ public Stream<Issue> issuesWithLabelLastUpdatedBefore(String label, Set<String>
*/
public Stream<Issue> issuesLastActedOnByAndLastUpdatedBefore(Set<String> initialActionLabels, String filterLabel,
IssueActionSide lastActionSide, Instant updatedBefore) {
return toStream(searchIssues()
return toStream(searchIssuesOnly()
.isOpen()
.q(anyLabel(initialActionLabels))
.q(label(filterLabel))
Expand Down Expand Up @@ -318,7 +324,7 @@ public void update(String topicSuffix, String markdownBody, boolean comment)
}

private Stream<GHIssue> getDedicatedIssues() throws IOException {
var builder = searchIssues()
var builder = searchIssuesOnly()
.q(author(appLogin()));
if (ref.assignee() != null) {
builder.q(assignee(ref.assignee()));
Expand Down
Loading
Loading