sts-sponsors team mailing list archive
-
sts-sponsors team
-
Mailing list archive
-
Message #05235
[Merge] ~alexsander-souza/maas/+git/maas-release-tools:point_release_checks into ~maas-committers/maas/+git/maas-release-tools:main
Alexsander de Souza has proposed merging ~alexsander-souza/maas/+git/maas-release-tools:point_release_checks into ~maas-committers/maas/+git/maas-release-tools:main.
Commit message:
Add check for point releases
Requested reviews:
MAAS Committers (maas-committers)
For more details, see:
https://code.launchpad.net/~alexsander-souza/maas/+git/maas-release-tools/+merge/437533
--
Your team MAAS Committers is requested to review the proposed merge of ~alexsander-souza/maas/+git/maas-release-tools:point_release_checks into ~maas-committers/maas/+git/maas-release-tools:main.
diff --git a/maas_release_tools/scripts/release_status.py b/maas_release_tools/scripts/release_status.py
index 58c9b5f..fdf4a13 100644
--- a/maas_release_tools/scripts/release_status.py
+++ b/maas_release_tools/scripts/release_status.py
@@ -15,6 +15,7 @@ will go smoother.
from abc import ABC, abstractmethod
from argparse import ArgumentParser, FileType
import base64
+from datetime import date, timedelta
from functools import lru_cache
import glob
import json
@@ -45,16 +46,21 @@ from ..maasci import (
from ..version import get_branch_setup_version, ReleaseVersion
MAAS_SNAP_ID = "shY22YTZ3RhJJDOj0MfmShTNZTEb1Jiq"
+MAAS_TEST_DB_SNAP_ID = "idVMgkvkiKaOC8BjKlJRPUH50fvibpp8"
BUILD_ARCHS = ("amd64", "arm64", "ppc64el", "s390x")
def get_macaroon_refresh_help():
"""Get help on refreshing the macaroon that can be copied&pasted."""
+ exp_date = date.today() + timedelta(days=7)
return (
" Please refresh it:\n"
" rm -f release.macaroon\n"
- " snapcraft export-login --snaps maas,maas-test-db \\\n"
- " --acls package_release,package_access release.macaroon"
+ " snapcraft export-login \\\n"
+ " --snaps maas,maas-test-db \\\n"
+ " --acls package_release,package_access \\\n"
+ f" --expires {exp_date.isoformat()} \\\n"
+ " release.macaroon"
)
@@ -352,7 +358,9 @@ class SnapTrack(ReleaseStep):
class PPACopyMixin:
- def check_packages_copied(self, source_ppa, target_ppa):
+ def check_packages_copied(
+ self, source_ppa, target_ppa, selected: Optional[list[str]] = None
+ ):
target_packages = list(
(package.source_package_name, package.source_package_version)
for package in target_ppa.getPublishedSources(
@@ -360,9 +368,14 @@ class PPACopyMixin:
)
)
missing_packages = set()
- for package in source_ppa.getPublishedSources(
- status="Published", distro_series=self.current_series
- ):
+ published_packages = [
+ package
+ for package in source_ppa.getPublishedSources(
+ status="Published", distro_series=self.current_series
+ )
+ if selected is None or package.source_package_name in selected
+ ]
+ for package in published_packages:
name, version = (
package.source_package_name,
package.source_package_version,
@@ -375,7 +388,6 @@ class PPACopyMixin:
f"{name} {version} has not been copied"
for name, version in sorted(missing_packages)
)
- # error_message += f"\nGo to {source_ppa.web_link}/+copy-packages"
return False, error_message
else:
return True, None
@@ -427,22 +439,25 @@ class MAASPPA(ReleaseStep):
)
return True, None
+ def how_to_create_ppa(self, ppa_owner: str, ppa_name: str) -> list[str]:
+ return [
+ f"Go to https://launchpad.net/~{ppa_owner}/+activate-ppa",
+ f"Create '{ppa_name}' PPA",
+ "Click `Change Details`",
+ f"Enable the following processors: {', '.join(sorted(set(BUILD_ARCHS)))}",
+ ]
+
def fix(self, doit: bool = False) -> Tuple[bool, list[str]]:
- steps = []
if self.ppa is None:
- steps.append(
- f"Go to https://launchpad.net/~{self.ppa_owner.name}/+activate-ppa"
+ return False, self.how_to_create_ppa(
+ self.ppa_owner.name, self.ppa_name
)
- steps.append(f"Create '{self.ppa_name}' PPA")
else:
- steps.append(
- f"Go to https://launchpad.net/~{self.ppa_owner.name}/+archive/ubuntu/{self.ppa_name}/"
- )
- steps.append("Click `Change Details`")
- steps.append(
- f"Enable the following processors: {', '.join(sorted(set(BUILD_ARCHS)))}"
- )
- return False, steps
+ return False, [
+ f"Go to {self.ppa.web_link}",
+ "Click `Change Details`",
+ f"Enable the following processors: {', '.join(sorted(set(BUILD_ARCHS)))}",
+ ]
class MAASPackagePublished(MAASPPA):
@@ -517,21 +532,24 @@ class MAASPackagePublished(MAASPPA):
if self.ppa is None:
return super().fix(doit)
return False, [
- f"Check https://launchpad.net/~/+archive/ubuntu/{self.ppa_name}/+packages",
+ f"Check {self.ppa.web_link}/+packages",
]
class PackagesCopiedFromDeps(MAASPPA, PPACopyMixin):
def __init__(self, preparer):
- super().__init__(preparer, "release-preparation")
+ super().__init__(preparer, "candidate")
self.source_ppa = None
self.target_ppa = None
+ self.selected = None
@property
def title(self):
return f"Packages copied from ppa:{MAAS_USER}/latest-deps"
def check(self):
+ if not self.preparer.version.new_series:
+ self.selected = ["maas"]
try:
self.source_ppa = self.preparer.launchpad.maas.getPPAByName(
name="latest-deps"
@@ -546,12 +564,39 @@ class PackagesCopiedFromDeps(MAASPPA, PPACopyMixin):
f"ppa:{self.ppa_path} couldn't be found.",
)
else:
- return self.check_packages_copied(self.source_ppa, self.target_ppa)
+ return self.check_packages_copied(
+ self.source_ppa, self.target_ppa, self.selected
+ )
- # def fix(self, doit: bool = False) -> Tuple[bool, list[str]]:
+ def fix(self, doit: bool = False) -> Tuple[bool, list[str]]:
+ if self.source_ppa is None:
+ return False, self.how_to_create_ppa(MAAS_USER, "latest-deps")
+ if self.target_ppa is None:
+ return False, self.how_to_create_ppa(self.ppa_owner, self.ppa_name)
+ procedure = [
+ f"Go to {self.source_ppa.web_link}/+copy-packages",
+ f"Under `Packages`, in the right middle of the screen, select the `{get_ubuntu_series()}` OS series and click `Filter`",
+ f"select {self.selected or 'all'} packages",
+ "select `copy existing binaries`",
+ f"Select `{self.target_ppa.name}` as Destination PPA",
+ "Click `Copy packages`",
+ ]
+ return False, procedure
class PackagesCopiedToReleasePPA(MAASPPA, PPACopyMixin):
+ def __init__(self, preparer, ppa_type):
+ super().__init__(preparer, ppa_type)
+ self.source_ppa = None
+ self.target_ppa = None
+ self.source = None
+ self.selected = None
+ match ppa_type:
+ case "stable":
+ self.source = MAASPPA(preparer, "candidate")
+ case "candidate":
+ self.source = MAASPPA(preparer, "release-preparation")
+
@property
def title(self):
return f"Packages copied to ppa:{self.ppa_path}"
@@ -563,27 +608,45 @@ class PackagesCopiedToReleasePPA(MAASPPA, PPACopyMixin):
)
def check(self):
- sources = {
- "stable": MAASPPA(self.preparer, "candidate"),
- "candidate": MAASPPA(self.preparer, "release-preparation"),
- }
- source = sources[self.ppa_type]
+ if not self.preparer.version.new_series:
+ self.selected = ["maas"]
try:
- source_ppa = source.ppa_owner.getPPAByName(name=source.ppa_name)
+ self.source_ppa = self.source.ppa_owner.getPPAByName(
+ name=self.source.ppa_name
+ )
except NotFound:
return (
False,
f"ppa:{self.ppa_path} couldn't be found.",
)
try:
- target_ppa = self.ppa_owner.getPPAByName(name=self.ppa_name)
+ self.target_ppa = self.ppa_owner.getPPAByName(name=self.ppa_name)
except NotFound:
return (
False,
f"ppa:{self.ppa_path} couldn't be found.",
)
else:
- return self.check_packages_copied(source_ppa, target_ppa)
+ return self.check_packages_copied(
+ self.source_ppa, self.target_ppa, self.selected
+ )
+
+ def fix(self, doit: bool = False) -> Tuple[bool, list[str]]:
+ if self.source_ppa is None:
+ return False, self.how_to_create_ppa(
+ self.source.ppa_owner, self.source.name
+ )
+ if self.target_ppa is None:
+ return False, self.how_to_create_ppa(self.ppa_owner, self.ppa_name)
+ procedure = [
+ f"Go to {self.source_ppa.web_link}/+copy-packages",
+ f"Under `Packages`, in the right middle of the screen, select the `{get_ubuntu_series()}` OS series and click `Filter`",
+ f"select {self.selected or 'all'} packages",
+ "select `copy existing binaries`",
+ f"Select `{self.target_ppa.name}` as Destination PPA",
+ "Click `Copy packages`",
+ ]
+ return False, procedure
def macaroon_auth(macaroons):
@@ -629,12 +692,22 @@ class PackageBuilt(ReleaseStep):
class SnapsUploaded(ReleaseStep):
-
- snap_name = "maas"
+ def __init__(
+ self,
+ preparer: ReleasePreparer,
+ snap_name: str = "maas",
+ snap_id: str = MAAS_SNAP_ID,
+ cwd: Optional[str] = None,
+ ):
+ super().__init__(preparer, cwd)
+ self.snap_name = snap_name
+ self.snap_id = snap_id
@property
def title(self):
- return "Snaps have been built and uploaded to the store."
+ return (
+ f"Snap `{self.snap_name}` has been built and uploaded to the store"
+ )
@lru_cache(maxsize=1)
def _get_revisisions(self):
@@ -645,7 +718,7 @@ class SnapsUploaded(ReleaseStep):
# check if the snap has been uploaded, if the snap is
# already released to a channel.
res = requests.get(
- f"https://dashboard.snapcraft.io/dev/api/snaps/{MAAS_SNAP_ID}/"
+ f"https://dashboard.snapcraft.io/dev/api/snaps/{self.snap_id}/"
+ "history",
headers={
"Authorization": self.preparer.snapstore_auth,
@@ -657,14 +730,16 @@ class SnapsUploaded(ReleaseStep):
return None, auth_error
revision_map = {arch: [] for arch in BUILD_ARCHS}
for revision in res.json():
- version = revision["version"]
- if not version.startswith(self.preparer.version.deb_version):
- continue
- if not version.endswith(self.preparer.git_short_rev):
- continue
- revision_map[revision["arch"]].append(revision)
+ if self._filter_revision(revision):
+ revision_map[revision["arch"]].append(revision)
return revision_map, None
+ def _filter_revision(self, revision) -> bool:
+ version = revision["version"]
+ return version.startswith(
+ self.preparer.version.deb_version
+ ) and version.endswith(self.preparer.git_short_rev)
+
def check(self):
revision_map, error_message = self._get_revisisions()
if revision_map is None:
@@ -688,7 +763,7 @@ class SnapsUploaded(ReleaseStep):
return True, "\n".join(revision_info)
def fix(self, doit=False):
- builder = f"maas-{self.preparer.version.major}"
+ builder = f"{self.snap_name}-{self.preparer.version.major}"
steps = []
if self.preparer.launchpad.snap_builder_exist(builder):
steps.append(
@@ -698,7 +773,7 @@ class SnapsUploaded(ReleaseStep):
steps.extend(
[
f" go to https://code.launchpad.net/~{MAAS_USER}/maas/+git/maas/+ref/{self.preparer.version.major}/+new-snap",
- f" * snap recipe name: maas-{self.preparer.version.major}",
+ f" * snap recipe name: {self.snap_name}-{self.preparer.version.major}",
" * owner: maas",
f" * processors: {', '.join(BUILD_ARCHS)}",
" * Automatically build when branch changes",
@@ -711,17 +786,21 @@ class SnapsUploaded(ReleaseStep):
class SnapsInChannel(SnapsUploaded):
-
- snap_name = "maas"
-
- def __init__(self, preparer, channel):
- super().__init__(preparer)
+ def __init__(
+ self,
+ preparer: ReleasePreparer,
+ channel: str,
+ snap_name: str = "maas",
+ snap_id: str = MAAS_SNAP_ID,
+ cwd: Optional[str] = None,
+ ):
+ super().__init__(preparer, snap_name, snap_id, cwd)
self.channel = channel
self.missing_archs = []
@property
def title(self):
- return f"Snaps have been released to {self.channel}"
+ return f"Snap `{self.snap_name}` has been released to {self.channel}"
def check(self):
revision_map, error_message = self._get_revisisions()
@@ -756,12 +835,31 @@ class SnapsInChannel(SnapsUploaded):
revision["revision"] for revision in revision_map[arch]
)
steps.append(
- f"snapcraft release maas {latest_revision} {self.channel}"
+ f"snapcraft release {self.snap_name} {latest_revision} {self.channel}"
)
return False, steps
+class SnapTestDBInChannel(SnapsInChannel):
+ def __init__(
+ self,
+ preparer: ReleasePreparer,
+ channel: str,
+ cwd: Optional[str] = None,
+ ):
+ super().__init__(
+ preparer,
+ channel=channel,
+ snap_name="maas-test-db",
+ snap_id=MAAS_TEST_DB_SNAP_ID,
+ cwd=cwd,
+ )
+
+ def _filter_revision(self, revision) -> bool:
+ return True
+
+
class ReleaseTagged(ReleaseStep):
@property
def title(self):
@@ -929,7 +1027,7 @@ class MilestoneReleased(ReleaseStep):
if not self._ms_found:
return False, ["Pre-requesites check has failed, check above"]
return False, [
- f"run {os.path.dirname(sys.argv[0])}/release-manage maas release-milestone {self.preparer.version.version}'"
+ f"run {os.path.dirname(sys.argv[0])}/release-manage maas release-milestone {self.preparer.version.version}"
]
@@ -1079,6 +1177,10 @@ def main():
SnapsInChannel(preparer, snap_channel)
for snap_channel in release_version.snap_channels
],
+ *[
+ SnapTestDBInChannel(preparer, snap_channel)
+ for snap_channel in release_version.snap_channels
+ ],
PackagesCopiedToReleasePPA(preparer, "stable"),
ReleaseTagged(preparer),
MilestoneExist(preparer),
diff --git a/maas_release_tools/version.py b/maas_release_tools/version.py
index cd5fbca..e238557 100644
--- a/maas_release_tools/version.py
+++ b/maas_release_tools/version.py
@@ -30,6 +30,7 @@ class ReleaseVersion:
self.snap_channels = self._snap_channels()
self.deb_version = self.version.replace("-", "~")
self.final_version = self._final()
+ self.new_series = self.final_version.rsplit(".", 1)[1] == "0"
def _python_version(self) -> Version:
string_version = (
Follow ups