Skip to content

Commit 5ad42fb

Browse files
author
Kevin Rocker
committed
Add GET /api/v1/commitfests endpoint
There is currently no way to discover which commitfests exist. The needs_ci endpoint only returns the two or three currently relevant ones, and the patches endpoint requires a commitfest id you already know. API consumers are left enumerating ids until they get a 404, or scraping the HTML pages that already show this data. This returns every commitfest, closed and draft ones included, ordered by id. It deliberately does not use CommitFest.relevant_commitfests(), which has write side effects and can return unsaved objects. Claude-Session: https://claude.ai/code/session_01QTYvAVjc8amv58QErCwox2
1 parent 5595a50 commit 5ad42fb

3 files changed

Lines changed: 70 additions & 0 deletions

File tree

‎pgcommitfest/commitfest/apiv1.py‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ def api_response(payload, status=200, content_type="application/json"):
3636
return response
3737

3838

39+
def all_commitfests(request):
40+
"""Return all commitfests, including closed ones."""
41+
return api_response({"commitfests": list(CommitFest.objects.order_by("id"))})
42+
43+
3944
def commitfestst_that_need_ci(request):
4045
cfs = CommitFest.relevant_commitfests()
4146

‎pgcommitfest/commitfest/tests/test_apiv1.py‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,70 @@
1212
pytestmark = pytest.mark.django_db
1313

1414

15+
def test_commitfests_endpoint(client, commitfests):
16+
"""Test the /api/v1/commitfests endpoint returns all commitfests."""
17+
response = client.get("/api/v1/commitfests")
18+
19+
assert response.status_code == 200
20+
assert response["Content-Type"] == "application/json"
21+
assert response["Access-Control-Allow-Origin"] == "*"
22+
23+
data = json.loads(response.content)
24+
25+
expected = [
26+
{
27+
"id": commitfests["open"].id,
28+
"name": "2025-01",
29+
"status": "Open",
30+
"draft": False,
31+
"startdate": "2025-01-01",
32+
"enddate": "2025-01-31",
33+
},
34+
{
35+
"id": commitfests["in_progress"].id,
36+
"name": "2024-11",
37+
"status": "In Progress",
38+
"draft": False,
39+
"startdate": "2024-11-01",
40+
"enddate": "2024-11-30",
41+
},
42+
{
43+
"id": commitfests["recent_previous"].id,
44+
"name": "2024-09",
45+
"status": "Closed",
46+
"draft": False,
47+
"startdate": "2024-09-01",
48+
"enddate": "2024-09-30",
49+
},
50+
{
51+
"id": commitfests["old_previous"].id,
52+
"name": "2024-07",
53+
"status": "Closed",
54+
"draft": False,
55+
"startdate": "2024-07-01",
56+
"enddate": "2024-07-31",
57+
},
58+
{
59+
"id": commitfests["draft"].id,
60+
"name": "2025-03-draft",
61+
"status": "Open",
62+
"draft": True,
63+
"startdate": "2025-03-01",
64+
"enddate": "2025-03-31",
65+
},
66+
]
67+
68+
assert data == {"commitfests": sorted(expected, key=lambda cf: cf["id"])}
69+
70+
71+
def test_commitfests_endpoint_empty(client):
72+
"""Test the /api/v1/commitfests endpoint with no commitfests."""
73+
response = client.get("/api/v1/commitfests")
74+
75+
assert response.status_code == 200
76+
assert json.loads(response.content) == {"commitfests": []}
77+
78+
1579
def test_needs_ci_endpoint(client, commitfests):
1680
"""Test the /api/v1/commitfests/needs_ci endpoint returns correct data."""
1781
response = client.get("/api/v1/commitfests/needs_ci")

‎pgcommitfest/urls.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
urlpatterns = [
1818
re_path(r"^$", views.home),
19+
re_path(r"^api/v1/commitfests$", apiv1.all_commitfests),
1920
re_path(r"^api/v1/commitfests/needs_ci$", apiv1.commitfestst_that_need_ci),
2021
re_path(r"^api/v1/commitfests/(\d+)/patches$", apiv1.commitfest_patches),
2122
re_path(r"^api/v1/patches/(\d+)/threads$", apiv1.patch_threads),

0 commit comments

Comments
 (0)