Skip to content

Pin setup-uv references and stabilise action tests#272

Merged
leynos merged 25 commits into
mainfrom
chore/bump-setup-uv-sha
Jun 2, 2026
Merged

Pin setup-uv references and stabilise action tests#272
leynos merged 25 commits into
mainfrom
chore/bump-setup-uv-sha

Conversation

@leynos

@leynos leynos commented May 26, 2026

Copy link
Copy Markdown
Owner

Summary

This branch pins every astral-sh/setup-uv reference used by the repository's action and workflow definitions to 08807647e7069bb48b6ef5acd8ec9567f424441b. It also hardens the local act workflow harness so Podman Docker API failures are detected before workflow execution, and stabilises Typer-based action script tests under the project test runner.

No issue, roadmap task, or execplan is linked to this branch.

Review walkthrough

Validation

  • uv run --with typer --with packaging --with plumbum --with pyyaml --with pytest-xdist pytest .github/actions/release-to-pypi-uv/tests/test_publish_release.py::test_cli_runner_respects_env_index .github/actions/release-to-pypi-uv/tests/test_publish_release.py::test_cli_proxies_to_main -v: passed, 2 passed.
  • uv run pytest .github/actions/generate-coverage/tests/ -v: passed, 115 passed.
  • make check-fmt: passed.
  • make typecheck: passed.
  • make lint: passed.
  • make test: passed, 728 passed, 93 skipped.
  • ACT=$HOME/go/bin/act ACT_WORKFLOW_TESTS=1 ./.venv/bin/pytest tests/workflows -v -rs: passed, 15 passed in 330.52s.

Notes

The Podman investigation found that podman ps -a could print containers while the Docker-compatible API endpoint GET /v1.41/containers/json?all=true returned HTTP 500 with container not known. Since act uses that API path before starting jobs, the harness now verifies the same path and reports the exact runtime problem before invoking act.

The generate-coverage scripts keep their PEP 723 metadata for direct action execution. Test execution now uses the project interpreter so cmd-mox stubs run in the same environment as pytest; the script dependencies required by the inline metadata are already present in pyproject.toml and uv.lock.

Summary by Sourcery

Pin uv setup actions across workflows, harden the local act workflow harness, and stabilise Typer-based action scripts and their tests for more reliable CI and local validation.

New Features:

  • Expose configurable act executable selection for workflow tests via the ACT environment variable and Makefile integration.

Bug Fixes:

  • Ensure workflow tests are skipped with clear reasons when the configured container runtime or Docker-compatible Podman API is unavailable or unhealthy.
  • Make generate-coverage Rust and Python runners resilient to missing or empty GitHub Actions environment inputs by falling back to explicit environment variable reads.
  • Ensure the release-to-pypi uv publish CLI honours the INPUT_UV_INDEX environment variable when the index option is omitted on the command line.

Enhancements:

  • Add explicit probing of the Docker-compatible API (including Podman unix sockets) before running act, automatically exporting DOCKER_HOST when a healthy Podman socket is detected.
  • Refactor coverage scripts to centralise computation and reporting of coverage percentages and to better support mixed-language projects.
  • Run generate-coverage action scripts under the project Python interpreter rather than via uv run to better align with the test environment.

Build:

  • Pin all astral-sh/setup-uv usages in workflows and composite actions to a single vetted commit for reproducible CI runs.

Documentation:

  • Update local act validation documentation to describe the Docker-compatible container listing check and sandbox permission requirements for Podman-based setups.

Tests:

  • Extend workflow harness tests to cover unhealthy Podman APIs, healthy Podman socket forwarding, and custom ACT command behaviour.
  • Adjust generate-coverage script tests to invoke scripts with the project interpreter instead of uv run for more stable action testing.

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2a706d1f-ef51-4042-ae35-8c30d3faf973

📥 Commits

Reviewing files that changed from the base of the PR and between 0d6a09d and c501086.

📒 Files selected for processing (3)
  • docs/developers-guide.md
  • docs/generate-coverage-design.md
  • tests/workflows/test_conftest_runtime.py

Overview

This pull request hardens the GitHub Actions workflow infrastructure by pinning all astral-sh/setup-uv references to commit 08807647e7069bb48b6ef5acd8ec9567f424441b across composite actions and CI workflows. It stabilises action scripts through Typer CLI refactoring, centralises environment-variable parsing, improves the local act workflow harness with Docker/Podman socket probing, and expands documentation and test coverage for workflow validation.

Key Changes

Setup-uv Pinning

All astral-sh/setup-uv action references across composite actions (.github/actions/*/action.yml) and CI workflows (.github/workflows/*.yml) have been pinned to commit 08807647e7069bb48b6ef5acd8ec9567f424441b, replacing previous semantic version tags and commit hashes. This hardens supply chain security by ensuring reproducible action versions.

Workflow Test Harness Stabilisation

tests/workflows/conftest.py was substantially refactored to provide robust act runtime detection:

  • Introduced ActRuntimeStatus dataclass to encapsulate runtime availability, skip reasons, and environment variable exports
  • Implemented multi-stage runtime probe (_probe_act_runtime) that checks: act executable availability; Docker/Podman API socket reachability (including Unix domain sockets via raw HTTP); and Docker CLI fallback (docker info)
  • Added @functools.cache decorator to _get_act_runtime_status() with an autouse fixture (_clear_act_runtime_cache) to clear cached probe results between tests, allowing per-test environment mutations to be observed
  • Updated skip_unless_act marker to consult probe results and skip with diagnostic reasons when the runtime is unavailable
  • Modified run_act to dynamically forward DOCKER_HOST and other environment variables detected by the probe

tests/workflows/test_conftest_runtime.py adds comprehensive test coverage for the harness, validating executable detection, subprocess status checks, socket probing (both missing and unreachable), and skip-marker behaviour.

Generate-Coverage Script Refactoring

Common helpers (common.py):

  • Centralised _required_env(name) and _env_bool(name, *, default) helpers to standardise environment-variable parsing across action scripts
  • Both functions handle whitespace trimming and emit typer.Exit(2) on invalid/missing values with stderr diagnostics
  • Covered by comprehensive unit tests in test_common.py, including property-based tests for case-insensitivity

run_rust.py and run_python.py:

  • Migrated from module-level typer.Option() constants to typing.Annotated[...] inline parameter declarations, enabling --option "" to explicitly override environment-variable defaults
  • Use None as sentinel default to distinguish "not provided" from "explicitly empty"
  • Extract coverage computation/reporting into dedicated helpers (_resolve_output_path, _compute_coverage_percent, _report_coverage)
  • Made resilient to missing or empty DETECTED_CARGO_MANIFEST and other GitHub Actions inputs by falling back to environment reads

merge_cobertura.py:

  • Migrated to typing.Annotated parameter declarations with inline typer.Option() metadata
  • Removed module-level option constants

test_scripts.py:

  • Fixed test execution by running scripts directly with sys.executable instead of uv run --script, ensuring cmd_mox IPC stubs installed in the project venv are available
  • Added test_run_rust_omitted_manifest_arg_ignores_blank_detected_manifest to validate blank-manifest fallback
  • Added test_run_python_integration_uses_env_fallbacks_for_omitted_cli_args to validate environment-variable fallbacks
  • Introduced snapshot assertion via syrupy for GITHUB_OUTPUT content validation

Release-to-PyPI-uv Script Hardening

publish_release.py:

  • Migrated index parameter from module-level typer.Option() to typing.Annotated with inline metadata
  • Fixed handling of INPUT_UV_INDEX environment variable by applying it only when CLI argument is not provided, allowing --index "" to explicitly clear the variable

test_features.py (Rust Build Release):

  • Updated test to introspect Typer CLI metadata for envvar assertions instead of mocking, improving test robustness

Documentation Updates

developers-guide.md:

  • Documents ACT Makefile variable resolution order (preferring ~/go/bin/act, then ~/.local/bin/act)
  • Adds "Setup-uv Pinning" section explaining repository-wide pinning strategy
  • Adds "Workflow Test Harness" section documenting runtime probing, caching behaviour, and skip markers

generate-coverage-design.md:

  • Adds "Shared Script Helpers (common.py)" section documenting _required_env and _env_bool public API
  • Updates roadmap checklist to mark environment-variable parsing centralisation as completed

python-action-scripts.md:

  • Adds "Testing Action Scripts" section explaining execution with sys.executable to preserve cmd_mox stub availability

local-validation-of-github-actions-with-act-and-pytest.md:

  • Expands Docker/Podman socket prerequisites with container listing endpoint checks
  • Documents container not known failure mode and remediation
  • Clarifies act cache/virtualenv redirection to /tmp to avoid root-owned residue

Build Integration

Makefile:

  • Introduces ACT variable with resolution order for local act executables
  • Updates test target to export ACT environment variable when running workflow tests

Code Quality

Removed and fixed:

  • Removed unused #[expect(dead_code, ...)] annotation from rust-toy-app/build.rs
  • Fixed markdownlint violations in design documentation (table spacing, row wrapping, heading deduplication)
  • Improved test diagnostics by adding descriptive failure messages to bare assertions in probe helpers

Testing and Validation

The changes include:

  • New test module test_conftest_runtime.py (185 lines) with parametrised coverage for runtime detection across Docker/Podman configurations
  • New test module test_common.py (244 lines) with hypothesis-based property tests for environment-variable parsing
  • Updated test_scripts.py with snapshot assertions and new integration tests validating environment fallbacks
  • Validation runs reported formatting, typechecking, lint, and large test suites passing locally; workflow harness tests under act passed

Follow-up Items

Property-based testing and snapshot testing enhancements are tracked as future improvements (cross-referenced in PR objectives).

Walkthrough

Update astral-sh/setup-uv pins across actions/workflows; centralise environment parsing for generate-coverage scripts and refactor CLIs; run action scripts under sys.executable in tests; add act runtime probing in the workflow test harness; update Makefile and docs; add tests and snapshots.

Changes

Workflow tooling and test harness enhancements

Layer / File(s) Summary
setup-uv action pinning across workflows and actions
.github/actions/*/action.yml, .github/workflows/*.yml, docs/developers-guide.md
Multiple composite actions and workflows update uses: astral-sh/setup-uv@<commit> to specific pinned commits and document the pinning pattern.
generate-coverage: shared env helpers
.github/actions/generate-coverage/scripts/common.py, docs/generate-coverage-design.md
Add _required_env and _env_bool helpers that trim/validate environment inputs and canonicalise boolean parsing; document the helpers.
generate-coverage: CLI and reporting refactor
.github/actions/generate-coverage/scripts/merge_cobertura.py, .github/actions/generate-coverage/scripts/run_python.py, .github/actions/generate-coverage/scripts/run_rust.py
Remove module-level typer.Option defaults, make CLI params tri-state/optional, resolve missing inputs from environment via shared helpers, centralise coverage percent computation and GITHUB_OUTPUT emission.
Coverage tests, snapshots and script-test docs
.github/actions/generate-coverage/tests/*, docs/python-action-scripts.md
Run scripts directly with sys.executable in tests; add pytest/Hypothesis coverage for common._required_env/_env_bool; add integration tests asserting GITHUB_OUTPUT and add a snapshot file.
Workflow test harness: act runtime probing and tests
tests/workflows/conftest.py, tests/workflows/test_conftest_runtime.py
Introduce ActRuntimeStatus, _probe_act_runtime, DOCKER_HOST/unix-socket probing, cached probe results, dynamic act selection and injected env, update skip marker logic, and add unit/integration tests for probe behaviours.
Makefile ACT variable and documentation updates
Makefile, docs/local-validation-of-github-actions-with-act-and-pytest.md, docs/developers-guide.md
Add ACT variable with local-first fallback and export it for workflow tests; document container-listing API endpoint, socket permission guidance, Podman/Docker diagnostics, and setup-uv pinning guidance; document workflow test harness.
PyPI publish CLI: inline typer annotation
.github/actions/release-to-pypi-uv/scripts/publish_release.py
Remove module-level INDEX_OPTION; make CLI index optional with typ.Annotated and apply INPUT_UV_INDEX fallback when omitted.
Rust build-release CLI and test loader fixes
.github/actions/rust-build-release/src/main.py, .github/actions/rust-build-release/tests/conftest.py, .github/actions/rust-build-release/tests/test_features.py, rust-toy-app/build.rs
Make toolchain/features Typer options optional and rederive values from env when None; clear cached sibling modules before loading test targets; update tests to inspect Typer option envvar and invoke CLI explicitly; remove a dead-code expect attribute in build.rs.

Sequence Diagram(s)
(Skip — changes are cross-cutting but do not require a new multi-component sequential flow diagram in the visible section.)

Possibly related issues

Poem

Align the uv pins, set sails anew, ✨
Helpers trim the env and parse with care,
Act probes sockets, finds the path,
Docs and Makefile map the local way,
Tests sing green beneath the CI air. 🚀

You are an AI reviewer. Summarise any remaining concerns in one sentence per concern if asked.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/bump-setup-uv-sha

@sourcery-ai

sourcery-ai Bot commented May 26, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Pins all astral-sh/setup-uv usages to a single commit, hardens the workflow test harness to accurately detect and configure the container runtime used by act (including Podman Docker-API health probing and ACT command selection), and stabilises Typer-based action scripts and their tests by routing through the project interpreter and making env-var handling more resilient and explicit.

File-Level Changes

Change Details Files
Harden workflow test harness to probe the actual act container runtime path and surface precise skip reasons.
  • Introduce ActRuntimeStatus dataclass to capture runtime availability, reason, and required env overrides.
  • Add helpers to resolve the ACT command, check command availability/success, and derive the default Podman Docker-compatible socket path.
  • Implement low-level HTTP-over-unix-socket probe against /v1.41/containers/json?all=true to validate Docker-compatible APIs (especially Podman).
  • Implement _probe_act_runtime to prioritise DOCKER_HOST, fall back to Docker CLI, then Podman socket with detailed diagnostics and optional DOCKER_HOST export.
  • Replace previous _container_runtime_available logic with _probe_act_runtime, wire its result into pytest skip marker, and ensure run_act uses both the probed env and resolved ACT command.
tests/workflows/conftest.py
tests/workflows/test_conftest_runtime.py
docs/local-validation-of-github-actions-with-act-and-pytest.md
Makefile
Stabilise generate-coverage action scripts by making Typer options optional, enforcing required env vars at runtime, and running scripts with the project interpreter in tests.
  • Refactor run_rust.py to use Annotated Typer options with defaults, add helpers for required env vars and boolean env parsing, and compute coverage output paths and percentages via dedicated helpers.
  • Resolve critical inputs (paths, language, format, booleans) from either CLI options or environment, with explicit failures when required env vars are missing, and keep support for mixed-language coverage and baselines.
  • Refactor merge_cobertura.py and run_python.py to treat Typer options as optional, fall back to required-env helpers, and keep behaviour of merging/deleting inputs and writing coverage results.
  • Update generate-coverage test helper to execute scripts via sys.executable instead of uv run --script, ensuring tests exercise the same interpreter environment as pytest.
.github/actions/generate-coverage/scripts/run_rust.py
.github/actions/generate-coverage/scripts/merge_cobertura.py
.github/actions/generate-coverage/scripts/run_python.py
.github/actions/generate-coverage/tests/test_scripts.py
Make release-to-pypi-uv action CLI more robust to missing or empty INPUT_UV_INDEX while preserving Typer-based interface.
  • Replace global INDEX_OPTION with an Annotated Typer option on cli, bound to INPUT_UV_INDEX.
  • Ensure the cli function passes either the explicit index argument or falls back to INPUT_UV_INDEX at runtime, keeping main simple and environment-aware.
.github/actions/release-to-pypi-uv/scripts/publish_release.py
Pin all astral-sh/setup-uv usages in workflows and composite actions to a single, specific commit for reproducibility.
  • Update setup-uv references in CI, rust-toy-app, dependabot-automerge, and test-rust-build-release-root-discovery workflows to 08807647e7069bb48b6ef5acd8ec9567f424441b.
  • Update all composite actions that install or use uv (ensure-cargo-version, generate-coverage, release-to-pypi-uv, rust-build-release, setup-rust, determine-release-modes, export-cargo-metadata, linux-packages, macos-package, ratchet-coverage, stage-release-artefacts, upload-release-assets, validate-linux-packages) to the same pinned SHA.
  • Remove mixed version comments (v5/v6.*) in favour of the unified pin.
.github/workflows/ci.yml
.github/workflows/rust-toy-app.yml
.github/workflows/dependabot-automerge.yml
.github/workflows/test-rust-build-release-root-discovery.yml
.github/actions/ensure-cargo-version/action.yml
.github/actions/generate-coverage/action.yml
.github/actions/release-to-pypi-uv/action.yml
.github/actions/rust-build-release/action.yml
.github/actions/setup-rust/action.yml
.github/actions/determine-release-modes/action.yml
.github/actions/export-cargo-metadata/action.yml
.github/actions/linux-packages/action.yml
.github/actions/macos-package/action.yml
.github/actions/ratchet-coverage/action.yml
.github/actions/stage-release-artefacts/action.yml
.github/actions/upload-release-assets/action.yml
.github/actions/validate-linux-packages/action.yml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos

leynos commented May 26, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response.

tests/workflows/conftest.py

Comment on lines +141 to +144

    if (
        shutil.which("docker")
        and _command_succeeds("docker", "info")
        and _command_succeeds("docker", "ps", "-a")

❌ New issue: Complex Conditional
_probe_act_runtime has 1 complex conditionals with 2 branches, threshold = 2

@leynos

leynos commented May 26, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Please investigate the cause of the following issue using codegraph exploration and research, identify a fix and provide an AI coding agent prompt for the fix:

=================================== FAILURES ===================================
____________________________ test_run_rust_success _____________________________

tmp_path = PosixPath('/tmp/pytest-of-runner/pytest-0/test_run_rust_success0')
shell_stubs = <test_support.cmd_mox_stub_adapter.StubManager object at 0x7f9176251550>
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f91760afe70>

    def test_run_rust_success(
        tmp_path: Path,
        shell_stubs: StubManager,
        monkeypatch: pytest.MonkeyPatch,
    ) -> None:
        """Happy path for ``run_rust.py``."""
        monkeypatch.setenv("CARGO_PROFILE_DEV_CODEGEN_BACKEND", "cranelift")
        monkeypatch.setenv("CARGO_PROFILE_TEST_CODEGEN_BACKEND", "cranelift")
>       cargo_call, out, gh = _run_rust_coverage_call(
            tmp_path,
            shell_stubs,
            RustCoverageConfig(
                use_nextest=False,
                features="fast",
                with_default_features=False,
            ),
            monkeypatch=monkeypatch,
        )

/home/runner/work/shared-actions/shared-actions/.github/actions/generate-coverage/tests/test_scripts.py:336: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/home/runner/work/shared-actions/shared-actions/.github/actions/generate-coverage/tests/test_scripts.py:318: in _run_rust_coverage_call
    _cargo_args, out, gh = _run_rust_coverage_test(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

tmp_path = PosixPath('/tmp/pytest-of-runner/pytest-0/test_run_rust_success0')
shell_stubs = <test_support.cmd_mox_stub_adapter.StubManager object at 0x7f9176251550>
config = RustCoverageConfig(use_nextest=False, features='fast', with_default_features=False, manifest_path='Cargo.toml')

    def _run_rust_coverage_test(
        tmp_path: Path,
        shell_stubs: StubManager,
        config: RustCoverageConfig,
        *,
        monkeypatch: pytest.MonkeyPatch,
    ) -> tuple[list[str], Path, Path]:
        """Run ``run_rust.py`` with shared setup and return cargo argv + paths."""
        out = tmp_path / "cov.lcov"
        gh = tmp_path / "gh.txt"
    
        out.write_text("LF:200\nLH:163\n")
        shell_stubs.register(
            "cargo",

/home/runner/work/_temp/uv-python-dir/cpython-3.13.13-linux-x86_64-gnu/lib/python3.13/pathlib/_local.py:537: FileNotFoundError
------------------------------ Captured log setup ------------------------------
ERROR    cmd_mox.ipc.server:server.py:373 IPC received malformed JSON
Traceback (most recent call last):
  File "/home/runner/work/shared-actions/shared-actions/.venv/lib/python3.13/site-packages/cmd_mox/ipc/server.py", line 371, in _parse_payload
    obj = json.loads(raw.decode("utf-8"))
  File "/home/runner/work/_temp/uv-python-dir/cpython-3.13.13-linux-x86_64-gnu/lib/python3.13/json/__init__.py", line 352, in loads
    return _default_decoder.decode(s)
           ~~~~~~~~~~~~~~~~~~~~~~~^^^
  File "/home/runner/work/_temp/uv-python-dir/cpython-3.13.13-linux-x86_64-gnu/lib/python3.13/json/decoder.py", line 345, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/_temp/uv-python-dir/cpython-3.13.13-linux-x86_64-gnu/lib/python3.13/json/decoder.py", line 363, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
----------------------------- Captured stdout call -----------------------------
$ /opt/hostedtoolcache/uv/0.11.16/x86_64/uv run --script /home/runner/work/shared-actions/shared-actions/.github/actions/generate-coverage/scripts/run_python.py
______________________ test_cli_runner_respects_env_index ______________________

monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f9167ec3ee0>
publish_module = <module 'release_to_pypi_uv_publish_release' from '/home/runner/work/shared-actions/shared-actions/.github/actions/release-to-pypi-uv/scripts/publish_release.py'>

    def test_cli_runner_respects_env_index(
        monkeypatch: pytest.MonkeyPatch, publish_module: ModuleType
    ) -> None:
        """Accept the index from the GitHub Action input environment variable."""
        calls: list[list[str]] = []
    
        def fake_run_cmd(cmd: object, **_: object) -> None:
            formulated = list(cmd.formulate())
            calls.append(_normalize_invocation(formulated))
    
        monkeypatch.setattr(publish_module, "run_cmd", fake_run_cmd)
    
        runner = CliRunner()
        app = publish_module.typer.Typer()
        app.command()(publish_module.cli)
        result = runner.invoke(app, [], env={"INPUT_UV_INDEX": "testpypi"})
    
        assert result.exit_code == 0
>       assert calls == [["uv", "publish", "--index", "testpypi"]]
E       AssertionError: assert [['uv', 'publish']] == [['uv', 'publ..., 'testpypi']]
E         
E         At index 0 diff: ['uv', 'publish'] != ['uv', 'publish', '--index', 'testpypi']
E         
E         Full diff:
E           [
E               [
E                   'uv',
E                   'publish',
E         -         '--index',
E         -         'testpypi',
E               ],
E           ]

.github/actions/release-to-pypi-uv/tests/test_publish_release.py:160: AssertionError
--------------------------- snapshot report summary ----------------------------
2 snapshots passed.
=========================== short test summary info ============================
FAILED .github/actions/generate-coverage/tests/test_scripts.py::test_run_rust_success - assert 2 == 0
FAILED .github/actions/generate-coverage/tests/test_scripts.py::test_run_rust_nextest_command - assert 2 == 0
FAILED .github/actions/generate-coverage/tests/test_scripts.py::test_run_rust_uses_detected_manifest_path - assert 2 == 0
FAILED .github/actions/generate-coverage/tests/test_scripts.py::test_run_rust_cranelift_project_uses_llvm_codegen_env - assert 2 == 0
FAILED .github/actions/generate-coverage/tests/test_scripts.py::test_run_rust_with_cucumber - assert 2 == 0
FAILED .github/actions/generate-coverage/tests/test_scripts.py::test_run_rust_with_cucumber_nextest - assert 2 == 0
FAILED .github/actions/generate-coverage/tests/test_scripts.py::test_run_rust_with_cucumber_cobertura - assert 2 == 0
FAILED .github/actions/generate-coverage/tests/test_scripts.py::test_run_rust_with_cucumber_cobertura_merge_failure - assert 2 == 3
FAILED .github/actions/generate-coverage/tests/test_scripts.py::test_run_rust_failure - assert 'llvm-cov' in "\x1b[33mUsage: \x1b[0mrun_rust.py [OPTIONS]\n\x1b[2mTry \x1b[0m\x1b[2;34m'run_rust.py \x1b[0m\x1b[1;2;34m-\x1b[0m\x1b...   \x1b[31m│\x1b[0m\n\x1b[31m╰──────────────────────────────────────────────────────────────────────────────╯\x1b[0m\n"
FAILED .github/actions/generate-coverage/tests/test_scripts.py::test_merge_cobertura - assert 2 == 0
FAILED .github/actions/generate-coverage/tests/test_scripts.py::test_run_python_integration_cobertura_success - FileNotFoundError: [Errno 2] No such file or directory: '/tmp/pytest-of-runner/pytest-0/test_run_python_integration_co0/uv-calls.log'
FAILED .github/actions/generate-coverage/tests/test_scripts.py::test_run_python_integration_mixed_lang_path - assert 2 == 0
FAILED .github/actions/generate-coverage/tests/test_scripts.py::test_run_python_integration_uv_failure_modes[uv-sync-fails] - assert 'uv sync failed' in "\x1b[33mUsage: \x1b[0mrun_python.py [OPTIONS]\n\x1b[2mTry \x1b[0m\x1b[2;34m'run_python.py \x1b[0m\x1b[1;2;34m-\x1b[0m...   \x1b[31m│\x1b[0m\n\x1b[31m╰──────────────────────────────────────────────────────────────────────────────╯\x1b[0m\n"
 +  where 'uv sync failed' = UvFailureSpec(write_kwargs={'sync_exit': 2}, expected_in_stderr='uv sync failed').expected_in_stderr
FAILED .github/actions/generate-coverage/tests/test_scripts.py::test_run_python_integration_venv_python_symlink_targets_venv - FileNotFoundError: [Errno 2] No such file or directory: '/tmp/pytest-of-runner/pytest-0/test_run_python_integration_ve0/uv-calls.log'
FAILED .github/actions/release-to-pypi-uv/tests/test_publish_release.py::test_cli_runner_respects_env_index - AssertionError: assert [['uv', 'publish']] == [['uv', 'publ..., 'testpypi']]
  
  At index 0 diff: ['uv', 'publish'] != ['uv', 'publish', '--index', 'testpypi']
  
  Full diff:
    [
        [
            'uv',
            'publish',
  -         '--index',
  -         'testpypi',
        ],
    ]
============ 15 failed, 758 passed, 81 skipped in 260.43s (0:04:20) ============

@coderabbitai

This comment was marked as resolved.

@coderabbitai

This comment was marked as resolved.

@leynos leynos changed the title Pin setup-uv references and harden act runtime checks Pin setup-uv references and stabilise action tests May 26, 2026
codescene-delta-analysis[bot]

This comment was marked as outdated.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos

leynos commented May 26, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response.

Complex Method

.github/actions/generate-coverage/scripts/run_rust.py: main

What lead to degradation?

main has a cyclomatic complexity of 15, threshold = 9

Why does this problem occur?

A Complex Method has a high cyclomatic complexity. The recommended threshold for the Python language is a cyclomatic complexity lower than 9.

How to fix it?

There are many reasons for Complex Method. Sometimes, another design approach is beneficial such as a) modeling state using an explicit state machine rather than conditionals, or b) using table lookup rather than long chains of logic. In other scenarios, the function can be split using EXTRACT FUNCTION. Just make sure you extract natural and cohesive functions. Complex Methods can also be addressed by identifying complex conditional expressions and then using the DECOMPOSE CONDITIONAL refactoring.

Helpful refactoring examples

To get a general understanding of what this code health issue looks like - and how it might be addressed - we have prepared some diffs for illustrative purposes.

SAMPLE

# complex_method.js
 function postItem(item) {
   if (!item.id) {
-    if (item.x != null && item.y != null) {
-      post(item);
-    } else {
-      throw Error("Item must have x and y");
-    }
+    // extract a separate function for creating new item
+    postNew(item);
   } else {
-    if (item.x < 10 && item.y > 25) {
-      put(item);
-    } else {
-      throw Error("Item must have an x and y value between 10 and 25");
-    }
+    // and one for updating existing items
+    updateItem(item);
   }
 }
+
+function postNew(item) {
+  validateNew(item);
+  post(item);
+}
+
+function updateItem(item) {
+  validateUpdate(item);
+  put(item);
+}
+

@coderabbitai

This comment was marked as resolved.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos

leynos commented May 26, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response.

.github/actions/generate-coverage/scripts/run_rust.py

Comment on lines +396 to +399

    output_path: typ.Annotated[
        Path | None, typer.Option(envvar="INPUT_OUTPUT_PATH")
    ] = None,
    features: typ.Annotated[str, typer.Option(envvar="INPUT_FEATURES")] = "",

❌ New issue: Complex Method
main has a cyclomatic complexity of 10, threshold = 9

@coderabbitai

This comment was marked as resolved.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos

leynos commented May 28, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph.

If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced.

Complex Method

.github/actions/generate-coverage/scripts/run_rust.py: main

What lead to degradation?

main has a cyclomatic complexity of 10, threshold = 9

Why does this problem occur?

A Complex Method has a high cyclomatic complexity. The recommended threshold for the Python language is a cyclomatic complexity lower than 9.

How to fix it?

There are many reasons for Complex Method. Sometimes, another design approach is beneficial such as a) modeling state using an explicit state machine rather than conditionals, or b) using table lookup rather than long chains of logic. In other scenarios, the function can be split using EXTRACT FUNCTION. Just make sure you extract natural and cohesive functions. Complex Methods can also be addressed by identifying complex conditional expressions and then using the DECOMPOSE CONDITIONAL refactoring.

Helpful refactoring examples

To get a general understanding of what this code health issue looks like - and how it might be addressed - we have prepared some diffs for illustrative purposes.

SAMPLE

# complex_method.js
 function postItem(item) {
   if (!item.id) {
-    if (item.x != null && item.y != null) {
-      post(item);
-    } else {
-      throw Error("Item must have x and y");
-    }
+    // extract a separate function for creating new item
+    postNew(item);
   } else {
-    if (item.x < 10 && item.y > 25) {
-      put(item);
-    } else {
-      throw Error("Item must have an x and y value between 10 and 25");
-    }
+    // and one for updating existing items
+    updateItem(item);
   }
 }
+
+function postNew(item) {
+  validateNew(item);
+  post(item);
+}
+
+function updateItem(item) {
+  validateUpdate(item);
+  put(item);
+}
+

@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Fetch the current run_rust.py from the PR branch
gh api repos/leynos/shared-actions/contents/.github/actions/generate-coverage/scripts/run_rust.py?ref=chore/bump-setup-uv-sha \
  --jq '.content' | base64 -d

Length of output: 16831



@leynos: The current branch already contains all four previously suggested helpers (_resolve_output_path, _compute_coverage_percent, _report_coverage, _resolve_bool_input). The remaining CC=10 comes entirely from:

  • Seven sequential or fallback chains (e.g. output_path = output_path or Path(_required_env(...))) — all structurally identical
  • One ternary for config_context
  • One and-guarded if block

Further extraction would be deleterious. Below is a suppression message for the CodeScene UI.


CodeScene suppression message

The residual cyclomatic complexity in main is a structural artefact of Typer's Annotated-option pattern combined with a required-env fallback layer, not genuine algorithmic branching. Seven of the ten decision points are homogeneous or short-circuit chains that resolve nullable CLI arguments against os.getenv — each identical in shape, trivial to read in sequence, and carrying negligible cognitive load. Cyclomatic complexity treats each or as an independent branch equivalent to a full if/else, which overstates the true comprehension cost of this uniform boilerplate.

All logically cohesive sub-concerns have already been extracted into dedicated private helpers (_resolve_bool_input, _resolve_output_path, _compute_coverage_percent, _report_coverage). The two remaining decision points — a ternary choosing between ensure_nextest_config() and contextlib.nullcontext(), and a single guard clause if with_cucumber_rs and cucumber_rs_features — are self-contained, named idioms that cannot be extracted without producing helpers of zero semantic value. Any further refactoring to satisfy the metric would reduce readability and increase indirection without improving correctness, testability, or maintainability.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos leynos marked this pull request as ready for review May 28, 2026 12:17
sourcery-ai[bot]

This comment was marked as resolved.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1b95aa3def

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/actions/generate-coverage/scripts/run_rust.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/actions/generate-coverage/scripts/run_rust.py:
- Around line 421-423: The current logic overwrites an explicitly passed
manifest_path with the DETECTED_CARGO_MANIFEST env var; change it so
manifest_path is only replaced by the environment value when no explicit value
was supplied (e.g., when manifest_path equals the default Path("Cargo.toml") or
is None). Locate the manifest_path parameter and the code that assigns from
DETECTED_CARGO_MANIFEST (the assignment around the existing use of
manifest_path) and wrap that override in a conditional that checks manifest_path
is the default before setting it from os.getenv("DETECTED_CARGO_MANIFEST"),
thereby preserving any explicit argument passed to the function.

In `@docs/local-validation-of-github-actions-with-act-and-pytest.md`:
- Around line 30-33: The guidance uses first/second-person pronouns ("your
sandbox", "use ... to") so update the sentences to an impersonal voice: rephrase
the lines that mention the socket and the command (referencing
ACT_WORKFLOW_TESTS and sudo -E make test) to remove "you/your" and "use", e.g.
state that commands that access the socket must run with permission and that, in
this repository, the workflow harness can be exercised by running the indicated
command when the sandbox requires elevated runtime access; apply the same
impersonal rewrite pattern to the other occurrence noted around lines 190-191.
- Around line 25-27: Remove the comma before "because" in the sentence that
begins "The pytest harness checks `GET /v1.41/containers/json?all=true`, because
this is the path `act` uses before starting a job." — edit the fragment in the
docs so it reads without the comma (i.e., "...checks `GET
/v1.41/containers/json?all=true` because this is the path `act` uses before
starting a job."), preserving the backtick-enclosed GET path and surrounding
punctuation.

In `@tests/workflows/conftest.py`:
- Around line 79-85: The parsing code should guard against empty/malformed
Docker API responses so import-time runtime discovery doesn't raise; update the
block that builds response -> head via response.partition and then status_line =
head.splitlines()[0].decode(...) to first ensure head.splitlines() is non-empty
and that parts = status_line.split(maxsplit=2) has at least 2 elements, and wrap
the int(parts[1]) conversion in a try/except (ValueError) to return a
probe-failure tuple (e.g., (0, response.decode(...))) when parsing fails instead
of letting IndexError/ValueError propagate; change checks around
head.splitlines(), status_line, parts and int(parts[1]) accordingly so callers
like _ACT_RUNTIME_STATUS initialization get a safe fallback.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7cf8f678-6de6-4b8a-b66e-7540f06c0b7c

📥 Commits

Reviewing files that changed from the base of the PR and between e202e43 and 1b95aa3.

📒 Files selected for processing (26)
  • .github/actions/determine-release-modes/action.yml
  • .github/actions/ensure-cargo-version/action.yml
  • .github/actions/export-cargo-metadata/action.yml
  • .github/actions/generate-coverage/action.yml
  • .github/actions/generate-coverage/scripts/merge_cobertura.py
  • .github/actions/generate-coverage/scripts/run_python.py
  • .github/actions/generate-coverage/scripts/run_rust.py
  • .github/actions/generate-coverage/tests/test_scripts.py
  • .github/actions/linux-packages/action.yml
  • .github/actions/macos-package/action.yml
  • .github/actions/ratchet-coverage/action.yml
  • .github/actions/release-to-pypi-uv/action.yml
  • .github/actions/release-to-pypi-uv/scripts/publish_release.py
  • .github/actions/rust-build-release/action.yml
  • .github/actions/setup-rust/action.yml
  • .github/actions/stage-release-artefacts/action.yml
  • .github/actions/upload-release-assets/action.yml
  • .github/actions/validate-linux-packages/action.yml
  • .github/workflows/ci.yml
  • .github/workflows/dependabot-automerge.yml
  • .github/workflows/rust-toy-app.yml
  • .github/workflows/test-rust-build-release-root-discovery.yml
  • Makefile
  • docs/local-validation-of-github-actions-with-act-and-pytest.md
  • tests/workflows/conftest.py
  • tests/workflows/test_conftest_runtime.py

Comment thread .github/actions/generate-coverage/scripts/run_rust.py
Comment thread .github/actions/generate-coverage/scripts/run_rust.py Outdated
Comment thread docs/local-validation-of-github-actions-with-act-and-pytest.md
Comment thread docs/local-validation-of-github-actions-with-act-and-pytest.md Outdated
Comment thread tests/workflows/conftest.py Outdated
codescene-delta-analysis[bot]

This comment was marked as outdated.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/actions/generate-coverage/scripts/run_python.py (1)

409-486: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Split main and unblock the failing quality gate.

Reduce this method to orchestration only. Extract input resolution and GITHUB_OUTPUT emission into helpers, then call them from main. The current shape still triggers the failing Large Method gate.

♻️ Proposed refactor
+def _resolve_main_inputs(
+    output_path: Path | None,
+    lang: str | None,
+    fmt: str | None,
+    github_output: Path | None,
+) -> tuple[Path, str, str, Path]:
+    resolved_output = output_path or Path(_required_env("INPUT_OUTPUT_PATH"))
+    resolved_lang = lang or _required_env("DETECTED_LANG")
+    resolved_fmt = fmt or _required_env("DETECTED_FMT")
+    resolved_gh_out = github_output or Path(_required_env("GITHUB_OUTPUT"))
+    return resolved_output, resolved_lang, resolved_fmt, resolved_gh_out
+
+
+def _write_github_output(github_output: Path, out: Path, percent: str) -> None:
+    with github_output.open("a") as fh:
+        fh.write(f"file={out}\n")
+        fh.write(f"percent={percent}\n")
+
 def main(
@@
 ) -> None:
@@
-    output_path = output_path or Path(_required_env("INPUT_OUTPUT_PATH"))
-    lang = lang or _required_env("DETECTED_LANG")
-    fmt = fmt or _required_env("DETECTED_FMT")
-    github_output = github_output or Path(_required_env("GITHUB_OUTPUT"))
+    output_path, lang, fmt, github_output = _resolve_main_inputs(
+        output_path, lang, fmt, github_output
+    )
@@
-    with github_output.open("a") as fh:
-        fh.write(f"file={out}\n")
-        fh.write(f"percent={percent}\n")
+    _write_github_output(github_output, out, percent)

As per coding guidelines: "Keep C90 / mccabe complexity ≤ 9" and "Follow single responsibility and CQRS (command/query segregation)".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/actions/generate-coverage/scripts/run_python.py around lines 409 -
486, The main function is too large and should be reduced to orchestration only:
extract the input resolution logic (resolving output_path, lang, fmt,
github_output via _required_env and calling _resolve_output_path) into a helper
like resolve_inputs(), and extract the GitHub Actions emission (opening
github_output and writing "file=" and "percent=") into a helper like
emit_github_output(path, percent); then update main to call resolve_inputs(),
call _run_coverage(fmt, out) and read_previous_coverage(baseline_file) and
finally call emit_github_output(out, percent). Keep existing calls to
_resolve_output_path, _run_coverage, and read_previous_coverage unchanged and
ensure out.parent.mkdir remains near orchestration where output_path is
available.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/workflows/conftest.py`:
- Around line 185-197: Replace the mutable global _ACT_RUNTIME_STATUS and its
manual lazy-init in _get_act_runtime_status with a cached no-arg function using
functools.cache: remove the _ACT_RUNTIME_STATUS global and change
_get_act_runtime_status to be a zero-argument function decorated with
functools.cache that calls _probe_act_runtime() on first invocation and returns
the result; keep the same function name (_get_act_runtime_status) and call sites
so behavior is unchanged while avoiding global mutation and Ruff PLW0603.

In `@tests/workflows/test_conftest_runtime.py`:
- Around line 119-154: The two tests use inconsistent environ argument styles
for conftest._probe_act_runtime: test_probe_reports_missing_docker_host_socket
calls _probe_act_runtime() with no args while
test_probe_reports_unreachable_docker_host_socket passes os.environ.copy();
since monkeypatch.setenv has already modified os.environ, change
test_probe_reports_unreachable_docker_host_socket to call
conftest._probe_act_runtime() with no arguments (keep monkeypatch.setenv and the
monkeypatched _read_unix_http), ensuring both tests consistently rely on the
global os.environ behavior.
- Around line 81-116: Hoist the repeated local imports by adding a single
module-level "import os" with the other imports at the top of the file, and
remove the per-test "import os" statements inside
test_docker_host_unix_socket_missing, test_docker_host_unix_socket_unreachable
(and the other test at the noted location); this keeps a single import for the
symbol used by conftest._docker_host_usable and related tests and eliminates
redundant imports.

---

Outside diff comments:
In @.github/actions/generate-coverage/scripts/run_python.py:
- Around line 409-486: The main function is too large and should be reduced to
orchestration only: extract the input resolution logic (resolving output_path,
lang, fmt, github_output via _required_env and calling _resolve_output_path)
into a helper like resolve_inputs(), and extract the GitHub Actions emission
(opening github_output and writing "file=" and "percent=") into a helper like
emit_github_output(path, percent); then update main to call resolve_inputs(),
call _run_coverage(fmt, out) and read_previous_coverage(baseline_file) and
finally call emit_github_output(out, percent). Keep existing calls to
_resolve_output_path, _run_coverage, and read_previous_coverage unchanged and
ensure out.parent.mkdir remains near orchestration where output_path is
available.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0b6a97f8-e29a-461a-b55f-3aef67c67ce4

📥 Commits

Reviewing files that changed from the base of the PR and between 1b95aa3 and 61a610c.

📒 Files selected for processing (8)
  • .github/actions/generate-coverage/scripts/common.py
  • .github/actions/generate-coverage/scripts/merge_cobertura.py
  • .github/actions/generate-coverage/scripts/run_python.py
  • .github/actions/generate-coverage/scripts/run_rust.py
  • .github/actions/release-to-pypi-uv/scripts/publish_release.py
  • docs/local-validation-of-github-actions-with-act-and-pytest.md
  • tests/workflows/conftest.py
  • tests/workflows/test_conftest_runtime.py

Comment thread tests/workflows/conftest.py Outdated
Comment thread tests/workflows/test_conftest_runtime.py Outdated
Comment thread tests/workflows/test_conftest_runtime.py Outdated
Update all `astral-sh/setup-uv` action and workflow references to the
requested commit SHA. Remove stale adjacent version comments so the pin is
not contradicted by old tag notes.
@leynos

leynos commented May 31, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Have the following now been resolved?

Annul any requirements that violate the en-GB-oxendict spelling (-ize / -yse / -our) conventions (for example a request to replace "normalize" with "normalise" or "artefact" with "artifact"), or where the requirement unnecessarily increases cyclomatic complexity.

Please address the comments from this code review:

## Overall Comments
- The runtime probe in tests/workflows/conftest.py is evaluated once at import time (`_ACT_RUNTIME_STATUS`), so any later changes to `ACT`, `DOCKER_HOST`, or related env vars in tests won’t be reflected in skip conditions or `run_act`; if per-test configuration is desirable, consider probing lazily (e.g. inside the skip predicate or `run_act`).
- The `_required_env` helper is duplicated across multiple scripts (run_rust.py, run_python.py, merge_cobertura.py); factoring this into a shared utility would reduce repetition and keep error handling/messages consistent.
- In run_rust.main, several parameters are both declared as Typer options with `envvar` and then overridden via `os.getenv` (e.g. `manifest_path`, `features`, `cucumber_rs_features`), which makes the precedence a bit hard to follow; simplifying this to a single source of truth per input (either Typer or explicit env reads) would make the behaviour clearer.

## Individual Comments

### Comment 1
<location path=".github/actions/generate-coverage/scripts/run_rust.py" line_range="101-105" />
<code_context>
+    raise typer.Exit(2)
+
+
+def _env_bool(name: str, *, default: bool) -> bool:
+    value = os.getenv(name)
+    if value is None or not value.strip():
+        return default
+    return value.strip().lower() in {"1", "true", "yes", "on"}
+
+
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Boolean env parsing now treats any non-recognized value as False, which may silently mask misconfiguration.

With `_env_bool`, any non-empty value not in `{1, true, yes, on}` now evaluates to `False`, so a typo like `tru` or `ye` would quietly disable a flag instead of failing. Consider either matching Typer’s accepted values or treating any non-empty, unrecognized value as an error to avoid silently masking misconfigurations.

Suggested implementation:

```python
def _required_env(name: str) -> str:
    value = os.getenv(name, "").strip()
    if value:
        return value
    typer.echo(f"Missing required environment variable: {name}", err=True)
    raise typer.Exit(2)


def _env_bool(name: str, *, default: bool) -> bool:
    value = os.getenv(name)
    if value is None or not value.strip():
        return default

    normalized = value.strip().lower()
    truthy_values = {"1", "true", "yes", "on"}
    falsy_values = {"0", "false", "no", "off"}

    if normalized in truthy_values:
        return True
    if normalized in falsy_values:
        return False

    typer.echo(
        f"Invalid boolean value for environment variable {name!r}: {value!r}. "
        f"Expected one of {sorted(truthy_values | falsy_values)} (case-insensitive).",
        err=True,
    )
    raise typer.Exit(2)

```

If `os` or `typer` are not already imported at the top of `.github/actions/generate-coverage/scripts/run_rust.py`, add:

- `import os`
- `import typer`

so that `_env_bool` can use them.
</issue_to_address>

### Comment 2
<location path=".github/actions/generate-coverage/scripts/merge_cobertura.py" line_range="20-25" />
<code_context>
-)
-OUTPUT_PATH_OPT = typer.Option(..., envvar="OUTPUT_PATH")
+
+def _required_env(name: str) -> str:
+    value = os.getenv(name, "").strip()
+    if value:
+        return value
+    typer.echo(f"Missing required environment variable: {name}", err=True)
+    raise typer.Exit(2)


</code_context>
<issue_to_address>
**suggestion:** The `_required_env` helper is duplicated across multiple scripts and could be centralized.

Similar `_required_env` helpers exist in `run_rust.py`, `run_python.py`, and `merge_cobertura.py`. If there’s a shared utilities module for these scripts, consider moving this helper there to avoid duplication and keep behavior (exit code, messaging) consistent.

Suggested implementation:

```python
import os
import typing as typ
from pathlib import Path

import typer
from plumbum.cmd import uvx
from plumbum.commands.processes import ProcessExecutionError

from common import _required_env

```

```python

```

To fully implement the centralization:

1. Create a new module in the same directory, e.g. `.github/actions/generate-coverage/scripts/common.py`, with:

   ```python
   import os
   import typer

   def _required_env(name: str) -> str:
       value = os.getenv(name, "").strip()
       if value:
           return value
       typer.echo(f"Missing required environment variable: {name}", err=True)
       raise typer.Exit(2)
   ```

2. In `run_rust.py` and `run_python.py`, remove their local `_required_env` definitions and add `from common import _required_env` alongside their other imports.

3. Ensure that all scripts are invoked in a way that allows importing `common` (e.g. by running them from the `scripts` directory or ensuring that directory is on `PYTHONPATH`). If this repo uses a different shared utilities module/path, adjust the import (`from common import _required_env`) to match that module instead.
</issue_to_address>

### Comment 3
<location path=".github/actions/release-to-pypi-uv/scripts/publish_release.py" line_range="82-91" />
<code_context>


-def cli(index: str = INDEX_OPTION) -> None:
+def cli(
+    index: typ.Annotated[
+        str,
+        typer.Option(
+            envvar="INPUT_UV_INDEX",
+            help="Optional index name or URL for uv publish.",
+        ),
+    ] = "",
+) -> None:
     """CLI entrypoint."""
-    main(index=index)
+    main(index=index or os.getenv("INPUT_UV_INDEX", ""))


</code_context>
<issue_to_address>
**issue:** CLI wrapper makes it impossible to override a non-empty INPUT_UV_INDEX with an explicitly empty value.

Since `cli` calls `main(index=index or os.getenv("INPUT_UV_INDEX", ""))`, passing `--index ""` can never clear a non-empty `INPUT_UV_INDEX`; the empty string is falsy so you always fall back to the env var. To support explicitly clearing the env value, consider using `None` as the "use env" sentinel (e.g. `index: str | None = None`) and only reading `INPUT_UV_INDEX` when `index is None`.
</issue_to_address>

### Comment 4
<location path="tests/workflows/conftest.py" line_range="88-97" />
<code_context>
+    return int(parts[1]), body.decode("utf-8", errors="replace")
+
+
+def _docker_host_usable(docker_host: str) -> tuple[bool, str]:
+    """Return whether act can list containers through *docker_host*."""
+    parsed = urllib.parse.urlparse(docker_host)
+    if parsed.scheme != "unix":
+        return True, ""
+
+    socket_path = Path(urllib.parse.unquote(parsed.path))
+    if not socket_path.exists():
+        return False, f"Docker API socket does not exist: {socket_path}"
+
+    try:
+        status, body = _read_unix_http(socket_path, _DOCKER_CONTAINERS_PATH)
+    except OSError as exc:
+        return False, f"Docker API socket is not reachable: {exc}"
+
+    if status != 200:
+        detail = body.strip() or f"HTTP {status}"
+        return False, f"Docker API cannot list containers: {detail}"
</code_context>
<issue_to_address>
**suggestion (testing):** Consider adding a test for a configured `DOCKER_HOST` Unix socket that does not exist or is unreachable to exercise the `_docker_host_usable` error paths.

`test_probe_reports_unhealthy_podman_docker_api` already covers the non-200 response case, but `_docker_host_usable` has additional branches (missing Unix socket and `OSError` on connect) that aren’t tested. Please add tests that:
- set `DOCKER_HOST` to a `unix://` URL with a non-existent path, and
- trigger an `OSError` from `_read_unix_http` (e.g., via monkeypatch),
then assert `ActRuntimeStatus.available` is `False` and that `reason` starts with the expected `

Suggested implementation:

```python
def _docker_host_usable(docker_host: str) -> tuple[bool, str]:
    """Return whether act can list containers through *docker_host*."""
    parsed = urllib.parse.urlparse(docker_host)
    if parsed.scheme != "unix":
        return True, ""

    socket_path = Path(urllib.parse.unquote(parsed.path))
    if not socket_path.exists():
        return False, f"Docker API socket does not exist: {socket_path}"

    try:
        status, body = _read_unix_http(socket_path, _DOCKER_CONTAINERS_PATH)
    except OSError as exc:
        return False, f"Docker API socket is not reachable: {exc}"

    if status != 200:
        detail = body.strip() or f"HTTP {status}"
        return False, f"Docker API cannot list containers: {detail}"
    return True, ""


def test_docker_host_unix_socket_missing(monkeypatch) -> None:
    """DOCKER_HOST=unix://… with a non-existent socket path reports a clear error."""
    import os

    docker_host = "unix:///this/path/does/not/exist.sock"
    monkeypatch.setenv("DOCKER_HOST", docker_host)

    usable, reason = _docker_host_usable(os.environ["DOCKER_HOST"])

    assert usable is False
    assert reason.startswith("Docker API socket does not exist:")


def test_docker_host_unix_socket_unreachable(monkeypatch, tmp_path) -> None:
    """DOCKER_HOST=unix://… with an unreachable socket surfaces the OSError."""
    import os
    import sys

    socket_path = tmp_path / "docker.sock"
    socket_path.touch()

    docker_host = f"unix://{socket_path}"
    monkeypatch.setenv("DOCKER_HOST", docker_host)

    def _raise_oserror(*_args, **_kwargs):
        raise OSError("test unreachable docker socket")

    # Patch _read_unix_http in this module to simulate an unreachable socket.
    monkeypatch.setattr(sys.modules[__name__], "_read_unix_http", _raise_oserror)

    usable, reason = _docker_host_usable(os.environ["DOCKER_HOST"])

    assert usable is False
    assert reason.startswith("Docker API socket is not reachable:")


def _container_runtime_available() -> bool:
    """Return True if a container runtime (docker/podman) is available."""

```

If your runtime-probing logic wraps `_docker_host_usable` and returns an `ActRuntimeStatus` object, you may also want to:
1. Add parallel tests (or adapt the above ones) that call the actual probe function and assert `ActRuntimeStatus.available is False` and `ActRuntimeStatus.reason.startswith("Docker API socket does not exist:")` / `"Docker API socket is not reachable:"`.
2. Import that probe function and `ActRuntimeStatus` type into the appropriate test module, or move these tests from `conftest.py` into the existing `test_probe_*.py` module to keep all probe tests together.
</issue_to_address>

### Comment 5
<location path=".github/actions/generate-coverage/scripts/run_rust.py" line_range="407" />
<code_context>
+    raise typer.Exit(2)


 def main(
-    rust_file: Path = RUST_FILE_OPT,
-    python_file: Path = PYTHON_FILE_OPT,
</code_context>
<issue_to_address>
**issue (complexity):** Consider simplifying configuration handling by removing the dual Typer+manual env resolution and routing all CLI vs environment behavior through a single, centralized path (including booleans).

You can keep the new behaviour while simplifying the configuration surface by removing the “dual path” resolution you’ve introduced (Typer `envvar` + manual env reading) and consolidating on a single strategy.

### 1. Avoid double-reading env for options that already have `envvar`

Right now, you define options with `envvar` and then immediately re-read the same variables:

```python
output_path = output_path or Path(_required_env("INPUT_OUTPUT_PATH"))
lang = lang or _required_env("DETECTED_LANG")
fmt = fmt or _required_env("DETECTED_FMT")
github_output = github_output or Path(_required_env("GITHUB_OUTPUT"))
features = features or os.getenv("INPUT_FEATURES", "")
...
with_default = _resolve_bool_input(
    with_default, "INPUT_WITH_DEFAULT_FEATURES", default=True
)
```

Since Typer is already wired to those envvars, this creates two sources of truth and extra branching.

**Actionable simplification:** drop the `envvar=` bindings for the options you *manually* resolve, and treat Typer purely as CLI parsing. All env behaviour then lives in one place (your helpers).

For example:

```python
def main(
    output_path: Path | None = typer.Option(None),
    lang: str | None = typer.Option(None),
    fmt: str | None = typer.Option(None),
    github_output: Path | None = typer.Option(None),
    features: str = typer.Option(""),
    with_default: bool | None = typer.Option(None),
    use_nextest: bool | None = typer.Option(None),
    with_cucumber_rs: bool | None = typer.Option(None),
    # ... other options unchanged
) -> None:
    output_path = output_path or Path(_required_env("INPUT_OUTPUT_PATH"))
    lang = lang or _required_env("DETECTED_LANG")
    fmt = fmt or _required_env("DETECTED_FMT")
    github_output = github_output or Path(_required_env("GITHUB_OUTPUT"))
    features = features or os.getenv("INPUT_FEATURES", "")
    with_default = _resolve_bool_input(
        with_default, "INPUT_WITH_DEFAULT_FEATURES", default=True
    )
    use_nextest = _resolve_bool_input(
        use_nextest, "INPUT_USE_CARGO_NEXTEST", default=True
    )
    with_cucumber_rs = _resolve_bool_input(
        with_cucumber_rs, "INPUT_WITH_CUCUMBER_RS", default=False
    )
    ...
```

This keeps current semantics (CLI wins over env; some vars required; custom boolean parsing), but now there’s only one place where env is consulted, and no confusion about precedence.

### 2. Centralise the boolean handling even more

You already have `_env_bool` and `_resolve_bool_input`, but you still mix Typer’s boolean parsing and your own. Once you drop `envvar=` from those options, all booleans go through one simple path:

```python
def _resolve_bool_input(
    value: bool | None,  # noqa: FBT001
    envvar: str,
    *,
    default: bool,
) -> bool:
    if value is not None:
        return value
    return _env_bool(envvar, default=default)
```

You can then make the intent clearer by grouping the boolean resolution:

```python
with_default = _resolve_bool_input(
    with_default, "INPUT_WITH_DEFAULT_FEATURES", default=True
)
use_nextest = _resolve_bool_input(
    use_nextest, "INPUT_USE_CARGO_NEXTEST", default=True
)
with_cucumber_rs = _resolve_bool_input(
    with_cucumber_rs, "INPUT_WITH_CUCUMBER_RS", default=False
)
```

No behaviour change, but the reader no longer has to mentally merge “Typer bool semantics” with “custom bool semantics”.

### 3. Optional: consistent env access for string options

For string inputs that also have env-var fallbacks, you can apply the same “Typer is CLI-only” rule:

```python
features: str = typer.Option(""),
cucumber_rs_features: str = typer.Option(""),
cucumber_rs_args: str = typer.Option(""),
```

and in `main`:

```python
features = features or os.getenv("INPUT_FEATURES", "")
cucumber_rs_features = cucumber_rs_features or os.getenv(
    "INPUT_CUCUMBER_RS_FEATURES", ""
)
cucumber_rs_args = cucumber_rs_args or os.getenv("INPUT_CUCUMBER_RS_ARGS", "")
```

Again, this keeps all functionality, but there’s a single, predictable path for configuration resolution:  
- CLI args via Typer  
- else env via helper / `os.getenv`  
- else defaults.
</issue_to_address>

### Comment 6
<location path=".github/actions/generate-coverage/scripts/run_python.py" line_range="56" />
<code_context>
-)
-OUTPUT_PATH_OPT = typer.Option(..., envvar="OUTPUT_PATH")
+
+def _required_env(name: str) -> str:
+    value = os.getenv(name, "").strip()
+    if value:
</code_context>
<issue_to_address>
**issue (complexity):** Consider relying on Typer’s required-with-envvar options instead of a custom `_required_env` helper and manual fallback logic in `main` to simplify configuration handling.

You can keep the new `Annotated` style and preserve behavior while dropping `_required_env` and the manual resolution logic, letting Typer enforce required envvars directly. That removes branching in `main` and an extra error path.

### Suggested simplification

Instead of making the options optional and resolving them manually:

```python
def _required_env(name: str) -> str:
    value = os.getenv(name, "").strip()
    if value:
        return value
    typer.echo(f"Missing required environment variable: {name}", err=True)
    raise typer.Exit(2)

def main(
    output_path: typ.Annotated[
        Path | None, typer.Option(envvar="INPUT_OUTPUT_PATH")
    ] = None,
    lang: typ.Annotated[str | None, typer.Option(envvar="DETECTED_LANG")] = None,
    fmt: typ.Annotated[str | None, typer.Option(envvar="DETECTED_FMT")] = None,
    github_output: typ.Annotated[
        Path | None, typer.Option(envvar="GITHUB_OUTPUT")
    ] = None,
    baseline_file: typ.Annotated[
        Path | None, typer.Option(envvar="BASELINE_PYTHON_FILE")
    ] = None,
) -> None:
    output_path = output_path or Path(_required_env("INPUT_OUTPUT_PATH"))
    lang = lang or _required_env("DETECTED_LANG")
    fmt = fmt or _required_env("DETECTED_FMT")
    github_output = github_output or Path(_required_env("GITHUB_OUTPUT"))
    ...
```

let Typer treat the core options as required-with-envvar:

```python
def main(
    output_path: typ.Annotated[
        Path,
        typer.Option(
            envvar="INPUT_OUTPUT_PATH",
            help="Destination path for the coverage output file.",
        ),
    ] = ...,
    lang: typ.Annotated[
        str,
        typer.Option(
            envvar="DETECTED_LANG",
            help='Detected project language: "rust", "python", or "mixed".',
        ),
    ] = ...,
    fmt: typ.Annotated[
        str,
        typer.Option(
            envvar="DETECTED_FMT",
            help='Coverage format: "slipcover", "coveragepy", etc.',
        ),
    ] = ...,
    github_output: typ.Annotated[
        Path,
        typer.Option(
            envvar="GITHUB_OUTPUT",
            help="Path to the GitHub Actions output file.",
        ),
    ] = ...,
    baseline_file: typ.Annotated[
        Path | None,
        typer.Option(
            envvar="BASELINE_PYTHON_FILE",
            help="Optional path to a previous coverage baseline file.",
        ),
    ] = None,
) -> None:
    out = _resolve_output_path(output_path, lang)
    out.parent.mkdir(parents=True, exist_ok=True)
    percent = _run_coverage(fmt, out)
    ...
```

Then you can delete `_required_env` entirely. This keeps:

- CLI args still override env vars (Typer’s default behavior).
- Missing required env vars/args still produce a clear error (Typer’s validation).
- `main` stays linear and focused on coverage behavior instead of configuration plumbing.
</issue_to_address>

### Comment 7
<location path="docs/local-validation-of-github-actions-with-act-and-pytest.md" line_range="33" />
<code_context>
+  3. Commands that talk to the socket (such as `act …` or the pytest harness)
+     run with permission to access it. In this repo, use
+     `ACT_WORKFLOW_TESTS=1 sudo -E make test` to exercise the workflow harness
+     when your sandbox requires elevated runtime access.
+  4. The release workflow now redirects `uv` caches and the project virtualenv
      to `/tmp` when it detects it is running under `act`, so the container no
</code_context>
<issue_to_address>
**issue (review_instructions):** The phrase "your sandbox" uses a second-person pronoun, which conflicts with the instruction to avoid first- and second-person pronouns.

Consider rephrasing to avoid second-person phrasing, for example: "when the sandbox requires elevated runtime access" or similar impersonal wording.

<details>
<summary>Review instructions:</summary>

**Path patterns:** `**/*.md`

**Instructions:**
Avoid 2nd person or 1st person pronouns ("I", "you", "we").

</details>
</issue_to_address>

Remove an invalid dead_code expectation from rust-toy-app's build script now
that the included CLI module is used for manpage generation.

Replace the broad generate-coverage GITHUB_OUTPUT key checks with a syrupy
snapshot that records the exact file and percent output format.
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos

leynos commented Jun 2, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@leynos

leynos commented Jun 2, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Add direct tests for the workflow runtime command availability and command
success helpers using real local process boundaries, complementing the existing
act runtime orchestration tests.
codescene-delta-analysis[bot]

This comment was marked as outdated.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/workflows/test_conftest_runtime.py (1)

113-180: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Parametrize the DOCKER_HOST failure-path coverage.

Fold these negative-path tests into parametrized helper/probe matrices. The current layout repeats the same monkeypatch wiring and makes new socket cases harder to keep aligned across _docker_host_usable() and _probe_act_runtime().

As per coding guidelines, "Replace duplicate tests with @pytest.mark.parametrize" and "Use pytest idioms. Prefer fixtures to setup/teardown methods. Parametrize broadly."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/workflows/test_conftest_runtime.py` around lines 113 - 180, The tests
duplicate failure-path wiring for DOCKER_HOST; consolidate them into
parametrized tests that run both _docker_host_usable and _probe_act_runtime
scenarios for the same failure cases (missing socket and unreachable socket).
Create a pytest.mark.parametrize over cases like
("unix:///nonexistent/path.sock", "missing") and (f"unix://{socket_path}",
"unreachable") and in the test body set the same monkeypatches: setenv for
DOCKER_HOST, monkeypatch _command_available when probing, and monkeypatch
_read_unix_http to raise OSError for the unreachable case; then assert expected
usable/available flags and that reason contains "Docker API socket does not
exist:" or "Docker API socket is not reachable:" for _docker_host_usable and
_probe_act_runtime respectively, reusing the same parameter matrix to keep
coverage aligned.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/workflows/test_conftest_runtime.py`:
- Around line 30-44: Replace the three near-duplicate tests
(test_command_succeeds_reports_successful_command,
test_command_succeeds_reports_failed_command,
test_command_succeeds_reports_missing_command) with a single
pytest.mark.parametrize test that calls conftest._command_succeeds with each
case; parametrize the cases: (sys.executable, "-c", "pass") -> True,
(sys.executable, "-c", "import sys; sys.exit(3)") -> False, and
("definitely-not-a-real-command-for-tests",) -> False, and assert the expected
boolean for each row (add clear ids for readability).

---

Outside diff comments:
In `@tests/workflows/test_conftest_runtime.py`:
- Around line 113-180: The tests duplicate failure-path wiring for DOCKER_HOST;
consolidate them into parametrized tests that run both _docker_host_usable and
_probe_act_runtime scenarios for the same failure cases (missing socket and
unreachable socket). Create a pytest.mark.parametrize over cases like
("unix:///nonexistent/path.sock", "missing") and (f"unix://{socket_path}",
"unreachable") and in the test body set the same monkeypatches: setenv for
DOCKER_HOST, monkeypatch _command_available when probing, and monkeypatch
_read_unix_http to raise OSError for the unreachable case; then assert expected
usable/available flags and that reason contains "Docker API socket does not
exist:" or "Docker API socket is not reachable:" for _docker_host_usable and
_probe_act_runtime respectively, reusing the same parameter matrix to keep
coverage aligned.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 47596995-aa4e-4b2d-a15c-9915be8b6e28

📥 Commits

Reviewing files that changed from the base of the PR and between 4cd3a45 and 8321f74.

📒 Files selected for processing (1)
  • tests/workflows/test_conftest_runtime.py

Comment thread tests/workflows/test_conftest_runtime.py Outdated
Collapse duplicate command success probes into a single parametrized test and
share the Docker host failure matrix across helper and act runtime probe checks.
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos

leynos commented Jun 2, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@leynos

leynos commented Jun 2, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/workflows/test_conftest_runtime.py`:
- Around line 48-54: The inline noqa on the parameter `expected: bool  # noqa:
FBT001` in test_command_succeeds_reports_command_status lacks a justification;
update the suppression to include a short reason (e.g., "# noqa: FBT001 - test
uses a boolean literal for clarity in parametrized cases") so it documents why
the FBT001 rule is intentionally bypassed; edit the test in
tests/workflows/test_conftest_runtime.py next to the `expected` parameter and
keep the scope narrow to that token while preserving the existing signature and
call to conftest._command_succeeds.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5adb80c8-9e88-43dd-a8e2-a815dacb4d6d

📥 Commits

Reviewing files that changed from the base of the PR and between 8321f74 and 35558e1.

📒 Files selected for processing (1)
  • tests/workflows/test_conftest_runtime.py

Comment thread tests/workflows/test_conftest_runtime.py Outdated
Document why the parametrized command status test intentionally uses boolean
literal cases while suppressing FBT001.
codescene-delta-analysis[bot]

This comment was marked as outdated.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/workflows/test_conftest_runtime.py`:
- Around line 53-54: The parametrized assertion in
tests/workflows/test_conftest_runtime.py uses a bare assert for
conftest._command_succeeds(command, *args) is expected; update this to include a
descriptive failure message that embeds the command, args and expected value so
test failures show context (e.g., include command, args, and expected in the
message) — change the assert to use the comma form with a clear message
referencing conftest._command_succeeds, command and args.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d251190e-d511-40e8-b41e-242074579cf4

📥 Commits

Reviewing files that changed from the base of the PR and between 35558e1 and 0d6a09d.

📒 Files selected for processing (1)
  • tests/workflows/test_conftest_runtime.py

Comment thread tests/workflows/test_conftest_runtime.py Outdated
@leynos

leynos commented Jun 2, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

The parametrized assert in test_command_succeeds_reports_command_status
used a bare `assert ... is expected` with no failure message, making
failures opaque.  Embed command, args, and expected value in the message.
codescene-delta-analysis[bot]

This comment was marked as outdated.

Add spaces around table column separators (MD060), wrap
over-length table rows in disable/enable directives (MD013),
and deduplicate "Observability" and "Public API" headings
(MD024) across developers-guide.md and generate-coverage-design.md.
@leynos leynos merged commit 42267e3 into main Jun 2, 2026
25 checks passed
@leynos leynos deleted the chore/bump-setup-uv-sha branch June 2, 2026 21:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant