summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorDylan Baker <dylan.c.baker@intel.com>2021-01-05 11:46:49 -0800
committerMarge Bot <eric+marge@anholt.net>2021-01-07 00:07:56 +0000
commita450b4550d5d66bc9826b22a4d1435faf31a4cb2 (patch)
tree3d457ffba0f99617811b51309a6fa123c79eb3ed /bin
parentbc9e09360f824612468a8a8d34987bbf7f820b86 (diff)
bin/gen_calendar_entries: Add support for extending a release
Acked-by: Eric Engestrom <eric@engestrom.ch> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8341>
Diffstat (limited to 'bin')
-rwxr-xr-xbin/gen_calendar_entries.py68
-rw-r--r--bin/gen_calendar_entries_test.py109
2 files changed, 167 insertions, 10 deletions
diff --git a/bin/gen_calendar_entries.py b/bin/gen_calendar_entries.py
index 45562eefec8..dcf3773db77 100755
--- a/bin/gen_calendar_entries.py
+++ b/bin/gen_calendar_entries.py
@@ -113,6 +113,69 @@ def release_candidate(args: RCArguments) -> None:
commit(f'docs: Add calendar entries for {major}.{minor} release candidates.')
+def extend(args: ExtendArguments) -> None:
+ """Extend a release."""
+ @contextlib.contextmanager
+ def write_existing(writer: _csv._writer, current: typing.List[CalendarRowType]) -> typing.Iterator[CalendarRowType]:
+ """Write the orinal file, yield to insert new entries.
+
+ This is a bit clever, basically what happens it writes out the
+ original csv file until it reaches the start of the release after the
+ one we're appending, then it yields the last row. When control is
+ returned it writes out the rest of the original calendar data.
+ """
+ last_row: typing.Optional[CalendarRowType] = None
+ in_wanted = False
+ for row in current:
+ if in_wanted and row[0]:
+ in_wanted = False
+ assert last_row is not None
+ yield last_row
+ if row[0] == args.series:
+ in_wanted = True
+ if in_wanted and len(row) >= 5 and row[4] in {LAST_RELEASE.format(args.series), OR_FINAL.format(args.series)}:
+ # If this was the last planned release and we're adding more,
+ # then we need to remove that message and add it elsewhere
+ r = list(row)
+ r[4] = None
+ # Mypy can't figure this out…
+ row = typing.cast('CalendarRowType', tuple(r))
+ last_row = row
+ writer.writerow(row)
+ # If this is the only entry we can hit a case where the contextmanager
+ # hasn't yielded
+ if in_wanted:
+ yield row
+
+ current = read_calendar()
+
+ with CALENDAR_CSV.open('w') as f:
+ writer = csv.writer(f)
+ with write_existing(writer, current) as row:
+ # Get rid of -rcX as well
+ if '-rc' in row[2]:
+ first_point = int(row[2].split('rc')[-1]) + 1
+ template = '{}.0-rc{}'
+ days = 7
+ else:
+ first_point = int(row[2].split('-')[0].split('.')[-1]) + 1
+ template = '{}.{}'
+ days = 14
+
+ date = datetime.date.fromisoformat(row[1])
+ for i in range(first_point, first_point + args.count):
+ date = date + datetime.timedelta(days=days)
+ r = [None, date.isoformat(), template.format(args.series, i), row[3], None]
+ if i == first_point + args.count - 1:
+ if days == 14:
+ r[4] = LAST_RELEASE.format(args.series)
+ else:
+ r[4] = OR_FINAL.format(args.series)
+ writer.writerow(r)
+
+ commit(f'docs: Extend calendar entries for {args.series} by {args.count} releases.')
+
+
def main() -> None:
parser = argparse.ArgumentParser()
sub = parser.add_subparsers()
@@ -121,6 +184,11 @@ def main() -> None:
rc.add_argument('manager', help="the name of the person managing the release.")
rc.set_defaults(func=release_candidate)
+ ex = sub.add_parser('extend', help='Generate additional entries for a release.')
+ ex.add_argument('series', help='The series to extend, such as "29.3" or "30.0".')
+ ex.add_argument('count', type=int, help='The number of new entries to add.')
+ ex.set_defaults(func=extend)
+
args = parser.parse_args()
args.func(args)
diff --git a/bin/gen_calendar_entries_test.py b/bin/gen_calendar_entries_test.py
index 30df79d4008..70536ba0f0d 100644
--- a/bin/gen_calendar_entries_test.py
+++ b/bin/gen_calendar_entries_test.py
@@ -25,15 +25,30 @@ from __future__ import annotations
from unittest import mock
import argparse
import csv
+import contextlib
import tempfile
import os
import pathlib
+import typing
import pytest
from . import gen_calendar_entries
+@contextlib.contextmanager
+def mock_csv(data: typing.List[gen_calendar_entries.CalendarRowType]) -> typing.Iterator[None]:
+ """Replace the actual CSV data with our test data."""
+ with tempfile.TemporaryDirectory() as d:
+ c = os.path.join(d, 'calendar.csv')
+ with open(c, 'w') as f:
+ writer = csv.writer(f)
+ writer.writerows(data)
+
+ with mock.patch('bin.gen_calendar_entries.CALENDAR_CSV', pathlib.Path(c)):
+ yield
+
+
@pytest.fixture(autouse=True, scope='module')
def disable_git_commits() -> None:
"""Mock out the commit function so no git commits are made durring testing."""
@@ -81,19 +96,13 @@ class TestRC:
yield
@pytest.fixture(autouse=True)
- def mock_data(self) -> None:
+ def csv(self) -> None:
"""inject our test data.."""
- with tempfile.TemporaryDirectory() as d:
- c = os.path.join(d, 'calendar.csv')
- with open(c, 'w') as f:
- writer = csv.writer(f)
- writer.writerows(self.ORIGINAL_DATA)
-
- with mock.patch('bin.gen_calendar_entries.CALENDAR_CSV', pathlib.Path(c)):
- yield
+ with mock_csv(self.ORIGINAL_DATA):
+ yield
def test_basic(self) -> None:
- args = argparse.Namespace()
+ args: gen_calendar_entries.RCArguments = argparse.Namespace()
args.manager = "Dylan Baker"
gen_calendar_entries.release_candidate(args)
@@ -106,3 +115,83 @@ class TestRC:
actual = gen_calendar_entries.read_calendar()
assert actual == expected
+
+
+class TestExtend:
+
+ def test_one_release(self) -> None:
+ data = [
+ ('20.3', '2021-01-13', '20.3.3', 'Dylan Baker', ''),
+ ('', '2021-01-27', '20.3.4', 'Dylan Baker', 'This is the last planned release of the 20.3.x series.'),
+ ]
+
+ args: gen_calendar_entries.ExtendArguments = argparse.Namespace()
+ args.series = '20.3'
+ args.count = 2
+
+ with mock_csv(data):
+ gen_calendar_entries.extend(args)
+ actual = gen_calendar_entries.read_calendar()
+
+ expected = [
+ data[0],
+ ('', '2021-01-27', '20.3.4', 'Dylan Baker', ''),
+ ('', '2021-02-10', '20.3.5', 'Dylan Baker', ''),
+ ('', '2021-02-24', '20.3.6', 'Dylan Baker', 'This is the last planned release of the 20.3.x series.'),
+ ]
+
+ assert actual == expected
+ def test_one_release(self) -> None:
+ data = [
+ ('20.3', '2021-01-13', '20.3.3', 'Dylan Baker', ''),
+ ('', '2021-01-27', '20.3.4', 'Dylan Baker', 'This is the last planned release of the 20.3.x series.'),
+ ('21.0', '2021-01-13', '21.0.1', 'Dylan Baker', ''),
+ ('', '2021-01-27', '21.0.2', 'Dylan Baker', ''),
+ ('', '2021-02-10', '21.0.3', 'Dylan Baker', ''),
+ ('', '2021-02-24', '21.0.4', 'Dylan Baker', 'This is the last planned release of the 21.0.x series.'),
+ ]
+
+ args: gen_calendar_entries.ExtendArguments = argparse.Namespace()
+ args.series = '21.0'
+ args.count = 1
+
+ with mock_csv(data):
+ gen_calendar_entries.extend(args)
+ actual = gen_calendar_entries.read_calendar()
+
+ expected = data.copy()
+ d = list(data[-1])
+ d[-1] = ''
+ expected[-1] = tuple(d)
+ expected.extend([
+ ('', '2021-03-10', '21.0.5', 'Dylan Baker', 'This is the last planned release of the 21.0.x series.'),
+ ])
+
+ assert actual == expected
+
+ def test_rc(self) -> None:
+ data = [
+ ('20.3', '2021-01-13', '20.3.3', 'Dylan Baker', ''),
+ ('', '2021-01-27', '20.3.4', 'Dylan Baker', 'This is the last planned release of the 20.3.x series.'),
+ ('21.0', '2021-01-13', '21.0.0-rc1', 'Dylan Baker', ''),
+ ('', '2021-01-20', '21.0.0-rc2', 'Dylan Baker', gen_calendar_entries.OR_FINAL.format('21.0')),
+ ]
+
+ args: gen_calendar_entries.ExtendArguments = argparse.Namespace()
+ args.series = '21.0'
+ args.count = 2
+
+ with mock_csv(data):
+ gen_calendar_entries.extend(args)
+ actual = gen_calendar_entries.read_calendar()
+
+ expected = data.copy()
+ d = list(expected[-1])
+ d[-1] = ''
+ expected[-1] = tuple(d)
+ expected.extend([
+ ('', '2021-01-27', '21.0.0-rc3', 'Dylan Baker', ''),
+ ('', '2021-02-03', '21.0.0-rc4', 'Dylan Baker', gen_calendar_entries.OR_FINAL.format('21.0')),
+ ])
+
+ assert actual == expected