Skip to content
Open
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
89 changes: 89 additions & 0 deletions .github/workflows/require-assigned-issue.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# This action requires that any PR references an issue via GitHub's closing
# keywords (e.g. "Fixes #1234") or manual linking, and that the PR author is
# assigned to that issue. PRs that don't meet both conditions are closed
# automatically. Draft PRs are exempt until marked ready for review.
# See CONTRIBUTING.md#issues-and-assignment for the full process.
#
# This uses pull_request_target (rather than pull_request) because PRs from
# forks only get a read-only GITHUB_TOKEN under pull_request, and commenting
# on / closing the PR requires write access. The job never checks out PR
# code, only calls the GitHub API, so this is safe to do.

name: require-assigned-issue

on:
pull_request_target:
types: [opened, reopened, synchronize, edited, ready_for_review]

permissions:
contents: read

jobs:
require-assigned-issue:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
permissions:
issues: read
pull-requests: write
steps:
- name: Check for a linked, assigned issue
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
const { owner, repo } = context.repo;
const pr = context.payload.pull_request;
const author = pr.user.login;

const exemptActors = ["dependabot[bot]", "otelbot[bot]"];
if (exemptActors.includes(author)) {
return;
}

const { repository } = await github.graphql(
`query($owner: String!, $repo: String!, $number: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $number) {
closingIssuesReferences(first: 10) {
nodes {
number
assignees(first: 20) {
nodes { login }
}
}
}
}
}
}`,
{ owner, repo, number: pr.number }
);

const linkedIssues = repository.pullRequest.closingIssuesReferences.nodes;
const isAssignedToOne = linkedIssues.some((issue) =>
issue.assignees.nodes.some((assignee) => assignee.login === author)
);

if (linkedIssues.length > 0 && isAssignedToOne) {
return;
}

const contributingUrl =
"https://github.com/open-telemetry/opentelemetry-python/blob/main/CONTRIBUTING.md#issues-and-assignment";

const body =
linkedIssues.length === 0
? `Thanks for opening this PR! Every PR in this repository needs to reference an issue that has already been discussed and assigned to its author (see [CONTRIBUTING.md](${contributingUrl})).\n\nThis PR doesn't appear to be linked to an issue yet. Please open an issue describing the change (if one doesn't already exist), get assigned to it by a maintainer or approver, and link it from this PR's description (e.g. \`Fixes #1234\`).\n\nClosing for now — feel free to reopen once the above is in place.`
: `Thanks for opening this PR! It references ${linkedIssues.map((issue) => `#${issue.number}`).join(", ")}, but you aren't currently assigned to ${linkedIssues.length > 1 ? "any of those issues" : "that issue"}.\n\nPer our [contribution process](${contributingUrl}), a maintainer or approver needs to assign you to the issue before a PR is opened against it. Please ask on the issue, on [Slack](https://slack.cncf.io/), or during the Python SIG meeting, and reopen this PR once you've been assigned.`;

await github.rest.issues.createComment({
owner,
repo,
issue_number: pr.number,
body,
});

await github.rest.pulls.update({
owner,
repo,
pull_number: pr.number,
state: "closed",
});
33 changes: 33 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,39 @@ file in the package it is testing. Make sure that the file name begins with

## Pull Requests

### Issues and Assignment

Every pull request in this repository needs to be tied to an issue, and its author needs to be
assigned to that issue. The process works like this:

1. **Anyone can open an issue.** When you do, please explain what you would like to see addressed.
This gives maintainers, approvers and the rest of the community a chance to discuss the idea and
reach consensus on whether it is something we want to do, and how.
2. **Once the issue is considered valid**, an [Approver](https://github.com/open-telemetry/community/blob/main/community-membership.md#approver)
or [Maintainer](https://github.com/open-telemetry/community/blob/main/community-membership.md#maintainer)
will assign it to whoever is going to work on the corresponding pull request. If you would like
to be the one implementing it, say so on the issue, or reach out on [Slack](https://slack.cncf.io/)
or during the Python SIG meeting, and a maintainer will assign it to you.
3. **Every pull request must reference the issue it addresses**, and its author must be the
assignee of that issue. Pull requests that are opened without a referenced issue, or whose
author is not assigned to that issue, will be closed automatically. Draft pull requests opened
to help illustrate a proposal that is still being discussed on its issue are exempt from this
until they are marked ready for review.

We want to be clear that this process is not meant to discourage contributions or add unnecessary
bureaucracy — everyone is still very welcome to open issues and work on them. It exists because the
number of pull requests being generated with the help of AI coding tools has grown substantially,
and this makes it difficult for our relatively small group of maintainers and approvers to review
everything with the attention it deserves. Reaching agreement on an issue before any code is
written lets us focus our limited review time on changes the community has already agreed are
worth making.

If writing some code helps you illustrate what you have in mind, you are welcome to open a
[draft pull request](https://github.blog/2019-02-14-introducing-draft-pull-requests/) and link it
from the issue discussion, even before the issue has been assigned. It is a great way to make a
proposal concrete while it is still being discussed. Once the issue reaches consensus and is
assigned, you can mark the pull request ready for review.

### How to Structure Pull Requests

Smaller PRs get merged faster, improve review quality, and reduce the risk of conflicts. Please keep PRs small and focused:
Expand Down
Loading