diff --git a/.cookiecutter-replay.json b/.cookiecutter-replay.json index 9add7664..e3bef652 100644 --- a/.cookiecutter-replay.json +++ b/.cookiecutter-replay.json @@ -8,6 +8,7 @@ "keywords": "dispatch, client, api, python", "github_org": "frequenz-floss", "license": "MIT", + "private_repo": "no", "author_name": "Frequenz Energy-as-a-Service GmbH", "author_email": "floss@frequenz.com", "python_package": "frequenz.client.dispatch", @@ -26,6 +27,10 @@ "keywords": "dispatch, client, api, python", "github_org": "frequenz-floss", "license": "MIT", + "private_repo": [ + "{{ 'yes' if cookiecutter.license == 'Proprietary' else 'no' }}", + "{{ 'no' if cookiecutter.license == 'Proprietary' else 'yes' }}" + ], "author_name": "Frequenz Energy-as-a-Service GmbH", "author_email": "floss@frequenz.com", "python_package": "frequenz.client.dispatch", diff --git a/.github/containers/nox-cross-arch/arm64-ubuntu-20.04-python-3.11.Dockerfile b/.github/containers/nox-cross-arch/arm64-ubuntu-20.04-python-3.11.Dockerfile deleted file mode 100644 index 4a29eec7..00000000 --- a/.github/containers/nox-cross-arch/arm64-ubuntu-20.04-python-3.11.Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ -# License: MIT -# Copyright © 2024 Frequenz Energy-as-a-Service GmbH -# This Dockerfile is used to run the tests in arm64, which is not supported by -# GitHub Actions at the moment. - -FROM docker.io/library/ubuntu:20.04 - -ENV DEBIAN_FRONTEND=noninteractive - -# Install Python 3.11 and curl to install pip later -RUN apt-get update -y && \ - apt-get install --no-install-recommends -y \ - software-properties-common && \ - add-apt-repository ppa:deadsnakes/ppa && \ - apt-get install --no-install-recommends -y \ - ca-certificates \ - curl \ - git \ - python3.11 \ - python3.11-distutils && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -# Install pip -RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python3.11 - -RUN update-alternatives --install \ - /usr/local/bin/python python /usr/bin/python3.11 1 && \ - python -m pip install --upgrade --no-cache-dir pip - -COPY entrypoint.bash /usr/bin/entrypoint.bash - -ENTRYPOINT ["/usr/bin/entrypoint.bash"] diff --git a/.github/containers/nox-cross-arch/entrypoint.bash b/.github/containers/nox-cross-arch/entrypoint.bash deleted file mode 100755 index f344deb0..00000000 --- a/.github/containers/nox-cross-arch/entrypoint.bash +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -# License: MIT -# Copyright © 2024 Frequenz Energy-as-a-Service GmbH -set -e - -echo "System details:" $(uname -a) -echo "Machine:" $(uname -m) - -exec "$@" diff --git a/.github/containers/test-installation/Dockerfile b/.github/containers/test-installation/Dockerfile deleted file mode 100644 index 478e6acb..00000000 --- a/.github/containers/test-installation/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -# License: MIT -# Copyright © 2024 Frequenz Energy-as-a-Service GmbH -# This Dockerfile is used to test the installation of the python package in -# multiple platforms in the CI. It is not used to build the package itself. - -FROM python:3.11-slim - -RUN apt-get update -y && \ - apt-get install --no-install-recommends -y \ - git && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* && \ - python -m pip install --upgrade --no-cache-dir pip - - -COPY dist dist -RUN pip install dist/*.whl && \ - rm -rf dist diff --git a/.github/dependabot.yml b/.github/dependabot.yml index feacf85c..fb7703d2 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -29,6 +29,7 @@ updates: exclude-patterns: # pydoclint has shipped breaking changes in patch updates often - "pydoclint" + - "isort" minor: update-types: - "minor" @@ -46,6 +47,7 @@ updates: - "mkdocstrings[python]" - "pydoclint" - "pytest-asyncio" + - "isort" # We group repo-config updates as it uses optional dependencies that are # considered different dependencies otherwise, and will create one PR for # each if we don't group them. diff --git a/.github/workflows/auto-dependabot.yaml b/.github/workflows/auto-dependabot.yaml index 572bd444..3245e911 100644 --- a/.github/workflows/auto-dependabot.yaml +++ b/.github/workflows/auto-dependabot.yaml @@ -23,7 +23,8 @@ jobs: if: > github.actor == 'dependabot[bot]' && !contains(github.event.pull_request.title, 'the repo-config group') && - !contains(github.event.pull_request.title, 'Bump black from ') + !contains(github.event.pull_request.title, 'Bump black from ') && + !contains(github.event.pull_request.title, 'Bump isort from ') runs-on: ubuntu-slim steps: - name: Generate GitHub App token diff --git a/.github/workflows/black-migration.yaml b/.github/workflows/black-migration.yaml index 3dc86fb7..7116acdb 100644 --- a/.github/workflows/black-migration.yaml +++ b/.github/workflows/black-migration.yaml @@ -66,7 +66,7 @@ jobs: # Read/update pull request metadata and labels. permission-pull-requests: write - name: Migrate - uses: frequenz-floss/gh-action-dependabot-migrate@eb100d3cf732b4808a7776eee8f303521efd494b # v1.2.1 + uses: frequenz-floss/gh-action-dependabot-migrate@27763fb5eb56476d91abe00132e8a0614171f92f # v1.2.0 with: migration-script: | import os @@ -81,6 +81,7 @@ jobs: subprocess.run([sys.executable, "-Im", "black", "."], check=True) token: ${{ steps.create-app-token.outputs.token }} auto-merge-on-changes: "false" + version-iteration: "false" sign-commits: "true" auto-merged-label: "tool:auto-merged" migrated-label: "tool:black:migration:executed" diff --git a/.github/workflows/isort-migration.yaml b/.github/workflows/isort-migration.yaml new file mode 100644 index 00000000..fde6c0c1 --- /dev/null +++ b/.github/workflows/isort-migration.yaml @@ -0,0 +1,92 @@ +# Automatic isort migration for Dependabot PRs +# +# When Dependabot upgrades isort, this workflow installs the new version and +# runs `isort .` so the PR already contains any import-ordering changes +# introduced by the upgrade, while leaving the PR open for review. +# +# isort follows SemVer but its release policy +# (https://github.com/PyCQA/isort/blob/main/docs/major_releases/release_policy.md) +# explicitly allows intentional formatting changes in minor releases, and +# patch releases may also adjust output in smaller bug-fix ways. Because of +# that, isort is excluded from the regular `patch` and `minor` Dependabot +# groups: every isort bump produces an individual `Bump isort from …` PR and +# is routed through this migration workflow. +# +# The companion auto-dependabot workflow skips those PRs so they're handled +# exclusively by this migration workflow. +# +# XXX: !!! SECURITY WARNING !!! +# pull_request_target has write access to the repo, and can read secrets. +# This is required because Dependabot PRs are treated as fork PRs: the +# GITHUB_TOKEN is read-only and secrets are unavailable with a plain +# pull_request trigger. The action mitigates the risk by: +# - Never executing code from the PR (the migration script is embedded +# in this workflow file on the base branch, not taken from the PR). +# - Gating migration steps on github.actor == 'dependabot[bot]'. +# - Running checkout with persist-credentials: false and isolating +# push credentials from the migration script environment. +# For more details read: +# https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ + +name: isort Migration + +on: + merge_group: # To allow using this as a required check for merging + pull_request_target: + types: [opened, synchronize, reopened, labeled, unlabeled] + +permissions: + # Commit reformatted files back to the PR branch. + contents: write + # Create and normalize migration state labels. + issues: write + # Read/update pull request metadata and comments. + pull-requests: write + +jobs: + isort-migration: + name: Migrate isort + # Skip if it was triggered by the merge queue. We only need the workflow to + # be executed to meet the "Required check" condition for merging, but we + # don't need to actually run the job, having the job present as Skipped is + # enough. + if: | + github.event_name == 'pull_request_target' && + github.actor == 'dependabot[bot]' && + contains(github.event.pull_request.title, 'Bump isort from ') + runs-on: ubuntu-24.04 + steps: + - name: Generate token + id: create-app-token + uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1 + with: + app-id: ${{ secrets.FREQUENZ_AUTO_DEPENDABOT_APP_ID }} + private-key: ${{ secrets.FREQUENZ_AUTO_DEPENDABOT_APP_PRIVATE_KEY }} + # Push reformatted files to the PR branch. + permission-contents: write + # Create and normalize migration state labels. + permission-issues: write + # Read/update pull request metadata and labels. + permission-pull-requests: write + - name: Migrate + uses: frequenz-floss/gh-action-dependabot-migrate@27763fb5eb56476d91abe00132e8a0614171f92f # v1.2.0 + with: + migration-script: | + import os + import subprocess + import sys + + version = os.environ["MIGRATION_VERSION"].lstrip("v") + subprocess.run( + [sys.executable, "-Im", "pip", "install", f"isort=={version}"], + check=True, + ) + subprocess.run([sys.executable, "-Im", "isort", "."], check=True) + token: ${{ steps.create-app-token.outputs.token }} + auto-merge-on-changes: "false" + version-iteration: "false" + sign-commits: "true" + auto-merged-label: "tool:auto-merged" + migrated-label: "tool:isort:migration:executed" + intervention-pending-label: "tool:isort:migration:intervention-pending" + intervention-done-label: "tool:isort:migration:intervention-done" diff --git a/.github/workflows/repo-config-migration.yaml b/.github/workflows/repo-config-migration.yaml index 8ab5e01c..9608e91f 100644 --- a/.github/workflows/repo-config-migration.yaml +++ b/.github/workflows/repo-config-migration.yaml @@ -58,12 +58,14 @@ jobs: # Allow pushes when migration changes workflow files. permission-workflows: write - name: Migrate - uses: frequenz-floss/gh-action-dependabot-migrate@eb100d3cf732b4808a7776eee8f303521efd494b # v1.2.1 + uses: frequenz-floss/gh-action-dependabot-migrate@27763fb5eb56476d91abe00132e8a0614171f92f # v1.2.0 with: script-url-template: >- https://raw.githubusercontent.com/frequenz-floss/frequenz-repo-config-python/{version}/cookiecutter/migrate.py token: ${{ steps.create-app-token.outputs.token }} migration-token: ${{ secrets.REPO_CONFIG_MIGRATION_TOKEN }} + version-iteration: "minor" + if-no-iterations: "pass" sign-commits: "true" auto-merged-label: "tool:auto-merged" migrated-label: "tool:repo-config:migration:executed" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 966c90f5..840dbac0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -50,14 +50,14 @@ pytest tests/test_*.py Or you can use `nox`: ```sh -nox -R -s pytest -- test/test_*.py +nox -R -s pytest -- tests/test_*.py ``` The same appliest to `pylint` or `mypy` for example: ```sh -nox -R -s pylint -- test/test_*.py -nox -R -s mypy -- test/test_*.py +nox -R -s pylint -- tests/test_*.py +nox -R -s mypy -- tests/test_*.py ``` ### Building the documentation @@ -154,30 +154,3 @@ These are the steps to create a new release: eventually too). 7. Celebrate! - -## Cross-Arch Testing - -This project has built-in support for testing across multiple architectures. -Currently, our CI conducts tests on `arm64` machines using QEMU emulation. We -also have the flexibility to expand this support to include additional -architectures in the future. - -This project contains Dockerfiles that can be used in the CI to test the -python package in non-native machine architectures, e.g., `arm64`. The -Dockerfiles exist in the directory `.github/containers/nox-cross-arch`, and -follow a naming scheme so that they can be easily used in build matrices in the -CI, in `nox-cross-arch` job. The naming scheme is: - -``` ---python-.Dockerfile -``` - -E.g., - -``` -arm64-ubuntu-20.04-python-3.11.Dockerfile -``` - -If a Dockerfile for your desired target architecture, OS, and python version -does not exist here, please add one before proceeding to add your options to -the test matrix. diff --git a/pyproject.toml b/pyproject.toml index 19829d5b..177bba42 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ requires = [ "setuptools == 82.0.1", "setuptools_scm[toml] == 10.0.5", - "frequenz-repo-config[lib] == 0.17.0", + "frequenz-repo-config[lib] == 0.18.0", ] build-backend = "setuptools.build_meta" @@ -80,7 +80,7 @@ dev-mkdocs = [ "mkdocs-macros-plugin == 1.5.0", "mkdocs-material == 9.7.6", "mkdocstrings[python] == 1.0.4", - "frequenz-repo-config[lib] == 0.17.0", + "frequenz-repo-config[lib] == 0.18.0", ] dev-mypy = [ "mypy == 2.1.0", @@ -91,7 +91,7 @@ dev-mypy = [ "types-protobuf == 7.34.1.20260518", "types-python-dateutil == 2.9.0.20260518", ] -dev-noxfile = ["nox == 2026.4.10", "frequenz-repo-config[lib] == 0.17.0"] +dev-noxfile = ["nox == 2026.4.10", "frequenz-repo-config[lib] == 0.18.0"] dev-pylint = [ "pylint == 4.0.5", # For checking the noxfile, docs/ script, and tests @@ -100,7 +100,7 @@ dev-pylint = [ ] dev-pytest = [ "pytest == 9.0.3", - "frequenz-repo-config[extra-lint-examples] == 0.17.0", + "frequenz-repo-config[extra-lint-examples] == 0.18.0", "pytest-mock == 3.15.1", "pytest-asyncio == 1.4.0", "async-solipsism == 0.9",