Skip to content

Commit 07e2bc6

Browse files
authored
Add GET /api/v1/commitfests endpoint listing all commitfests (#114)
There's no way to discover which commitfests exist. `needs_ci` returns only the two or three currently relevant ones, and `/api/v1/commitfests/<cfid>/patches` requires a cfid. This adds `GET /api/v1/commitfests` which returns every commitfest, closed and draft ones included: ```json {"commitfests": [{"id": 1, "name": "PG18-3", "status": "Closed", "draft": false, "startdate": "2024-11-01", "enddate": "2024-11-30"}, ...]} ``` This data is all already available from `/commitfest_history` and `/archive`, but those would need to be scraped, this makes the data machine-readable. Notes: - Order by ID since start dates can tie and this gives us a stable order. - No pagination because it's a small dataset. - I've exposed the 'draft' field through `CommitFest.to_json()`. This does add the key to `needs_ci`. If we'd rather be strict about that endpoint, I can build the dict inline in a new view instead.
1 parent ba38414 commit 07e2bc6

5 files changed

Lines changed: 77 additions & 0 deletions

File tree

‎.github/workflows/ci.yaml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@ jobs:
1414

1515
- name: Run ruff check
1616
uses: astral-sh/ruff-action@v2
17+
with:
18+
version: 0.15.20
1719

1820
- name: Run ruff format --check
1921
uses: astral-sh/ruff-action@v2
2022
with:
23+
version: 0.15.20
2124
args: "format --check"
2225

2326
- name: Setup Biome

‎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/models.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ def to_json(self):
106106
"id": self.id,
107107
"name": self.name,
108108
"status": self.statusstring,
109+
"draft": self.draft,
109110
"startdate": self.startdate.isoformat(),
110111
"enddate": self.enddate.isoformat(),
111112
}

‎pgcommitfest/commitfest/tests/test_apiv1.py‎

Lines changed: 67 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")
@@ -30,20 +94,23 @@ def test_needs_ci_endpoint(client, commitfests):
3094
"id": commitfests["open"].id,
3195
"name": "2025-01",
3296
"status": "Open",
97+
"draft": False,
3398
"startdate": "2025-01-01",
3499
"enddate": "2025-01-31",
35100
},
36101
"in_progress": {
37102
"id": commitfests["in_progress"].id,
38103
"name": "2024-11",
39104
"status": "In Progress",
105+
"draft": False,
40106
"startdate": "2024-11-01",
41107
"enddate": "2024-11-30",
42108
},
43109
"draft": {
44110
"id": commitfests["draft"].id,
45111
"name": "2025-03-draft",
46112
"status": "Open",
113+
"draft": True,
47114
"startdate": "2025-03-01",
48115
"enddate": "2025-03-31",
49116
},

‎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)