diff --git a/backend/Platform/settings/base.py b/backend/Platform/settings/base.py index b9d3fa6..89710d1 100644 --- a/backend/Platform/settings/base.py +++ b/backend/Platform/settings/base.py @@ -208,3 +208,6 @@ # Media Upload Settings MEDIA_ROOT = os.path.join(BASE_DIR, "accounts", "mediafiles") MEDIA_URL = "/media/" + +# GitHub API +GH_PERSONAL_ACCESS_TOKEN = os.environ.get("GH_PERSONAL_ACCESS_TOKEN") diff --git a/backend/Platform/urls.py b/backend/Platform/urls.py index 9d9b3c0..e66c7b6 100644 --- a/backend/Platform/urls.py +++ b/backend/Platform/urls.py @@ -12,6 +12,7 @@ path("accounts/", include("accounts.urls")), path("options/", include("options.urls", namespace="options")), path("identity/", include("identity.urls", namespace="identity")), + path("monitor/", include("monitor.urls", namespace="monitor")), path("s/", include("shortener.urls", namespace="shortener")), path( "openapi/", diff --git a/backend/monitor/__init__.py b/backend/monitor/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/monitor/apps.py b/backend/monitor/apps.py new file mode 100644 index 0000000..3b67f38 --- /dev/null +++ b/backend/monitor/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class MonitorConfig(AppConfig): + name = "monitor" diff --git a/backend/monitor/urls.py b/backend/monitor/urls.py new file mode 100644 index 0000000..4574632 --- /dev/null +++ b/backend/monitor/urls.py @@ -0,0 +1,10 @@ +from django.urls import path +from monitor.views import PullsView + + +app_name = "monitor" + + +urlpatterns = [ + path("pulls/", PullsView.as_view(), name="pulls"), +] diff --git a/backend/monitor/views.py b/backend/monitor/views.py new file mode 100644 index 0000000..5a9fbd6 --- /dev/null +++ b/backend/monitor/views.py @@ -0,0 +1,43 @@ +import requests +from django.conf import settings +from django.http.response import HttpResponse +from django.views.generic.base import View + + +PRODUCTS_TO_URL = { + "website": "pennlabs.org/", + "platform": "platform.pennlabs.org/", + "penn-clubs": "pennclubs.com/", +} + + +class PullsView(View): + """ + Returns a view displaying all PRs that have the feature-branch tag and + their status. + """ + + def get(self, request): + headers = {"Authorization": settings.GH_PERSONAL_ACCESS_TOKEN} + pulls = [] + + for product, product_url in PRODUCTS_TO_URL.items(): + url = f"https://api.github.com/repos/pennlabs/{product}/pulls" + r = requests.get(url, headers=headers) + if r.status_code != 200: + print(f"Error: Request returned status code {r.status_code}") + return + + for pull in r.json(): + if "labels" not in pull: + continue + for label in pull["labels"]: + if "name" in label and label["name"].startswith("feature-branch:"): + pulls.append( + { + "url": f"https://pr-{pull['number']}.{product_url}", + "status": label["name"].split(":")[1], + } + ) + break + return HttpResponse("
".join(str(pull) for pull in pulls)) diff --git a/backend/tests/monitor/__init__.py b/backend/tests/monitor/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/tests/monitor/test_views.py b/backend/tests/monitor/test_views.py new file mode 100644 index 0000000..aeb4185 --- /dev/null +++ b/backend/tests/monitor/test_views.py @@ -0,0 +1,12 @@ +from django.test import TestCase +from django.urls import reverse +from rest_framework.test import APIClient + + +class PullsViewTestCase(TestCase): + def setUp(self): + self.client = APIClient() + + def test_monitor_pulls(self): + resp = self.client.get(reverse("monitor:pulls")) + self.assertEqual(resp.status_code, 200, resp.content)