Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the repository’s Rhiza template reference to v0.13.3, syncs template-managed files, and introduces new workflow “stub” files plus expanded template-bundle validation tests.
Changes:
- Bump Rhiza template ref/lock to
v0.13.3and Rhiza tool version to0.15.0. - Add
.rhiza/stubs/workflows/*and adjust template-bundle tests to support{source,dest}file entries. - Remove the
configure-git-authcomposite action and reduce some workflow-structure assertions in Rhiza API tests.
Reviewed changes
Copilot reviewed 12 out of 20 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
.rhiza/template.yml |
Updates template branch to v0.13.3. |
.rhiza/template.lock |
Updates locked template SHA/ref and replaces tracked .github/workflows/rhiza_*.yml with stub workflow paths. |
.rhiza/.rhiza-version |
Bumps Rhiza CLI version to 0.15.0. |
.rhiza/stubs/workflows/rhiza_book.yml |
Adds stub delegating to Rhiza reusable “book” workflow. |
.rhiza/stubs/workflows/rhiza_ci.yml |
Adds stub delegating to Rhiza reusable “ci” workflow. |
.rhiza/stubs/workflows/rhiza_codeql.yml |
Adds stub delegating to Rhiza reusable “codeql” workflow. |
.rhiza/stubs/workflows/rhiza_marimo.yml |
Adds stub delegating to Rhiza reusable “marimo” workflow. |
.rhiza/stubs/workflows/rhiza_release.yml |
Adds stub delegating to Rhiza reusable “release” workflow. |
.rhiza/stubs/workflows/rhiza_sync.yml |
Adds stub delegating to Rhiza reusable “sync” workflow. |
.rhiza/stubs/workflows/rhiza_weekly.yml |
Adds stub delegating to Rhiza reusable “weekly” workflow. |
.rhiza/tests/structure/test_template_bundles.py |
Adds richer bundle validation (cycle detection, overlays, ownership conflicts) and supports dict file entries. |
.rhiza/tests/api/test_weekly_workflow.py |
Removes job/delegation assertions, leaving an empty “jobs present” section. |
.rhiza/tests/api/test_release_workflow.py |
Removes job/delegation assertions, leaving only trigger/permission checks. |
.github/actions/configure-git-auth/README.md |
Deletes the action documentation. |
.github/actions/configure-git-auth/action.yml |
Deletes the composite action implementation. |
.rhiza/tests/structure/test_template_bundles.py.rej |
Conflict artifact (rejected hunks) added. |
.rhiza/tests/api/test_weekly_workflow.py.rej |
Conflict artifact (rejected hunks) added. |
.rhiza/tests/api/test_release_workflow.py.rej |
Conflict artifact (rejected hunks) added. |
.rhiza/tests/api/test_ci_workflow.py.rej |
Conflict artifact (rejected hunks) added. |
.rhiza/.rhiza-version.rej |
Conflict artifact (rejected hunks) added. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+1
to
+54
| diff a/.rhiza/tests/structure/test_template_bundles.py b/.rhiza/tests/structure/test_template_bundles.py (rejected hunks) | ||
| @@ -14,6 +14,30 @@ import pytest | ||
| import yaml | ||
|
|
||
|
|
||
| +def _resolve_path(entry: str | dict) -> str: | ||
| + """Return the source path from a file entry (string or {source, dest} dict).""" | ||
| + if isinstance(entry, dict): | ||
| + return entry["source"] | ||
| + return entry | ||
| + | ||
| + | ||
| +def _find_cycle(start: str, bundles: dict, visited: set, path: list) -> list | None: | ||
| + """DFS helper returning the cycle path (e.g. ['A', 'B', 'A']) if one exists, else None.""" | ||
| + visited.add(start) | ||
| + path.append(start) | ||
| + for dep in bundles.get(start, {}).get("requires", []): | ||
| + if dep not in bundles: | ||
| + continue | ||
| + if dep in path: | ||
| + return [*path[path.index(dep) :], dep] | ||
| + if dep not in visited: | ||
| + result = _find_cycle(dep, bundles, visited, path) | ||
| + if result: | ||
| + return result | ||
| + path.pop() | ||
| + return None | ||
| + | ||
| + | ||
| class TestTemplateBundles: | ||
| """Tests for template-bundles.yml validation.""" | ||
|
|
||
| @@ -66,10 +90,10 @@ class TestTemplateBundles: | ||
|
|
||
| for file_path in files: | ||
| total_files += 1 | ||
| - path = root / file_path | ||
| + path = root / _resolve_path(file_path) | ||
|
|
||
| if not path.exists(): | ||
| - all_missing.append((bundle_name, file_path)) | ||
| + all_missing.append((bundle_name, _resolve_path(file_path))) | ||
|
|
||
| # Report results | ||
| if all_missing: | ||
| @@ -90,10 +114,10 @@ class TestTemplateBundles: | ||
| missing_in_bundle = [] | ||
|
|
||
| for file_path in files: | ||
| - path = root / file_path | ||
| + path = root / _resolve_path(file_path) | ||
|
|
||
| if not path.exists(): | ||
| - missing_in_bundle.append(file_path) |
Comment on lines
+1
to
+5
| diff a/.rhiza/tests/api/test_weekly_workflow.py b/.rhiza/tests/api/test_weekly_workflow.py (rejected hunks) | ||
| @@ -106,99 +106,6 @@ class TestWeeklyWorkflowStructure: | ||
|
|
||
| # --- jobs present --- | ||
|
|
Comment on lines
+1
to
+38
| diff a/.rhiza/tests/api/test_release_workflow.py b/.rhiza/tests/api/test_release_workflow.py (rejected hunks) | ||
| @@ -63,93 +63,7 @@ class TestReleaseWorkflowStructure: | ||
| tags = push.get("tags", []) | ||
| assert any("v*" in tag for tag in tags), "Workflow must trigger on v* tags" | ||
|
|
||
| - def test_workflow_defines_all_expected_jobs(self, workflow): | ||
| - """Workflow must define all expected jobs including update-changelog.""" | ||
| - defined_jobs = set(workflow["jobs"].keys()) | ||
| - for job in EXPECTED_JOBS: | ||
| - assert job in defined_jobs, f"Job '{job}' not found in workflow" | ||
| - | ||
| def test_workflow_has_contents_write_permission(self, workflow): | ||
| """Workflow must have contents: write permission to push CHANGELOG.md.""" | ||
| permissions = workflow.get("permissions", {}) | ||
| assert permissions.get("contents") == "write", "Workflow must have contents: write permission" | ||
| - | ||
| - | ||
| -class TestUpdateChangelogJob: | ||
| - """Validate the update-changelog job in the release workflow.""" | ||
| - | ||
| - @pytest.fixture(scope="class") | ||
| - def workflow(self, root): | ||
| - """Load and return the parsed release workflow YAML.""" | ||
| - return _load_workflow(root) | ||
| - | ||
| - @pytest.fixture(scope="class") | ||
| - def job(self, workflow): | ||
| - """Return the update-changelog job definition.""" | ||
| - assert "update-changelog" in workflow["jobs"], "update-changelog job must exist" | ||
| - return workflow["jobs"]["update-changelog"] | ||
| - | ||
| - def test_update_changelog_job_exists(self, workflow): | ||
| - """update-changelog job must be present in the workflow.""" | ||
| - assert "update-changelog" in workflow["jobs"] | ||
| - | ||
| - def test_update_changelog_needs_draft_release(self, job): | ||
| - """update-changelog must depend on draft-release to ensure notes are ready.""" | ||
| - needs = job.get("needs", []) |
Comment on lines
+1
to
+70
| diff a/.rhiza/tests/api/test_ci_workflow.py b/.rhiza/tests/api/test_ci_workflow.py (rejected hunks) | ||
| @@ -3,50 +3,12 @@ | ||
| from __future__ import annotations | ||
|
|
||
| import json | ||
| -from pathlib import Path | ||
|
|
||
| -import pytest | ||
| -import yaml | ||
| from api.conftest import run_make | ||
|
|
||
| -WORKFLOW_PATH = Path(".github") / "workflows" / "rhiza_ci.yml" | ||
| MULTI_OS_MATRIX = 'RHIZA_CI_OS_MATRIX=["ubuntu-latest","windows-latest"]' | ||
|
|
||
|
|
||
| -def _load_workflow(root: Path) -> dict: | ||
| - """Load and parse the CI workflow YAML file.""" | ||
| - workflow_file = root / WORKFLOW_PATH | ||
| - if not workflow_file.exists(): | ||
| - pytest.fail(f"Workflow file not found: {workflow_file}") | ||
| - with open(workflow_file) as fh: | ||
| - return yaml.safe_load(fh) | ||
| - | ||
| - | ||
| -def test_ci_workflow_uses_generated_os_matrix(root): | ||
| - """CI test job must read its OS matrix from generate-matrix job output.""" | ||
| - workflow = _load_workflow(root) | ||
| - test_job = workflow["jobs"]["test"] | ||
| - matrix = test_job["strategy"]["matrix"] | ||
| - assert matrix["os"] == "${{ fromJson(needs.generate-matrix.outputs.os_matrix) }}" | ||
| - | ||
| - | ||
| -def test_ci_workflow_defines_os_matrix_output(root): | ||
| - """generate-matrix job must expose an os_matrix output from the os step.""" | ||
| - workflow = _load_workflow(root) | ||
| - outputs = workflow["jobs"]["generate-matrix"]["outputs"] | ||
| - assert outputs["os_matrix"] == "${{ steps.os.outputs.list }}" | ||
| - | ||
| - | ||
| -def test_ci_workflow_generates_os_matrix_via_make_target(root): | ||
| - """OS matrix generation must delegate to the dedicated Make target.""" | ||
| - workflow = _load_workflow(root) | ||
| - steps = workflow["jobs"]["generate-matrix"]["steps"] | ||
| - os_step = next((step for step in steps if step.get("id") == "os"), None) | ||
| - assert os_step is not None, "Expected a step with id='os' in generate-matrix job" | ||
| - run = os_step["run"] | ||
| - assert "ci-os-matrix" in run | ||
| - | ||
| - | ||
| def test_ci_os_matrix_make_target_defaults_to_ubuntu_when_env_missing(logger): | ||
| """ci-os-matrix target must default to ubuntu-latest when env value is absent.""" | ||
| result = run_make(logger, ["-f", ".rhiza/rhiza.mk", "RHIZA_CI_OS_MATRIX=", "ci-os-matrix"], dry_run=False) | ||
| @@ -63,17 +25,3 @@ def test_ci_os_matrix_make_target_can_be_configured(logger): | ||
| ) | ||
| assert result.returncode == 0 | ||
| assert json.loads(result.stdout.strip()) == ["ubuntu-latest", "windows-latest"] | ||
| - | ||
| - | ||
| -def test_ci_test_job_retries_uv_install_on_failure(root): | ||
| - """Test job must retry uv setup when the first attempt fails.""" | ||
| - workflow = _load_workflow(root) | ||
| - steps = workflow["jobs"]["test"]["steps"] | ||
| - | ||
| - install_step = next((step for step in steps if step.get("id") == "install-uv"), None) | ||
| - assert install_step is not None, "Expected an install-uv step in test job" | ||
| - assert install_step.get("continue-on-error") is True | ||
| - | ||
| - retry_step = next((step for step in steps if step.get("name") == "Retry uv installation"), None) | ||
| - assert retry_step is not None, "Expected a retry step for uv setup in test job" | ||
| - assert retry_step.get("if") == "steps.install-uv.outcome == 'failure'" |
Comment on lines
+1
to
+4
| diff a/.rhiza/.rhiza-version b/.rhiza/.rhiza-version (rejected hunks) | ||
| @@ -1 +1 @@ | ||
| -0.14.1 | ||
| +0.15.0 |
Comment on lines
93
to
94
|
|
||
|
|
Comment on lines
56
to
59
| def test_workflow_has_contents_write_permission(self, workflow): | ||
| """Workflow must have contents: write permission to push CHANGELOG.md.""" | ||
| permissions = workflow.get("permissions", {}) | ||
| assert permissions.get("contents") == "write", "Workflow must have contents: write permission" |
Comment on lines
+42
to
+48
| - .rhiza/stubs/workflows/rhiza_book.yml | ||
| - .rhiza/stubs/workflows/rhiza_ci.yml | ||
| - .rhiza/stubs/workflows/rhiza_codeql.yml | ||
| - .rhiza/stubs/workflows/rhiza_marimo.yml | ||
| - .rhiza/stubs/workflows/rhiza_release.yml | ||
| - .rhiza/stubs/workflows/rhiza_sync.yml | ||
| - .rhiza/stubs/workflows/rhiza_weekly.yml |
Comment on lines
172
to
+177
| for bundle_name in local_bundles: | ||
| bundle_config = bundles.get(bundle_name, {}) | ||
| for file_path in bundle_config.get("files", []): | ||
| if ".github/workflows/" in file_path: | ||
| workflow_files.append(f" [{bundle_name}] {file_path}") | ||
| resolved = _resolve_path(file_path) | ||
| if ".github/workflows/" in resolved: | ||
| workflow_files.append(f" [{bundle_name}] {resolved}") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
make syncGenerated with Claude Code