diff --git a/.github/workflows/dco-merge-queue.yml b/.github/workflows/dco-merge-queue.yml deleted file mode 100644 index 7a4260de..00000000 --- a/.github/workflows/dco-merge-queue.yml +++ /dev/null @@ -1,14 +0,0 @@ -# Based on https://github.com/hyperledger/besu/pull/5207/files -name: DCO -on: - merge_group: - -# Drop all token permissions: this workflow only runs a local echo command. -permissions: {} - -jobs: - DCO: - runs-on: ubuntu-slim - if: ${{ github.actor != 'dependabot[bot]' }} - steps: - - run: echo "This DCO job runs on merge_queue event and doesn't check PR contents" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b7f1dde2..02d7831c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -53,7 +53,7 @@ Or you can use `nox`: nox -R -s pytest -- tests/test_*.py ``` -The same appliest to `pylint` or `mypy` for example: +The same applies to `pylint` or `mypy` for example: ```sh nox -R -s pylint -- tests/test_*.py @@ -121,12 +121,19 @@ These are the steps to create a new release: 1. Get the latest head you want to create a release from. + If you use milestones, check that the milestone for this release has no open + issues left, and move whatever won't make it to a later milestone. + 2. Update the `RELEASE_NOTES.md` file if it is not complete, up to date, and - remove template comments (``) and empty sections. Submit a pull request if an update is needed, wait until it is merged, and update the latest head you want to create a release from to get the new merged pull request. + This can't be left for later: the notes published with the release are read + from the `RELEASE_NOTES.md` committed at the tagged commit, not from the tag + message. + 3. Create a new signed tag using the release notes and a [semver](https://semver.org/) compatible version number with a `v` prefix, for example: @@ -135,6 +142,10 @@ These are the steps to create a new release: git tag -s --cleanup=whitespace -F RELEASE_NOTES.md v0.0.1 ``` + The signature is not optional: the *Protect released tags* ruleset rejects + unsigned tags. It also forbids updating or deleting a released tag, so make + sure you are tagging the commit you want. + 4. Push the new tag. 5. A GitHub action will test the tag and if all goes well it will create @@ -153,4 +164,7 @@ These are the steps to create a new release: Commit the new release notes and create a PR (this step should be automated eventually too). -7. Celebrate! +7. If you use milestones, close the milestone for this release, and create the + next one if it doesn't exist yet. + +8. Celebrate! diff --git a/pyproject.toml b/pyproject.toml index ceedd33b..e3aa46cd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ requires = [ "setuptools == 84.0.0", "setuptools_scm[toml] == 10.2.1", - "frequenz-repo-config[lib] == 0.18.0", + "frequenz-repo-config[lib] == 0.19.0", ] build-backend = "setuptools.build_meta" @@ -72,7 +72,7 @@ dev-mkdocs = [ "mkdocs-material == 9.7.7", "mkdocstrings[python] == 1.0.6", "mkdocstrings-python == 2.0.7", - "frequenz-repo-config[lib] == 0.18.0", + "frequenz-repo-config[lib] == 0.19.0", ] dev-mypy = [ "mypy == 2.3.1", @@ -82,7 +82,7 @@ dev-mypy = [ # For checking the noxfile, docs/ script, and tests "frequenz-client-microgrid[dev-mkdocs,dev-noxfile,dev-pytest]", ] -dev-noxfile = ["nox == 2026.8.17", "frequenz-repo-config[lib] == 0.18.0"] +dev-noxfile = ["nox == 2026.8.17", "frequenz-repo-config[lib] == 0.19.0"] dev-pylint = [ "pylint == 4.0.7", # For checking the noxfile, docs/ script, and tests @@ -90,7 +90,7 @@ dev-pylint = [ ] dev-pytest = [ "pytest == 9.1.1", - "frequenz-repo-config[extra-lint-examples] == 0.18.0", + "frequenz-repo-config[extra-lint-examples] == 0.19.0", "pytest-mock == 3.15.1", "pytest-asyncio == 1.4.0", "async-solipsism == 0.9", @@ -168,7 +168,6 @@ disable = [ ] [tool.pytest.ini_options] -addopts = "-vv" filterwarnings = [ "error", "once::DeprecationWarning", @@ -178,11 +177,13 @@ filterwarnings = [ 'ignore:Protobuf gencode version .*exactly one major version older.*:UserWarning', ] testpaths = ["tests", "src"] +asyncio_debug = true asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "function" required_plugins = ["pytest-asyncio", "pytest-mock"] [tool.mypy] +enable_error_code = ["exhaustive-match"] explicit_package_bases = true namespace_packages = true # This option disables mypy cache, and it is sometimes useful to enable it if diff --git a/src/frequenz/client/microgrid/component/_component_proto.py b/src/frequenz/client/microgrid/component/_component_proto.py index 6d8d7f72..ccb65254 100644 --- a/src/frequenz/client/microgrid/component/_component_proto.py +++ b/src/frequenz/client/microgrid/component/_component_proto.py @@ -557,6 +557,8 @@ def _metric_config_bounds_from_proto( minor_issues.append( f"metric_config_bounds has an unrecognized metric {metric}" ) + case _: + pass if not metric_bound.HasField("config_bounds"): major_issues.append( diff --git a/src/frequenz/client/microgrid/metrics/_sample_proto.py b/src/frequenz/client/microgrid/metrics/_sample_proto.py index def7ce4e..c713225c 100644 --- a/src/frequenz/client/microgrid/metrics/_sample_proto.py +++ b/src/frequenz/client/microgrid/metrics/_sample_proto.py @@ -4,6 +4,7 @@ """Loading of MetricSample and AggregatedMetricValue objects from protobuf messages.""" from collections.abc import Sequence +from typing import assert_never from frequenz.api.common.v1alpha8.metrics import bounds_pb2, metrics_pb2 from frequenz.client.base import conversion @@ -59,6 +60,10 @@ def metric_sample_from_proto_with_issues( value = aggregated_metric_sample_from_proto( message.value.aggregated_metric ) + case None: + pass + case unexpected: + assert_never(unexpected) metric = enum_from_proto(message.metric, Metric) diff --git a/tests/metrics/test_sample.py b/tests/metrics/test_sample.py index 538430eb..196e1f77 100644 --- a/tests/metrics/test_sample.py +++ b/tests/metrics/test_sample.py @@ -449,3 +449,30 @@ def test_metric_sample_from_proto_with_issues( assert sample == case.expected_sample assert major_issues == case.expected_major_issues assert minor_issues == case.expected_minor_issues + + +def test_metric_sample_from_proto_with_unknown_value_variant() -> None: + """Test that an unknown future oneof member is converted to no value.""" + value = metrics_pb2.MetricValueVariant() + # Field 3 represents a hypothetical future oneof member. + value.ParseFromString(b"\x1a\x00") + message = metrics_pb2.MetricSample( + sample_time=TIMESTAMP, + metric=Metric.AC_POWER_ACTIVE.value, + value=value, + bounds=[bounds_pb2.Bounds(lower=-10.0, upper=10.0)], + ) + + major_issues: list[str] = [] + minor_issues: list[str] = [] + + sample = metric_sample_from_proto_with_issues( + message, + major_issues=major_issues, + minor_issues=minor_issues, + ) + + assert sample.value is None + assert sample.bounds == [Bounds(lower=-10.0, upper=10.0)] + assert major_issues == [] + assert minor_issues == []