Skip to content

Commit a3fb6f3

Browse files
committed
Undo update of spec0_action but with upstream changes
1 parent 31c3862 commit a3fb6f3

2 files changed

Lines changed: 51 additions & 54 deletions

File tree

.github/workflows/release_schedule.yaml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ on:
77
push:
88
branches:
99
- "main"
10-
pull_request:
1110
# On demand
1211
workflow_dispatch:
1312

@@ -47,9 +46,9 @@ jobs:
4746
echo "TAG_NAME=$(date '+%Y-Q%q')" >> "$GITHUB_OUTPUT"
4847
- name: Commit artifacts and create tag
4948
env:
50-
GH_TOKEN: ${{ secrets.PAT }}
49+
GH_TOKEN: ${{ secrets.RELEASE_PAT }}
5150
run: |
52-
git add schedule.md chart.md schedule.json
51+
git add -f schedule.md chart.md schedule.json
5352
git commit -m "generate schedule for ${{ steps.tag_name.outputs.TAG_NAME }} release" || echo "No changes to commit"
5453
git tag ${{ steps.tag_name.outputs.TAG_NAME }}
5554
git push origin main
@@ -58,7 +57,7 @@ jobs:
5857
- name: Publish github release
5958
uses: softprops/action-gh-release@v2
6059
env:
61-
GH_TOKEN: ${{ secrets.PAT }}
60+
GH_TOKEN: ${{ secrets.RELEASE_PAT }}
6261
with:
6362
generate_release_notes: true
6463
tag_name: ${{ steps.tag_name.outputs.TAG_NAME }}

spec0_versions.py

Lines changed: 48 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import requests
2+
import json
23
import collections
34
from datetime import datetime, timedelta
45

56
import pandas as pd
67
from packaging.version import Version, InvalidVersion
78

89

9-
py_releases = {
10+
PY_RELEASES = {
1011
"3.8": "Oct 14, 2019",
1112
"3.9": "Oct 5, 2020",
1213
"3.10": "Oct 4, 2021",
@@ -15,107 +16,93 @@
1516
"3.13": "Oct 7, 2024",
1617
"3.14": "Oct 7, 2025",
1718
}
18-
core_packages = [
19-
# Path(x).stem for x in glob("../core-projects/*.md") if "_index" not in x
20-
"numpy",
21-
"scipy",
19+
CORE_PACKAGES = [
20+
"ipython",
2221
"matplotlib",
22+
"networkx",
23+
"numpy",
2324
"pandas",
2425
"scikit-image",
25-
"networkx",
2626
"scikit-learn",
27+
"scipy",
2728
"xarray",
28-
"ipython",
2929
"zarr",
3030
]
31-
plus36 = timedelta(days=int(365 * 3))
32-
plus24 = timedelta(days=int(365 * 2))
31+
PLUS_36_MONTHS = timedelta(days=int(365 * 3))
32+
PLUS_24_MONTHS = timedelta(days=int(365 * 2))
3333

3434
# Release data
35-
36-
# put cutoff 3 quarters ago – we do not use "just" -9 month,
37-
# to avoid the content of the quarter to change depending on when we generate this
38-
# file during the current quarter.
39-
40-
current_date = pd.Timestamp.now()
41-
current_quarter_start = pd.Timestamp(
42-
current_date.year, (current_date.quarter - 1) * 3 + 1, 1
35+
# We put the cutoff at 3 quarters ago - we do not use "just" -9 months
36+
# to avoid the content of the quarter to change depending on when we
37+
# generate this file during the current quarter.
38+
CURRENT_DATE = pd.Timestamp.now()
39+
CURRENT_QUARTER_START = pd.Timestamp(
40+
CURRENT_DATE.year, (CURRENT_DATE.quarter - 1) * 3 + 1, 1
4341
)
44-
cutoff = current_quarter_start - pd.DateOffset(months=9)
42+
CUTOFF = CURRENT_QUARTER_START - pd.DateOffset(months=9)
4543

4644

47-
def get_release_dates(package, support_time=plus24):
45+
def get_release_dates(package, support_time=PLUS_24_MONTHS):
4846
releases = {}
49-
5047
print(f"Querying pypi.org for {package} versions...", end="", flush=True)
5148
response = requests.get(
5249
f"https://pypi.org/simple/{package}",
5350
headers={"Accept": "application/vnd.pypi.simple.v1+json"},
5451
).json()
5552
print("OK")
56-
5753
file_date = collections.defaultdict(list)
5854
for f in response["files"]:
55+
if f["filename"].endswith(".tar.gz") or f["filename"].endswith(".zip"):
56+
continue
5957
ver = f["filename"].split("-")[1]
6058
try:
6159
version = Version(ver)
6260
except InvalidVersion as e:
6361
print(f"Error: '{ver}' is an invalid version for '{package}'. Reason: {e}")
6462
continue
65-
6663
if version.is_prerelease or version.micro != 0:
6764
continue
68-
6965
release_date = None
7066
for format in ["%Y-%m-%dT%H:%M:%S.%fZ", "%Y-%m-%dT%H:%M:%SZ"]:
7167
try:
7268
release_date = datetime.strptime(f["upload-time"], format)
7369
except ValueError as e:
7470
print(f"Error parsing invalid date: {e}")
75-
7671
if not release_date:
7772
continue
78-
7973
file_date[version].append(release_date)
80-
8174
release_date = {v: min(file_date[v]) for v in file_date}
82-
8375
for ver, release_date in sorted(release_date.items()):
8476
drop_date = release_date + support_time
85-
if drop_date >= cutoff:
77+
if drop_date >= CUTOFF:
8678
releases[ver] = {
8779
"release_date": release_date,
8880
"drop_date": drop_date,
8981
}
90-
9182
return releases
9283

9384

9485
package_releases = {
9586
"python": {
9687
version: {
9788
"release_date": datetime.strptime(release_date, "%b %d, %Y"),
98-
"drop_date": datetime.strptime(release_date, "%b %d, %Y") + plus36,
89+
"drop_date": datetime.strptime(release_date, "%b %d, %Y") + PLUS_36_MONTHS,
9990
}
100-
for version, release_date in py_releases.items()
91+
for version, release_date in PY_RELEASES.items()
10192
}
10293
}
103-
104-
package_releases |= {package: get_release_dates(package) for package in core_packages}
105-
106-
# filter all items whose drop_date are in the past
94+
package_releases |= {package: get_release_dates(package) for package in CORE_PACKAGES}
95+
# Filter all items whose drop_date are in the past
10796
package_releases = {
10897
package: {
10998
version: dates
11099
for version, dates in releases.items()
111-
if dates["drop_date"] > cutoff
100+
if dates["drop_date"] > CUTOFF
112101
}
113102
for package, releases in package_releases.items()
114103
}
115104

116-
117105
# Save Gantt chart
118-
119106
print("Saving Mermaid chart to chart.md")
120107
with open("chart.md", "w") as fh:
121108
fh.write(
@@ -124,7 +111,6 @@ def get_release_dates(package, support_time=plus24):
124111
axisFormat %m / %Y
125112
title Support Window"""
126113
)
127-
128114
for name, releases in package_releases.items():
129115
fh.write(f"\n\nsection {name}")
130116
for version, dates in releases.items():
@@ -134,7 +120,6 @@ def get_release_dates(package, support_time=plus24):
134120
fh.write("\n")
135121

136122
# Print drop schedule
137-
138123
data = []
139124
for k, versions in package_releases.items():
140125
for v, dates in versions.items():
@@ -146,15 +131,30 @@ def get_release_dates(package, support_time=plus24):
146131
pd.to_datetime(dates["drop_date"]),
147132
)
148133
)
149-
150134
df = pd.DataFrame(data, columns=["package", "version", "release", "drop"])
151-
152135
df["quarter"] = df["drop"].dt.to_period("Q")
136+
df["new_min_version"] = (
137+
df[["package", "version", "quarter"]].groupby("package").shift(-1)["version"]
138+
)
139+
dq = df.set_index(["quarter", "package"]).sort_index().dropna()
140+
new_min_versions = (
141+
dq.groupby(["quarter", "package"]).agg({"new_min_version": "max"}).reset_index()
142+
)
153143

154-
dq = df.set_index(["quarter", "package"]).sort_index()
155-
156-
157-
print("Saving drop schedule to schedule.md")
144+
# We want to build a dict with the structure [{start_date: timestamp, packages: {package: lower_bound}}]
145+
new_min_versions_list = []
146+
for q, packages in new_min_versions.groupby("quarter"):
147+
package_lower_bounds = {
148+
p: str(v) for p, v in packages.drop("quarter", axis=1).itertuples(index=False)
149+
}
150+
# jq is really insistent the Z should be there
151+
quarter_start_time_str = str(q.start_time.isoformat()) + "Z"
152+
new_min_versions_list.append(
153+
{"start_date": quarter_start_time_str, "packages": package_lower_bounds}
154+
)
155+
print("Saving drop schedule to schedule.json")
156+
with open("schedule.json", "w") as f:
157+
f.write(json.dumps(new_min_versions_list, sort_keys=True))
158158

159159

160160
def pad_table(table):
@@ -172,7 +172,6 @@ def pad_table(table):
172172
line += f"| {str.ljust(entry, width)} "
173173
line += "|"
174174
padded_table.append(line)
175-
176175
return padded_table
177176

178177

@@ -192,7 +191,6 @@ def make_table(sub):
192191
else f"{rel_min.strftime('%b %Y')} and {rel_max.strftime('%b %Y')}"
193192
)
194193
table.append(f"|{package:<15}|{version_range:<19}|released {rel_range}|")
195-
196194
return pad_table(table)
197195

198196

@@ -204,13 +202,13 @@ def make_quarter(quarter, dq):
204202
return "\n".join(table)
205203

206204

205+
print("Saving drop schedule to schedule.md")
207206
with open("schedule.md", "w") as fh:
208-
# we collect package 6 month in the past, and drop the first quarter
207+
# We collect packages 6 month in the past, and drop the first quarter
209208
# as we might have filtered some of the packages out depending on
210209
# when we ran the script.
211210
tb = []
212211
for quarter in list(sorted(set(dq.index.get_level_values(0))))[1:]:
213212
tb.append(make_quarter(quarter, dq))
214-
215213
fh.write("\n\n".join(tb))
216214
fh.write("\n")

0 commit comments

Comments
 (0)