Skip to content

Commit

Permalink
feat: PRs are added to repo-specific projects
Browse files Browse the repository at this point in the history
  • Loading branch information
Ned Batchelder authored and nedbat committed Jan 27, 2023
1 parent 4d69314 commit 00e2711
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.. A new scriv changelog fragment.
- Added: contribution pull requests will be added to GitHub projects if the
base repo says to by adding an "openedx.org/add-to-projects" annotation in
its catalog-info.yaml file.
28 changes: 28 additions & 0 deletions docs/details.rst
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,31 @@ When a pull request is re-opened
The bot deletes the "please complete a survey" comment that was added when the
pull request was closed. The Jira issue is returned to the state it was in
when the pull request was closed.


Adding pull requests to GitHub projects
---------------------------------------

The bot will add new pull requests to GitHub projects. Projects are specified
with a string like "openedx:23" meaning `project number 23`_ in the openedx
organization.

.. _project number 23: https://github.com/orgs/openedx/projects/23

- Regular non-internal pull requests get added to the project specified in the
GITHUB_OSPR_PROJECT setting.

- Blended pull requests get added to the project specified in the
GITHUB_BLENDED_PROJECT setting.

- Individual repos can specify other projects that external non-draft pull
requests should be added to. The projects are listed in an annotation in
their catalog-info.yaml file:

.. code-block:: yaml
annotations:
# This can be multiple comma-separated projects.
openedx.org/add-to-projects: "openedx:23"
The bot never removes pull requests from projects.
38 changes: 37 additions & 1 deletion openedx_webhooks/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
from typing import Dict, Iterable, Optional, Tuple, Union

import yaml
from glom import glom
from iso8601 import parse_date

from openedx_webhooks import settings
from openedx_webhooks.lib.github.models import PrId
from openedx_webhooks.oauth import get_github_session
from openedx_webhooks.types import PrDict, PrCommentDict
from openedx_webhooks.types import GhProject, PrDict, PrCommentDict
from openedx_webhooks.utils import (
memoize,
memoize_timed,
Expand Down Expand Up @@ -357,3 +358,38 @@ def jira_project_for_blended(pr: PrDict) -> Optional[str]:
if settings.JIRA_SERVER is None:
return None
return "BLENDED"


def get_catalog_info(repo_fullname: str) -> Dict:
"""Get the parsed catalog-info.yaml data from a repo, or {} if missing."""
yml = _read_github_file(repo_fullname, "catalog-info.yaml", not_there="{}")
return yaml.safe_load(yml)


def projects_for_pr(pull_request: PrDict) -> Iterable[GhProject]:
"""
Get the projects a pull request should be added to.
Draft pull requests don't get added.
The projects are specified in an annotation in catalog-info.yaml::
metadata:
annotations:
openedx.org/add-to-projects: "openedx:23, openedx:456"
Each entry is an org:num spec for an organization project.
"""
if is_draft_pull_request(pull_request):
return set()

catalog_info = get_catalog_info(pull_request["base"]["repo"]["full_name"])
annotations = glom(catalog_info, "metadata.annotations", default={})
projects = annotations.get("openedx.org/add-to-projects", "")
gh_projects = []
if projects:
for spec in projects.split(","):
org, number = spec.strip().split(":")
gh_projects.append((org, int(number)))
return gh_projects
5 changes: 3 additions & 2 deletions openedx_webhooks/tasks/pr_tracking.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional, Set, Tuple, cast

from glom import glom

from openedx_webhooks import settings
from openedx_webhooks.bot_comments import (
BOT_COMMENT_INDICATORS,
Expand Down Expand Up @@ -49,6 +47,7 @@
is_private_repo_no_cla_pull_request,
jira_project_for_blended,
jira_project_for_ospr,
projects_for_pr,
pull_request_has_cla,
)
from openedx_webhooks.labels import (
Expand Down Expand Up @@ -299,6 +298,8 @@ def desired_support_state(pr: PrDict) -> Optional[PrDesiredInfo]:
assert settings.GITHUB_OSPR_PROJECT, "You must set GITHUB_OSPR_PROJECT"
desired.github_projects.add(settings.GITHUB_OSPR_PROJECT)

desired.github_projects.update(projects_for_pr(pr))

has_signed_agreement = pull_request_has_cla(pr)
if is_bot:
desired.cla_check = CLA_STATUS_BOT
Expand Down
11 changes: 11 additions & 0 deletions tests/repo_data/anotherorg/multi-project/catalog-info.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: 'Multi-project'
description: 'Some other thing'
annotations:
openedx.org/add-to-projects: "openedx:23, anotherorg:17"
spec:
type: 'service'
lifecycle: 'production'
owner: someone-else
22 changes: 22 additions & 0 deletions tests/repo_data/openedx/credentials/catalog-info.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# This file records information about this repo. Its use is described in OEP-55:
# https://open-edx-proposals.readthedocs.io/en/latest/processes/oep-0055-proc-project-maintainers.html
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: 'Credentials'
description: 'The Open edX Credentials Service, which supports course and program certificates.'
links:
- url: 'https://edx-credentials.readthedocs.io/'
title: 'Documentation'
icon: 'Article'
annotations:
# (Optional) Annotation keys and values can be whatever you want.
# We use it in Open edX repos to have a comma-separated list of GitHub user
# names that might be interested in changes to the architecture of this
# component.
openedx.org/arch-interest-groups: ""
openedx.org/add-to-projects: "openedx:23"
spec:
type: 'service'
lifecycle: 'production'
owner: 2U-aperture
14 changes: 14 additions & 0 deletions tests/repo_data/openedx/edx-platform/catalog-info.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# This file records information about this repo. Its use is described in OEP-55:
# https://open-edx-proposals.readthedocs.io/en/latest/processes/oep-0055-proc-project-maintainers.html

apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: 'edx-platform'
description: "the original ball of mud"
annotations:
openedx.org/arch-interest-groups: ""
spec:
owner: group:arch-bom
type: 'service'
lifecycle: 'production'
26 changes: 26 additions & 0 deletions tests/test_pull_request_opened.py
Original file line number Diff line number Diff line change
Expand Up @@ -901,3 +901,29 @@ def test_extra_fields_are_ok(fake_github, fake_jira):
assert len(pr.list_comments()) == 1
# The issue should still have the ad-hoc label.
assert "my-label" in issue.labels


def test_dont_add_internal_prs_to_project(fake_github, fake_jira):
pr = fake_github.make_pull_request(owner="openedx", repo="credentials", user="nedbat")
pull_request_changed(pr.as_json())
assert pull_request_projects(pr.as_json()) == set()


def test_add_external_prs_to_project(fake_github, fake_jira):
pr = fake_github.make_pull_request(owner="openedx", repo="credentials", user="tusbar")
pull_request_changed(pr.as_json())
assert pull_request_projects(pr.as_json()) == {settings.GITHUB_OSPR_PROJECT, ("openedx", 23)}


def test_dont_add_draft_prs_to_project(fake_github, fake_jira):
pr = fake_github.make_pull_request(owner="openedx", repo="credentials", user="tusbar", draft=True)
pull_request_changed(pr.as_json())
assert pull_request_projects(pr.as_json()) == {settings.GITHUB_OSPR_PROJECT}


def test_add_to_multiple_projects(fake_github, fake_jira):
pr = fake_github.make_pull_request(owner="anotherorg", repo="multi-project", user="tusbar")
pull_request_changed(pr.as_json())
assert pull_request_projects(pr.as_json()) == {
settings.GITHUB_OSPR_PROJECT, ("openedx", 23), ("anotherorg", 17),
}

0 comments on commit 00e2711

Please sign in to comment.