From 48fee2fdae8011f266395aaadf1700899fe91ca7 Mon Sep 17 00:00:00 2001 From: Linostar Date: Mon, 30 Sep 2024 14:39:06 +0300 Subject: [PATCH 01/25] Do not build/release/test/scan tracks with expired end-of-life values (#241) --- src/image/prepare_single_image_build_matrix.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/image/prepare_single_image_build_matrix.py b/src/image/prepare_single_image_build_matrix.py index 09cecc66..f94dfa6a 100755 --- a/src/image/prepare_single_image_build_matrix.py +++ b/src/image/prepare_single_image_build_matrix.py @@ -106,10 +106,9 @@ def validate_image_trigger(data: dict) -> None: # set an output as a marker for later knowing if we need to release if "release" in builds[img_number]: - min_eol = datetime.strptime( - min(v["end-of-life"] for v in builds[img_number]["release"].values()), - "%Y-%m-%dT%H:%M:%SZ", - ).replace(tzinfo=timezone.utc) + min_eol = datetime.strptime(min( + v["end-of-life"] for v in builds[img_number]["release"].values() + ), "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=timezone.utc) if min_eol < datetime.now(timezone.utc): print("Track skipped because it reached its end of life") del builds[img_number] From c39b5de6c808bd0d2a6e0455f6c40af07bfc97be Mon Sep 17 00:00:00 2001 From: Anas Husseini Date: Wed, 13 Nov 2024 10:27:36 +0200 Subject: [PATCH 02/25] fix import --- src/docs/generate_oci_doc_yaml.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/docs/generate_oci_doc_yaml.py b/src/docs/generate_oci_doc_yaml.py index 5853d3cc..ea4de057 100755 --- a/src/docs/generate_oci_doc_yaml.py +++ b/src/docs/generate_oci_doc_yaml.py @@ -13,6 +13,7 @@ import sys import tempfile from typing import Any, Dict, List +from datetime import datetime, timezone from dateutil import parser import boto3 From 30a259dc9bcacfa77df0046f37a9525ee4ab6677 Mon Sep 17 00:00:00 2001 From: linostar Date: Wed, 13 Nov 2024 12:47:19 +0000 Subject: [PATCH 03/25] ci: automatically update oci/mock-rock/_releases.json, from https://github.com/canonical/oci-factory/actions/runs/11817397670 --- oci/mock-rock/_releases.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/oci/mock-rock/_releases.json b/oci/mock-rock/_releases.json index be106187..4ae973ca 100644 --- a/oci/mock-rock/_releases.json +++ b/oci/mock-rock/_releases.json @@ -35,31 +35,31 @@ "1.1-22.04": { "end-of-life": "2025-05-01T00:00:00Z", "candidate": { - "target": "677" + "target": "701" }, "beta": { - "target": "677" + "target": "701" }, "edge": { - "target": "677" + "target": "701" } }, "1-22.04": { "end-of-life": "2025-05-01T00:00:00Z", "candidate": { - "target": "677" + "target": "701" }, "beta": { - "target": "677" + "target": "701" }, "edge": { - "target": "677" + "target": "701" } }, "1.2-22.04": { "end-of-life": "2025-05-01T00:00:00Z", "beta": { - "target": "678" + "target": "702" }, "edge": { "target": "1.2-22.04_beta" From f75a0f0b1263f3bfd2f78fb7e578f5409829f5d5 Mon Sep 17 00:00:00 2001 From: Anas Husseini Date: Thu, 14 Nov 2024 09:50:15 +0200 Subject: [PATCH 04/25] cherry-pick changes to generate_oci_doc_yaml --- src/docs/generate_oci_doc_yaml.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/docs/generate_oci_doc_yaml.py b/src/docs/generate_oci_doc_yaml.py index ea4de057..90e00842 100755 --- a/src/docs/generate_oci_doc_yaml.py +++ b/src/docs/generate_oci_doc_yaml.py @@ -268,6 +268,11 @@ def build_releases_data( eol = parser.parse(all_tracks[track_base]) release_data["support"] = {"until": eol.strftime("%m/%Y")} + if eol > datetime.now(timezone.utc): + release_data["deprecated"] = { + "date": eol.strftime("%m/%Y") + } + releases.append(release_data) return releases From b4423a5174278cb1c7670590650a283e3fc4cc70 Mon Sep 17 00:00:00 2001 From: linostar Date: Thu, 14 Nov 2024 08:02:07 +0000 Subject: [PATCH 05/25] ci: automatically update oci/mock-rock/_releases.json, from https://github.com/canonical/oci-factory/actions/runs/11832900511 --- oci/mock-rock/_releases.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/oci/mock-rock/_releases.json b/oci/mock-rock/_releases.json index 4ae973ca..d4f1726f 100644 --- a/oci/mock-rock/_releases.json +++ b/oci/mock-rock/_releases.json @@ -35,31 +35,31 @@ "1.1-22.04": { "end-of-life": "2025-05-01T00:00:00Z", "candidate": { - "target": "701" + "target": "705" }, "beta": { - "target": "701" + "target": "705" }, "edge": { - "target": "701" + "target": "705" } }, "1-22.04": { "end-of-life": "2025-05-01T00:00:00Z", "candidate": { - "target": "701" + "target": "705" }, "beta": { - "target": "701" + "target": "705" }, "edge": { - "target": "701" + "target": "705" } }, "1.2-22.04": { "end-of-life": "2025-05-01T00:00:00Z", "beta": { - "target": "702" + "target": "706" }, "edge": { "target": "1.2-22.04_beta" From 4d1fae1b3f426066c8dc9286c6d946679600f44a Mon Sep 17 00:00:00 2001 From: Anas Husseini Date: Thu, 14 Nov 2024 10:30:20 +0200 Subject: [PATCH 06/25] fix a typo in comparison --- src/docs/generate_oci_doc_yaml.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/docs/generate_oci_doc_yaml.py b/src/docs/generate_oci_doc_yaml.py index 90e00842..7ed2f412 100755 --- a/src/docs/generate_oci_doc_yaml.py +++ b/src/docs/generate_oci_doc_yaml.py @@ -268,7 +268,7 @@ def build_releases_data( eol = parser.parse(all_tracks[track_base]) release_data["support"] = {"until": eol.strftime("%m/%Y")} - if eol > datetime.now(timezone.utc): + if eol < datetime.now(timezone.utc): release_data["deprecated"] = { "date": eol.strftime("%m/%Y") } From 5229a718e619f8a67f66ac240572fd6573057933 Mon Sep 17 00:00:00 2001 From: linostar Date: Thu, 14 Nov 2024 08:42:14 +0000 Subject: [PATCH 07/25] ci: automatically update oci/mock-rock/_releases.json, from https://github.com/canonical/oci-factory/actions/runs/11833455469 --- oci/mock-rock/_releases.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/oci/mock-rock/_releases.json b/oci/mock-rock/_releases.json index d4f1726f..2cc35b9f 100644 --- a/oci/mock-rock/_releases.json +++ b/oci/mock-rock/_releases.json @@ -35,31 +35,31 @@ "1.1-22.04": { "end-of-life": "2025-05-01T00:00:00Z", "candidate": { - "target": "705" + "target": "709" }, "beta": { - "target": "705" + "target": "709" }, "edge": { - "target": "705" + "target": "709" } }, "1-22.04": { "end-of-life": "2025-05-01T00:00:00Z", "candidate": { - "target": "705" + "target": "709" }, "beta": { - "target": "705" + "target": "709" }, "edge": { - "target": "705" + "target": "709" } }, "1.2-22.04": { "end-of-life": "2025-05-01T00:00:00Z", "beta": { - "target": "706" + "target": "710" }, "edge": { "target": "1.2-22.04_beta" From f6df920eaf2008cd597c146cdfdf5f7adfc141cd Mon Sep 17 00:00:00 2001 From: Anas Husseini Date: Thu, 14 Nov 2024 17:03:00 +0200 Subject: [PATCH 08/25] fix overwriting eol when it is already set --- src/image/release.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/image/release.py b/src/image/release.py index 0adf81ef..87459409 100755 --- a/src/image/release.py +++ b/src/image/release.py @@ -77,11 +77,18 @@ for risk, value in risks.dict(exclude_none=True).items(): if risk in ["end-of-life", "end_of_life"]: - all_releases[track]["end-of-life"] = value + # Only set 'end-of-life' if it hasn't been set already + if "end-of-life" not in all_releases[track]: + all_releases[track]["end-of-life"] = value + else: + print( + f"Track {track} already has an end-of-life date " + f"({all_releases[track]['end-of-life']}), so it is not overwritten." + ) continue if risk not in KNOWN_RISKS_ORDERED: - print(f"Skipping unkown risk {risk} in track {track}") + print(f"Skipping unknown risk {risk} in track {track}") continue all_releases[track][risk] = {"target": value} From a101cb5b11368c54faac1e87a6e638f25213a46f Mon Sep 17 00:00:00 2001 From: linostar Date: Thu, 14 Nov 2024 15:14:32 +0000 Subject: [PATCH 09/25] ci: automatically update oci/mock-rock/_releases.json, from https://github.com/canonical/oci-factory/actions/runs/11839846167 --- oci/mock-rock/_releases.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/oci/mock-rock/_releases.json b/oci/mock-rock/_releases.json index 2cc35b9f..7fc62d3b 100644 --- a/oci/mock-rock/_releases.json +++ b/oci/mock-rock/_releases.json @@ -35,31 +35,31 @@ "1.1-22.04": { "end-of-life": "2025-05-01T00:00:00Z", "candidate": { - "target": "709" + "target": "735" }, "beta": { - "target": "709" + "target": "735" }, "edge": { - "target": "709" + "target": "735" } }, "1-22.04": { "end-of-life": "2025-05-01T00:00:00Z", "candidate": { - "target": "709" + "target": "735" }, "beta": { - "target": "709" + "target": "735" }, "edge": { - "target": "709" + "target": "735" } }, "1.2-22.04": { "end-of-life": "2025-05-01T00:00:00Z", "beta": { - "target": "710" + "target": "736" }, "edge": { "target": "1.2-22.04_beta" From cc3c1637c3c9c6d3a1f2eaaa7b3693926039fc34 Mon Sep 17 00:00:00 2001 From: Anas Husseini Date: Fri, 15 Nov 2024 08:55:19 +0200 Subject: [PATCH 10/25] update EOLs from upload dict in image.yaml --- src/image/release.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/image/release.py b/src/image/release.py index 87459409..21750524 100755 --- a/src/image/release.py +++ b/src/image/release.py @@ -77,14 +77,7 @@ for risk, value in risks.dict(exclude_none=True).items(): if risk in ["end-of-life", "end_of_life"]: - # Only set 'end-of-life' if it hasn't been set already - if "end-of-life" not in all_releases[track]: - all_releases[track]["end-of-life"] = value - else: - print( - f"Track {track} already has an end-of-life date " - f"({all_releases[track]['end-of-life']}), so it is not overwritten." - ) + all_releases[track]["end-of-life"] = value continue if risk not in KNOWN_RISKS_ORDERED: @@ -96,6 +89,16 @@ print(f"Channel {tag} points to {value}") tag_mapping_from_trigger[tag] = value +# update EOL dates from upload dictionary +for upload in image_trigger.upload or []: + for track, upload_release_dict in (upload.release or {}).items(): + if track not in all_releases: + print(f"Track {track} will be created for the 1st time") + all_releases[track] = {} + + if upload_release_dict and upload_release_dict.end_of_life: + all_releases[track]["end-of-life"] = upload_release_dict.end_of_life + print( "Going to update channels according to the following:\n" f"{json.dumps(tag_mapping_from_trigger, indent=2)}" From 29c4dd3f3a72fac3eea72ccfa8d67f92cc20b65d Mon Sep 17 00:00:00 2001 From: linostar Date: Fri, 15 Nov 2024 07:07:43 +0000 Subject: [PATCH 11/25] ci: automatically update oci/mock-rock/_releases.json, from https://github.com/canonical/oci-factory/actions/runs/11851716382 --- oci/mock-rock/_releases.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/oci/mock-rock/_releases.json b/oci/mock-rock/_releases.json index 7fc62d3b..d753bfb4 100644 --- a/oci/mock-rock/_releases.json +++ b/oci/mock-rock/_releases.json @@ -21,7 +21,7 @@ "edge": { "target": "654" }, - "end-of-life": "2025-05-01T00:00:00Z" + "end-of-life": "2024-05-01T00:00:00Z" }, "test": { "beta": { @@ -35,31 +35,31 @@ "1.1-22.04": { "end-of-life": "2025-05-01T00:00:00Z", "candidate": { - "target": "735" + "target": "743" }, "beta": { - "target": "735" + "target": "743" }, "edge": { - "target": "735" + "target": "743" } }, "1-22.04": { "end-of-life": "2025-05-01T00:00:00Z", "candidate": { - "target": "735" + "target": "743" }, "beta": { - "target": "735" + "target": "743" }, "edge": { - "target": "735" + "target": "743" } }, "1.2-22.04": { "end-of-life": "2025-05-01T00:00:00Z", "beta": { - "target": "736" + "target": "744" }, "edge": { "target": "1.2-22.04_beta" From 1ae8a441f27f991e3fcff2342dd2f8a3359da333 Mon Sep 17 00:00:00 2001 From: Anas Husseini Date: Fri, 15 Nov 2024 09:43:28 +0200 Subject: [PATCH 12/25] merge and solve conflicts --- oci/mock-rock/_releases.json | 6 +- .../prepare_single_image_build_matrix.py | 304 ++++++++++++------ 2 files changed, 208 insertions(+), 102 deletions(-) diff --git a/oci/mock-rock/_releases.json b/oci/mock-rock/_releases.json index d753bfb4..8e8cb4f4 100644 --- a/oci/mock-rock/_releases.json +++ b/oci/mock-rock/_releases.json @@ -13,13 +13,13 @@ }, "1.0-22.04": { "candidate": { - "target": "654" + "target": "737" }, "beta": { - "target": "654" + "target": "737" }, "edge": { - "target": "654" + "target": "737" }, "end-of-life": "2024-05-01T00:00:00Z" }, diff --git a/src/image/prepare_single_image_build_matrix.py b/src/image/prepare_single_image_build_matrix.py index f94dfa6a..175c2f51 100755 --- a/src/image/prepare_single_image_build_matrix.py +++ b/src/image/prepare_single_image_build_matrix.py @@ -4,11 +4,73 @@ from datetime import datetime, timezone import glob import json -import os import pydantic import yaml - -from utils.schema.triggers import ImageSchema +from typing import Any +from pathlib import Path +from git import Repo +from tempfile import TemporaryDirectory as tempdir +from copy import deepcopy +import logging + + +from ..uploads.infer_image_track import get_base_and_track +from ..shared.github_output import GithubOutput +from .utils.schema.triggers import ImageSchema +from .utils.schema.revision_data import RevisionDataSchema + +# TODO: +# - inject_metadata uses a static github url, does this break builds that are sourced +# from non-gh repos? + +parser = argparse.ArgumentParser() +parser.add_argument( + "--oci-path", + help="Local path to the image's folder hosting the image.yaml file", + type=Path, + required=True, +) +parser.add_argument( + "--revision-data-dir", + help="Path where to save the revision data files for each build", + type=Path, + required=True, +) +parser.add_argument( + "--next-revision", + help="Next revision number", + type=int, + default=1, +) +parser.add_argument( + "--infer-image-track", + help="Infer the track corresponding to the releases", + action="store_true", + default=False, +) + + +class RevisionDataSchemaFilter(RevisionDataSchema): + """A subclass of RevisionDataSchema to prepare data for serialization.""" + + model_config = pydantic.ConfigDict(extra="ignore") + + @pydantic.model_validator(mode="before") + def _warn_extra_fields(cls, data: Any) -> Any: + for extra_field in data.keys() - cls.model_fields.keys(): + logging.warning( + f'Field "{extra_field}" removed from {data["name"]} revision data' + ) + + return data + + +class AmbiguousConfigFileError(Exception): + """Raised when multiple trigger image.y*ml files are found.""" + + +class InvalidSchemaError(Exception): + """Raised when image.yaml schema is found.""" def validate_image_trigger(data: dict) -> None: @@ -18,114 +80,158 @@ def validate_image_trigger(data: dict) -> None: _ = ImageSchema(**data) - return None +def is_track_eol(track_value: str, track_name: str | None = None) -> bool: + """Test if track is EOL, or still valid. Log warning if track_name is provided.""" + eol_date = datetime.strptime( + track_value["end-of-life"], + "%Y-%m-%dT%H:%M:%SZ", + ).replace(tzinfo=timezone.utc) + is_eol = eol_date < datetime.now(timezone.utc) -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument( - "--oci-path", - help="Local path to the image's folder hosting the image.yaml file", - required=True, - ) - parser.add_argument( - "--revision-data-dir", - help="Path where to save the revision data files for each build", - required=True, - ) - parser.add_argument( - "--next-revision", - help="Next revision number", - default=1, - ) - parser.add_argument( - "--infer-image-track", - help="Infer the track corresponding to the releases", - action="store_true", - default=False, - ) + if is_eol and track_name is not None: + logging.warning(f'Removing EOL track "{track_name}", EOL: {eol_date}') - args = parser.parse_args() + return is_eol + + +def filter_eol_tracks(build: dict[str, Any]) -> dict[str, Any]: + """Filter EOL tracks from build.""" + build["release"] = { + key: value + for key, value in build["release"].items() + if not is_track_eol(value, track_name=f"{key}:{build['name']}") + } + + return build + + +def filter_eol_builds(builds: list[dict[str, Any]]) -> list[dict[str, Any]]: + """Remove any builds with no tracks specified.""" + # remove any end of life tracks + builds = [filter_eol_tracks(build) for build in builds] + + return [build for build in builds if len(build["release"])] - image_trigger_file = glob.glob(f"{args.oci_path}/image.y*ml")[0] - print(f"Generating build matrix for {image_trigger_file}") +def write_revision_data(data_dir: Path, build: dict[str, Any]): + """Prepare and dump revision data from build dict. Ignore any fields not included in RevisionDataSchema""" + revision_data = RevisionDataSchemaFilter(**build) + with open(data_dir / str(build["revision"]), "w", encoding="UTF-8") as fh: + fh.write(revision_data.model_dump_json(by_alias=True)) + + +def locate_trigger_yaml(oci_path: Path) -> Path: + """Locate image trigger file if that is image.yaml or image.yml""" + + oci_path_yaml_files = glob.glob(str(oci_path / "image.y*ml")) + + if len(oci_path_yaml_files) == 0: + raise FileNotFoundError(f"image.y*ml not found in {oci_path}") + elif len(oci_path_yaml_files) > 1: + raise AmbiguousConfigFileError( + f"More than one image.y*ml not found in {oci_path}" + ) + + return Path(oci_path_yaml_files[0]) + + +def load_trigger_yaml(oci_path: Path) -> dict[str, Any]: + """Load image trigger file (image.yaml) located in oci_path directory.""" + image_trigger_file = locate_trigger_yaml(oci_path) + with open(image_trigger_file, encoding="UTF-8") as bf: image_trigger = yaml.load(bf, Loader=yaml.BaseLoader) - try: - validate_image_trigger(image_trigger) - except pydantic.error_wrappers.ValidationError as err: - raise Exception(f"Bad schema for {image_trigger_file}") from err - builds = image_trigger.get("upload", []) + try: + validate_image_trigger(image_trigger) + except pydantic.ValidationError as err: + raise InvalidSchemaError(f"Bad schema for {image_trigger_file}") from err + + return image_trigger - release_to = "true" if "release" in image_trigger else "" - img_number = 0 +def write_github_output( + release_to: bool, builds: list[dict[str, Any]], revision_data_dir: Path +): + """Write script result to GITHUB_OUTPUT.""" + outputs = { + "build-matrix": {"include": builds}, + "release-to": release_to, + "revision-data-dir": str(revision_data_dir), + } + with GithubOutput() as github_output: + github_output.write(**outputs) + + +def inject_metadata(builds: list[dict[str, Any]], next_revision: int, oci_path: Path): + """Inject additional metadata (name, path, revision, directory, dir_identifier, + track, base) into build dicts. + """ + _builds = deepcopy(builds) + # inject some extra metadata into the matrix data - while img_number < len(builds): - builds[img_number]["name"] = args.oci_path.rstrip("/").split("/")[-1] - builds[img_number]["path"] = args.oci_path - builds[img_number]["revision"] = img_number + int(args.next_revision) - - if args.infer_image_track: - import sys - - sys.path.append("src/") - from git import Repo - from tempfile import TemporaryDirectory as tempdir - from uploads.infer_image_track import get_base_and_track - - with tempdir() as d: - url = f"https://github.com/{builds[img_number]['source']}.git" - repo = Repo.clone_from(url, d) - repo.git.checkout(builds[img_number]["commit"]) - # get the base image from the rockcraft.yaml file - with open( - f"{d}/{builds[img_number]['directory']}/rockcraft.yaml", - encoding="UTF-8", - ) as rockcraft_file: - rockcraft_yaml = yaml.load(rockcraft_file, Loader=yaml.BaseLoader) - - base_release, track = get_base_and_track(rockcraft_yaml) - builds[img_number]["track"] = track - builds[img_number]["base"] = f"ubuntu:{base_release}" - - with open( - f"{args.revision_data_dir}/{builds[img_number]['revision']}", - "w", - encoding="UTF-8", - ) as data_file: - json.dump(builds[img_number], data_file) + for img_number, build in enumerate(_builds): + build["name"] = str(oci_path).rstrip("/").split("/")[-1] + build["path"] = str(oci_path) + + # used in setting the path where the build info is saved + build["revision"] = img_number + int(next_revision) # Add dir_identifier to assemble the cache key and artefact path # No need to write it to rev data file since it's only used in matrix - builds[img_number]["dir_identifier"] = ( - builds[img_number]["directory"].rstrip("/").replace("/", "_") - ) + build["dir_identifier"] = build["directory"].rstrip("/").replace("/", "_") + + with tempdir() as d: + url = f"https://github.com/{build['source']}.git" + repo = Repo.clone_from(url, d) + repo.git.checkout(build["commit"]) + # get the base image from the rockcraft.yaml file + with open( + f"{d}/{build['directory']}/rockcraft.yaml", + encoding="UTF-8", + ) as rockcraft_file: + rockcraft_yaml = yaml.load(rockcraft_file, Loader=yaml.BaseLoader) + + base_release, track = get_base_and_track(rockcraft_yaml) + build["track"] = track + build["base"] = f"ubuntu:{base_release}" - # set an output as a marker for later knowing if we need to release - if "release" in builds[img_number]: - min_eol = datetime.strptime(min( - v["end-of-life"] for v in builds[img_number]["release"].values() - ), "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=timezone.utc) - if min_eol < datetime.now(timezone.utc): - print("Track skipped because it reached its end of life") - del builds[img_number] - continue - else: - release_to = "true" - # the workflow GH matrix has a problem parsing nested JSON dicts - # so let's remove this field since we don't need it for the builds - builds[img_number]["release"] = "true" - else: - builds[img_number]["release"] = "" - - img_number += 1 - - matrix = {"include": builds} - print(f"{args.oci_path} - build matrix:\n{json.dumps(matrix, indent=4)}") - with open(os.environ["GITHUB_OUTPUT"], "a") as gh_out: - print(f"build-matrix={matrix}", file=gh_out) - print(f"release-to={release_to}", file=gh_out) - print(f"revision-data-dir={args.revision_data_dir}", file=gh_out) + return _builds + + +def main(): + """Executed when script is called directly.""" + args = parser.parse_args() + + # locate and load image.yaml + image_trigger = load_trigger_yaml(args.oci_path) + + # extract builds to upload + builds = image_trigger.get("upload", []) + + # inject additional meta data into builds + builds = inject_metadata(builds, args.next_revision, args.oci_path) + + # remove any builds without valid tracks + builds = filter_eol_builds(builds) + + # pretty print builds + logging.info( + f"Generating matrix for following builds: \n {json.dumps(builds, indent=4)}" + ) + + for build in builds: + write_revision_data(args.revision_data_dir, build) + + # the workflow GH matrix has a problem parsing nested JSON dicts + # so let's remove this field since we don't need it for the builds + del build["release"] + + release_to = "true" if "release" in image_trigger else "" + + write_github_output(release_to, builds, args.revision_data_dir) + + +if __name__ == "__main__": + main() From 1594b0abf3d90b19260f286aab9c0490747ebf21 Mon Sep 17 00:00:00 2001 From: Anas Husseini Date: Fri, 15 Nov 2024 09:59:35 +0200 Subject: [PATCH 13/25] fix after merge --- src/image/release.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/image/release.py b/src/image/release.py index 3b938189..9c18b5fb 100755 --- a/src/image/release.py +++ b/src/image/release.py @@ -95,14 +95,14 @@ tag_mapping_from_trigger[tag] = value # update EOL dates from upload dictionary -for upload in image_trigger.upload or []: - for track, upload_release_dict in (upload.release or {}).items(): +for upload in image_trigger["upload"] or []: + for track, upload_release_dict in (upload["release"] or {}).items(): if track not in all_releases: print(f"Track {track} will be created for the 1st time") all_releases[track] = {} - if upload_release_dict and upload_release_dict.end_of_life: - all_releases[track]["end-of-life"] = upload_release_dict.end_of_life + if upload_release_dict and upload_release_dict.get("end_of_life"): + all_releases[track]["end-of-life"] = upload_release_dict["end_of_life"] print( "Going to update channels according to the following:\n" From 502ebd5688cbef2a93a4ec30c70971169a4f7ac1 Mon Sep 17 00:00:00 2001 From: linostar Date: Fri, 15 Nov 2024 08:31:20 +0000 Subject: [PATCH 14/25] ci: automatically update oci/mock-rock/_releases.json, from https://github.com/canonical/oci-factory/actions/runs/11852716014 --- oci/mock-rock/_releases.json | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/oci/mock-rock/_releases.json b/oci/mock-rock/_releases.json index 3db1d718..165eca2d 100644 --- a/oci/mock-rock/_releases.json +++ b/oci/mock-rock/_releases.json @@ -13,15 +13,15 @@ }, "1.0-22.04": { "candidate": { - "target": "737" + "target": "751" }, "beta": { - "target": "737" + "target": "751" }, "edge": { - "target": "737" + "target": "751" }, - "end-of-life": "2024-05-01T00:00:00Z" + "end-of-life": "2030-05-01T00:00:00Z" }, "test": { "beta": { @@ -35,34 +35,35 @@ "1.1-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "candidate": { - "target": "743" + "target": "752" }, "beta": { - "target": "743" + "target": "752" }, "edge": { - "target": "743" + "target": "752" } }, "1-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "candidate": { - "target": "743" + "target": "752" }, "beta": { - "target": "743" + "target": "752" }, "edge": { - "target": "743" + "target": "752" } }, "1.2-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "beta": { - "target": "744" + "target": "753" }, "edge": { "target": "1.2-22.04_beta" } - } + }, + "1.0.0-22.04": {} } \ No newline at end of file From ce1a986017b40a9a6df551944c2fac610c0dc89d Mon Sep 17 00:00:00 2001 From: Anas Husseini Date: Fri, 15 Nov 2024 10:57:04 +0200 Subject: [PATCH 15/25] fix for untracked releases --- src/image/release.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/image/release.py b/src/image/release.py index 9c18b5fb..e7bb8fe3 100755 --- a/src/image/release.py +++ b/src/image/release.py @@ -98,8 +98,7 @@ for upload in image_trigger["upload"] or []: for track, upload_release_dict in (upload["release"] or {}).items(): if track not in all_releases: - print(f"Track {track} will be created for the 1st time") - all_releases[track] = {} + continue if upload_release_dict and upload_release_dict.get("end_of_life"): all_releases[track]["end-of-life"] = upload_release_dict["end_of_life"] From d3d856f6c4d803294e6e5bdb8225d321588f26c7 Mon Sep 17 00:00:00 2001 From: linostar Date: Fri, 15 Nov 2024 09:10:17 +0000 Subject: [PATCH 16/25] ci: automatically update oci/mock-rock/_releases.json, from https://github.com/canonical/oci-factory/actions/runs/11853224578 --- oci/mock-rock/_releases.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/oci/mock-rock/_releases.json b/oci/mock-rock/_releases.json index 165eca2d..4995e636 100644 --- a/oci/mock-rock/_releases.json +++ b/oci/mock-rock/_releases.json @@ -13,13 +13,13 @@ }, "1.0-22.04": { "candidate": { - "target": "751" + "target": "757" }, "beta": { - "target": "751" + "target": "757" }, "edge": { - "target": "751" + "target": "757" }, "end-of-life": "2030-05-01T00:00:00Z" }, @@ -35,31 +35,31 @@ "1.1-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "candidate": { - "target": "752" + "target": "758" }, "beta": { - "target": "752" + "target": "758" }, "edge": { - "target": "752" + "target": "758" } }, "1-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "candidate": { - "target": "752" + "target": "758" }, "beta": { - "target": "752" + "target": "758" }, "edge": { - "target": "752" + "target": "758" } }, "1.2-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "beta": { - "target": "753" + "target": "759" }, "edge": { "target": "1.2-22.04_beta" From 16f3fae6dd6ae751385a53fa4ad8d7ad0c2be642 Mon Sep 17 00:00:00 2001 From: Anas Husseini Date: Fri, 15 Nov 2024 12:25:54 +0200 Subject: [PATCH 17/25] mock-rock: remove 1.0.0 tag and change 1.0 EOL to an expired one --- oci/mock-rock/image.yaml | 8 +------- src/image/release.py | 3 ++- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/oci/mock-rock/image.yaml b/oci/mock-rock/image.yaml index 362b45b0..72382b32 100644 --- a/oci/mock-rock/image.yaml +++ b/oci/mock-rock/image.yaml @@ -13,14 +13,8 @@ upload: commit: 17916dd5de270e61a6a3fd3f4661a6413a50fd6f directory: mock_rock/1.0 release: - 1.0.0-22.04: - end-of-life: "2024-05-01T00:00:00Z" - risks: - - candidate - - edge - - beta 1.0-22.04: - end-of-life: "2030-05-01T00:00:00Z" + end-of-life: "2024-05-01T00:00:00Z" risks: - candidate - edge diff --git a/src/image/release.py b/src/image/release.py index e7bb8fe3..9c18b5fb 100755 --- a/src/image/release.py +++ b/src/image/release.py @@ -98,7 +98,8 @@ for upload in image_trigger["upload"] or []: for track, upload_release_dict in (upload["release"] or {}).items(): if track not in all_releases: - continue + print(f"Track {track} will be created for the 1st time") + all_releases[track] = {} if upload_release_dict and upload_release_dict.get("end_of_life"): all_releases[track]["end-of-life"] = upload_release_dict["end_of_life"] From a88f5d76b9d6d2f27c59f42d16e605a03ad463ab Mon Sep 17 00:00:00 2001 From: linostar Date: Fri, 15 Nov 2024 10:40:00 +0000 Subject: [PATCH 18/25] ci: automatically update oci/mock-rock/_releases.json, from https://github.com/canonical/oci-factory/actions/runs/11854551870 --- oci/mock-rock/_releases.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/oci/mock-rock/_releases.json b/oci/mock-rock/_releases.json index 4995e636..08eb37e8 100644 --- a/oci/mock-rock/_releases.json +++ b/oci/mock-rock/_releases.json @@ -35,31 +35,31 @@ "1.1-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "candidate": { - "target": "758" + "target": "761" }, "beta": { - "target": "758" + "target": "761" }, "edge": { - "target": "758" + "target": "761" } }, "1-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "candidate": { - "target": "758" + "target": "761" }, "beta": { - "target": "758" + "target": "761" }, "edge": { - "target": "758" + "target": "761" } }, "1.2-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "beta": { - "target": "759" + "target": "762" }, "edge": { "target": "1.2-22.04_beta" From 7f2cbb43d50303fe9f4a91c6d68c171c5ee60774 Mon Sep 17 00:00:00 2001 From: Anas Husseini Date: Fri, 15 Nov 2024 12:54:31 +0200 Subject: [PATCH 19/25] fix dict key name --- src/image/release.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/image/release.py b/src/image/release.py index 9c18b5fb..cddafe83 100755 --- a/src/image/release.py +++ b/src/image/release.py @@ -101,8 +101,8 @@ print(f"Track {track} will be created for the 1st time") all_releases[track] = {} - if upload_release_dict and upload_release_dict.get("end_of_life"): - all_releases[track]["end-of-life"] = upload_release_dict["end_of_life"] + if upload_release_dict and upload_release_dict.get("end-of-life"): + all_releases[track]["end-of-life"] = upload_release_dict["end-of-life"] print( "Going to update channels according to the following:\n" From 97b999ca7a03a3507728d77e715ce3c00ddb05d6 Mon Sep 17 00:00:00 2001 From: linostar Date: Fri, 15 Nov 2024 11:06:29 +0000 Subject: [PATCH 20/25] ci: automatically update oci/mock-rock/_releases.json, from https://github.com/canonical/oci-factory/actions/runs/11854971402 --- oci/mock-rock/_releases.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/oci/mock-rock/_releases.json b/oci/mock-rock/_releases.json index 08eb37e8..3effd46b 100644 --- a/oci/mock-rock/_releases.json +++ b/oci/mock-rock/_releases.json @@ -21,7 +21,7 @@ "edge": { "target": "757" }, - "end-of-life": "2030-05-01T00:00:00Z" + "end-of-life": "2024-05-01T00:00:00Z" }, "test": { "beta": { @@ -35,31 +35,31 @@ "1.1-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "candidate": { - "target": "761" + "target": "764" }, "beta": { - "target": "761" + "target": "764" }, "edge": { - "target": "761" + "target": "764" } }, "1-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "candidate": { - "target": "761" + "target": "764" }, "beta": { - "target": "761" + "target": "764" }, "edge": { - "target": "761" + "target": "764" } }, "1.2-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "beta": { - "target": "762" + "target": "765" }, "edge": { "target": "1.2-22.04_beta" From 516757d010627c0a74bd59444fa20e16828c111f Mon Sep 17 00:00:00 2001 From: linostar Date: Fri, 15 Nov 2024 12:01:10 +0000 Subject: [PATCH 21/25] ci: automatically update oci/mock-rock/_releases.json, from https://github.com/canonical/oci-factory/actions/runs/11855725992 --- oci/mock-rock/_releases.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/oci/mock-rock/_releases.json b/oci/mock-rock/_releases.json index 3effd46b..d85866f5 100644 --- a/oci/mock-rock/_releases.json +++ b/oci/mock-rock/_releases.json @@ -35,31 +35,31 @@ "1.1-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "candidate": { - "target": "764" + "target": "767" }, "beta": { - "target": "764" + "target": "767" }, "edge": { - "target": "764" + "target": "767" } }, "1-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "candidate": { - "target": "764" + "target": "767" }, "beta": { - "target": "764" + "target": "767" }, "edge": { - "target": "764" + "target": "767" } }, "1.2-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "beta": { - "target": "765" + "target": "768" }, "edge": { "target": "1.2-22.04_beta" From dfe6a511a3f2a57e721293f480d1a01cd1de42ba Mon Sep 17 00:00:00 2001 From: linostar Date: Tue, 19 Nov 2024 10:42:29 +0000 Subject: [PATCH 22/25] ci: automatically update oci/mock-rock/_releases.json, from https://github.com/canonical/oci-factory/actions/runs/11911169972 --- oci/mock-rock/_releases.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/oci/mock-rock/_releases.json b/oci/mock-rock/_releases.json index d85866f5..83889b3c 100644 --- a/oci/mock-rock/_releases.json +++ b/oci/mock-rock/_releases.json @@ -35,31 +35,31 @@ "1.1-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "candidate": { - "target": "767" + "target": "779" }, "beta": { - "target": "767" + "target": "779" }, "edge": { - "target": "767" + "target": "779" } }, "1-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "candidate": { - "target": "767" + "target": "779" }, "beta": { - "target": "767" + "target": "779" }, "edge": { - "target": "767" + "target": "779" } }, "1.2-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "beta": { - "target": "768" + "target": "780" }, "edge": { "target": "1.2-22.04_beta" From 46a1691fa47547a89e862ab916324295d911021d Mon Sep 17 00:00:00 2001 From: zhijie-yang Date: Tue, 19 Nov 2024 11:03:04 +0000 Subject: [PATCH 23/25] ci: automatically update oci/mock-rock/_releases.json, from https://github.com/canonical/oci-factory/actions/runs/11911502146 --- oci/mock-rock/_releases.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/oci/mock-rock/_releases.json b/oci/mock-rock/_releases.json index 39fa6525..69d0cbe6 100644 --- a/oci/mock-rock/_releases.json +++ b/oci/mock-rock/_releases.json @@ -35,31 +35,31 @@ "1.1-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "candidate": { - "target": "779" + "target": "782" }, "beta": { - "target": "779" + "target": "782" }, "edge": { - "target": "779" + "target": "782" } }, "1-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "candidate": { - "target": "779" + "target": "782" }, "beta": { - "target": "779" + "target": "782" }, "edge": { - "target": "779" + "target": "782" } }, "1.2-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "beta": { - "target": "780" + "target": "783" }, "edge": { "target": "1.2-22.04_beta" From ba191296bde0274e61a6382dd4468ba7e3f7ef12 Mon Sep 17 00:00:00 2001 From: Linostar Date: Wed, 20 Nov 2024 15:48:14 +0200 Subject: [PATCH 24/25] Apply Clay's suggestion Co-authored-by: Adrian Clay Lake --- src/image/release.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/image/release.py b/src/image/release.py index cddafe83..1ba19e0e 100755 --- a/src/image/release.py +++ b/src/image/release.py @@ -101,7 +101,7 @@ print(f"Track {track} will be created for the 1st time") all_releases[track] = {} - if upload_release_dict and upload_release_dict.get("end-of-life"): + if isinstance(upload_release_dict, dict) and "end-of-life" in upload_release_dict: all_releases[track]["end-of-life"] = upload_release_dict["end-of-life"] print( From 62c44dc1303fecf089b7ad55d1c4cbb590a234cc Mon Sep 17 00:00:00 2001 From: linostar Date: Wed, 20 Nov 2024 13:58:27 +0000 Subject: [PATCH 25/25] ci: automatically update oci/mock-rock/_releases.json, from https://github.com/canonical/oci-factory/actions/runs/11934719683 --- oci/mock-rock/_releases.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/oci/mock-rock/_releases.json b/oci/mock-rock/_releases.json index 69d0cbe6..384f8f9a 100644 --- a/oci/mock-rock/_releases.json +++ b/oci/mock-rock/_releases.json @@ -35,31 +35,31 @@ "1.1-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "candidate": { - "target": "782" + "target": "788" }, "beta": { - "target": "782" + "target": "788" }, "edge": { - "target": "782" + "target": "788" } }, "1-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "candidate": { - "target": "782" + "target": "788" }, "beta": { - "target": "782" + "target": "788" }, "edge": { - "target": "782" + "target": "788" } }, "1.2-22.04": { "end-of-life": "2030-05-01T00:00:00Z", "beta": { - "target": "783" + "target": "789" }, "edge": { "target": "1.2-22.04_beta"