diff --git a/.github/cookiecutter-migrate.template.py b/.github/cookiecutter-migrate.template.py index 70c66fbc..8e560bc8 100644 --- a/.github/cookiecutter-migrate.template.py +++ b/.github/cookiecutter-migrate.template.py @@ -20,7 +20,7 @@ And remember to follow any manual instructions for each run. """ # noqa: E501 -# pylint: disable=too-many-lines +# pylint: disable=too-many-lines, too-many-locals, too-many-branches import hashlib import json diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 9b157268..179d9eab 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -35,3 +35,4 @@ But you might still need to adapt your code: ### Cookiecutter template - Added a migration step for api repositories to fix `mkdocs.yml` when the previous `mkdocstrings-python` v2 migration moved only `paths: ["src"]` under `handlers.python.options` but not `paths: ["py"]`. +- Fixed runners for jobs that require Docker and where wrongly converted to `ubuntu-slim` in v0.15.0, changing them back to `ubuntu-24.04` to avoid Docker-related failures. The template and the migration script were both updated to reflect this change. diff --git a/cookiecutter/migrate.py b/cookiecutter/migrate.py index ab301ebd..bc25db29 100644 --- a/cookiecutter/migrate.py +++ b/cookiecutter/migrate.py @@ -20,7 +20,7 @@ And remember to follow any manual instructions for each run. """ # noqa: E501 -# pylint: disable=too-many-lines +# pylint: disable=too-many-lines, too-many-locals, too-many-branches import hashlib import json @@ -41,6 +41,9 @@ def main() -> None: print("Fixing mkdocstrings-python v2 paths for api repos...") migrate_api_mkdocs_mkdocstrings_paths() print("=" * 72) + print("Migrating protolint and publish-to-pypi runners to ubuntu-24.04...") + migrate_docker_based_runners() + print("=" * 72) print() if _manual_steps: @@ -111,6 +114,125 @@ def migrate_api_mkdocs_mkdocstrings_paths() -> None: ) +def migrate_docker_based_runners() -> None: + """Migrate Docker-based jobs to use ubuntu-24.04 runners. + + The ``protolint`` and ``publish-to-pypi`` jobs need Docker, which is not + available on ``ubuntu-slim``. They should therefore run on + ``ubuntu-24.04`` instead. + """ + workflows_dir = Path(".github") / "workflows" + protolint_new = ( + " protolint:\n" + " name: Check proto files with protolint\n" + " runs-on: ubuntu-24.04" + ) + publish_to_pypi_new = ( + ' needs: ["create-github-release"]\n runs-on: ubuntu-24.04' + ) + migrations: dict[str, list[dict[str, Any]]] = {} + + protolint_rule = { + "job": "protolint", + "required_for": "api repos", + "job_marker": " protolint:\n", + "old": [ + ( + " protolint:\n" + " name: Check proto files with protolint\n" + " runs-on: ubuntu-slim" + ), + ( + " protolint:\n" + " name: Check proto files with protolint\n" + " runs-on: ubuntu-latest" + ), + ], + "new": protolint_new, + } + project_type = read_cookiecutter_str_var("type") + if project_type is None: + manual_step( + "Unable to detect the cookiecutter project type from " + ".cookiecutter-replay.json; cannot determine whether the protolint " + "runner migration applies." + ) + elif project_type == "api": + migrations.setdefault("ci-pr.yaml", []).append(protolint_rule) + migrations.setdefault("ci.yaml", []).append(protolint_rule) + else: + print(" Skipping protolint runner migration (not an api project)") + + github_org = read_cookiecutter_str_var("github_org") + if github_org is None: + manual_step( + "Unable to detect the cookiecutter GitHub organization from " + ".cookiecutter-replay.json; cannot determine whether the " + "publish-to-pypi runner migration applies." + ) + elif github_org == "frequenz-floss": + migrations.setdefault("ci.yaml", []).append( + { + "job": "publish-to-pypi", + "required_for": "frequenz-floss repos", + "job_marker": " publish-to-pypi:\n", + "old": [ + (' needs: ["create-github-release"]\n runs-on: ubuntu-slim'), + ( + ' needs: ["create-github-release"]\n' + " runs-on: ubuntu-latest" + ), + ], + "new": publish_to_pypi_new, + } + ) + else: + print(" Skipping publish-to-pypi runner migration (not a frequenz-floss repo)") + + for filename, rules in migrations.items(): + filepath = workflows_dir / filename + if not filepath.exists(): + for rule in rules: + manual_step( + f" Expected to find {filepath} for job {rule['job']} in " + f"{rule['required_for']}. Please add or update that job to use " + "`runs-on: ubuntu-24.04`." + ) + continue + + for rule in rules: + job = rule["job"] + required_for = rule["required_for"] + job_marker = rule["job_marker"] + new = rule["new"] + content = filepath.read_text(encoding="utf-8") + + if job_marker not in content: + manual_step( + f" Expected to find job {job} in {filepath} for " + f"{required_for}. Please update it to use " + "`runs-on: ubuntu-24.04`." + ) + continue + + if new in content: + print(f" Skipped {filepath}: runner already up to date for job {job}") + continue + + for old in rule["old"]: + if old in content: + replace_file_contents_atomically( + filepath, old, new, content=content + ) + print(f" Updated {filepath}: migrated runner for job {job}") + break + else: + manual_step( + f" Pattern not found in {filepath}: please switch the runner " + f"for job {job} to `runs-on: ubuntu-24.04`." + ) + + def apply_patch(patch_content: str) -> None: """Apply a patch using the patch utility.""" subprocess.run(["patch", "-p1"], input=patch_content.encode(), check=True) diff --git a/cookiecutter/{{cookiecutter.github_repo_name}}/.github/workflows/ci-pr.yaml b/cookiecutter/{{cookiecutter.github_repo_name}}/.github/workflows/ci-pr.yaml index 1218f78a..46e07c63 100644 --- a/cookiecutter/{{cookiecutter.github_repo_name}}/.github/workflows/ci-pr.yaml +++ b/cookiecutter/{{cookiecutter.github_repo_name}}/.github/workflows/ci-pr.yaml @@ -15,7 +15,7 @@ jobs: {% endraw %}{% if cookiecutter.type == "api" %}{% raw -%} protolint: name: Check proto files with protolint - runs-on: ubuntu-slim + runs-on: ubuntu-24.04 steps: - name: Setup Git diff --git a/cookiecutter/{{cookiecutter.github_repo_name}}/.github/workflows/ci.yaml b/cookiecutter/{{cookiecutter.github_repo_name}}/.github/workflows/ci.yaml index 74e6ed16..39c4267b 100644 --- a/cookiecutter/{{cookiecutter.github_repo_name}}/.github/workflows/ci.yaml +++ b/cookiecutter/{{cookiecutter.github_repo_name}}/.github/workflows/ci.yaml @@ -27,7 +27,7 @@ jobs: {% endraw %}{% if cookiecutter.type == "api" %}{% raw -%} protolint: name: Check proto files with protolint - runs-on: ubuntu-slim + runs-on: ubuntu-24.04 steps: - name: Setup Git diff --git a/tests_golden/integration/test_cookiecutter_generation/api/frequenz-api-test/.github/workflows/ci-pr.yaml b/tests_golden/integration/test_cookiecutter_generation/api/frequenz-api-test/.github/workflows/ci-pr.yaml index 27349aa2..232a3e7f 100644 --- a/tests_golden/integration/test_cookiecutter_generation/api/frequenz-api-test/.github/workflows/ci-pr.yaml +++ b/tests_golden/integration/test_cookiecutter_generation/api/frequenz-api-test/.github/workflows/ci-pr.yaml @@ -13,7 +13,7 @@ env: jobs: protolint: name: Check proto files with protolint - runs-on: ubuntu-slim + runs-on: ubuntu-24.04 steps: - name: Setup Git diff --git a/tests_golden/integration/test_cookiecutter_generation/api/frequenz-api-test/.github/workflows/ci.yaml b/tests_golden/integration/test_cookiecutter_generation/api/frequenz-api-test/.github/workflows/ci.yaml index c4464f92..060c331a 100644 --- a/tests_golden/integration/test_cookiecutter_generation/api/frequenz-api-test/.github/workflows/ci.yaml +++ b/tests_golden/integration/test_cookiecutter_generation/api/frequenz-api-test/.github/workflows/ci.yaml @@ -25,7 +25,7 @@ env: jobs: protolint: name: Check proto files with protolint - runs-on: ubuntu-slim + runs-on: ubuntu-24.04 steps: - name: Setup Git