Skip to content

Add policies validation workflow#2

Merged
ringods merged 3 commits into
mainfrom
add-policy-validation
May 18, 2026
Merged

Add policies validation workflow#2
ringods merged 3 commits into
mainfrom
add-policy-validation

Conversation

@ringods
Copy link
Copy Markdown
Contributor

@ringods ringods commented May 18, 2026

Summary by Sourcery

Introduce automated validation, testing, and release support for Updatecli policies, including CI integration.

New Features:

  • Add a Bash script to validate, test, and optionally publish Updatecli policies, including file/metadata checks and changelog consistency.
  • Add a Python-based documentation generator that discovers policies and builds a POLICIES.md summary table from their metadata.

Enhancements:

  • Introduce Makefile targets to run policy validation, end-to-end tests, and publishing workflows locally and in CI.

CI:

  • Add a GitHub Actions workflow to validate policies on pushes and pull requests, and to run end-to-end tests on the main branch using GitHub App credentials.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 18, 2026

Reviewer's Guide

Adds a new validation and release workflow for Updatecli policies, including a Bash script to validate and optionally publish policies, a Python doc generator for policy metadata, a GitHub Actions workflow to run tests and e2e checks, and Makefile targets to orchestrate these operations.

Sequence diagram for the new policy validation and release workflow

sequenceDiagram
    actor Developer
    participant GitHubActions
    participant Makefile
    participant release_bash as release.bash
    participant updatecli as UpdatecliCLI

    Developer->>GitHubActions: push / pull_request
    GitHubActions->>Makefile: make test
    Makefile->>release_bash: .ci/scripts/release.bash
    loop For each Policy.yaml
        release_bash->>release_bash: validateRequiredFile
        alt e2e tests on main
            GitHubActions->>Makefile: make e2e-test
            Makefile->>release_bash: .ci/scripts/release.bash --e2e-test
            release_bash->>release_bash: runUpdatecliDiff
            release_bash->>updatecli: updatecli diff
        end
        alt publish
            Developer->>Makefile: make release
            Makefile->>release_bash: .ci/scripts/release.bash --publish
            release_bash->>updatecli: updatecli manifest push
        end
    end
Loading

Flow diagram for the policy documentation generation script

flowchart TD
    A[Start docgen.py] --> B[find_policy_yaml]
    B --> C{Policy.yaml files found?}
    C -- No --> D[Print 'No Policy.yaml files found.'] --> Z[End]
    C -- Yes --> E[For each Policy.yaml: load_policy_metadata]
    E --> F[generate_markdown_table]
    F --> G[Write POLICIES.md]
    G --> Z[End]
Loading

File-Level Changes

Change Details Files
Introduce a Bash script to validate Updatecli policies, run tests, and optionally publish them to an OCI registry.
  • Discover all Policy.yaml files under a configurable policies root directory and iterate over each policy directory.
  • Implement validation of required files (values.yaml, README.md, Policy.yaml, CHANGELOG.md) and the updatecli.d directory for each policy.
  • Parse Policy.yaml and CHANGELOG.md to enforce required metadata fields (source, documentation, url, version) and ensure version consistency with changelog entries.
  • Provide switches for unit-style validation, e2e diff tests using updatecli diff, and publishing policies via updatecli manifest push, while aggregating failures into a single exit code.
.ci/scripts/release.bash
Add a Python script to generate Markdown documentation for all policies based on their Policy.yaml files.
  • Recursively find all Policy.yaml files and load minimal metadata (dir, version, description, path) using PyYAML.
  • Generate a Markdown table summarizing the image URL (ghcr.io path plus tag), description, and README link for each policy.
  • Implement URL manipulation helper to transform a Policy.yaml GitHub URL into the associated README.md URL, and write the final table into POLICIES.md.
.ci/scripts/docgen.py
Configure a GitHub Actions workflow to validate policies on PRs, pushes, and manual runs, including optional e2e tests on main.
  • Set up checkout, updatecli, and releasepost GitHub Actions across the validate job.
  • Run make test as the main validation step for all events.
  • On main branch only, create a GitHub App token using repository secrets and run make e2e-test with the generated token for both GITHUB_TOKEN and RELEASEPOST_GITHUB_TOKEN.
.github/workflows/validate.yaml
Add Makefile targets to orchestrate policy release, validation, and e2e tests via the new Bash script.
  • Define release target to run the Bash script with --publish for pushing policies.
  • Define test target to run the Bash script for validation-only checks.
  • Define e2e-test target to run the Bash script with --e2e-test for running updatecli diff-based end-to-end tests.
  • Provide a help target that documents the available Makefile commands using annotated comments.
Makefile

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

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 3 issues, and left some high level feedback:

  • In .ci/scripts/docgen.py, the nested f-string in generate_markdown_table ({f"[link]({readme_url})" }) is invalid Python syntax; build the link string separately or inline it without a nested f-string, and consider removing the unused top-level original_url/new_url example code which currently runs at import time.
  • The Makefile has .PHONY: validate for the test and e2e-test targets, which should instead list test and e2e-test, and the help recipe line must start with a tab rather than spaces or make help will fail.
  • The Bash validation in .ci/scripts/release.bash relies on sed/grep against Policy.yaml and CHANGELOG.md with hard-coded patterns and line ranges, which is quite brittle; consider using a YAML-aware parser or more robust pattern matching so minor formatting changes don’t break the workflow.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `.ci/scripts/docgen.py`, the nested f-string in `generate_markdown_table` (`{f"[link]({readme_url})" }`) is invalid Python syntax; build the link string separately or inline it without a nested f-string, and consider removing the unused top-level `original_url`/`new_url` example code which currently runs at import time.
- The `Makefile` has `.PHONY: validate` for the `test` and `e2e-test` targets, which should instead list `test` and `e2e-test`, and the `help` recipe line must start with a tab rather than spaces or `make help` will fail.
- The Bash validation in `.ci/scripts/release.bash` relies on `sed`/`grep` against `Policy.yaml` and `CHANGELOG.md` with hard-coded patterns and line ranges, which is quite brittle; consider using a YAML-aware parser or more robust pattern matching so minor formatting changes don’t break the workflow.

## Individual Comments

### Comment 1
<location path=".ci/scripts/docgen.py" line_range="46" />
<code_context>
+        description = p.description.replace("\n", " ").strip()
+        ghcr_path = f"ghcr.io/{os.path.normpath(os.path.dirname(p.path))}"
+        readme_url = replace_filename_in_url(f"https://github.com/ContainerCraft/updatecli-policies/tree/main/{p.path}", "README.md")
+        rows.append(f"| `{ghcr_path}:{p.version}` | {description or '-'} | {f"[link]({readme_url})" } |")
+    return header + separator + "\n".join(rows)
+
</code_context>
<issue_to_address>
**issue (bug_risk):** Nested f-strings here are invalid syntax and will cause the script to fail to run.

You can’t embed an f-string inside another like this. Build the link separately and interpolate it, for example:

```python
link = f"[link]({readme_url})"
rows.append(f"| `{ghcr_path}:{p.version}` | {description or '-'} | {link} |")
```

or inline without nesting:

```python
rows.append(f"| `{ghcr_path}:{p.version}` | {description or '-'} | [link]({readme_url}) |")
```
</issue_to_address>

### Comment 2
<location path="Makefile" line_range="15" />
<code_context>
+
+.PHONY: help
+help: ## Show this Makefile's help
+    @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
</code_context>
<issue_to_address>
**issue (bug_risk):** The help command line is indented with spaces instead of a tab, which will break the Makefile.

As written, this target will likely fail with a `*** missing separator` error. Replace the leading spaces on the recipe line with a single tab to ensure `help` runs correctly.
</issue_to_address>

### Comment 3
<location path=".ci/scripts/release.bash" line_range="134" />
<code_context>
+
+  GLOBAL_ERROR=0
+
+  for POLICY in $POLICIES
+  do
+    echo ""
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Unquoted expansion of POLICIES in the loop may misbehave if paths contain whitespace or glob characters.

`for POLICY in $POLICIES` depends on word-splitting and globbing and will break if any path has spaces or wildcard chars. Consider iterating safely, e.g.:

```bash
mapfile -t POLICIES < <(find "$POLICIES_ROOT_DIR" -name 'Policy.yaml')
for POLICY in "${POLICIES[@]}"; do
  ...
done
```

Suggested implementation:

```shell
  GLOBAL_ERROR=0

  mapfile -t POLICIES < <(find "$POLICIES_ROOT_DIR" -name 'Policy.yaml')

  for POLICY in "${POLICIES[@]}"
  do

```

1. Ensure that `POLICIES_ROOT_DIR` is defined before calling `main` (for example, the root directory under which policies live).
2. If `POLICIES` was previously being set elsewhere (e.g., as a space-separated list), remove or adjust that logic so that `mapfile` is the single source of truth for the list of policy files.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread .ci/scripts/docgen.py Outdated
Comment thread Makefile Outdated
Comment thread .ci/scripts/release.bash

GLOBAL_ERROR=0

for POLICY in $POLICIES
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (bug_risk): Unquoted expansion of POLICIES in the loop may misbehave if paths contain whitespace or glob characters.

for POLICY in $POLICIES depends on word-splitting and globbing and will break if any path has spaces or wildcard chars. Consider iterating safely, e.g.:

mapfile -t POLICIES < <(find "$POLICIES_ROOT_DIR" -name 'Policy.yaml')
for POLICY in "${POLICIES[@]}"; do
  ...
done

Suggested implementation:

  GLOBAL_ERROR=0

  mapfile -t POLICIES < <(find "$POLICIES_ROOT_DIR" -name 'Policy.yaml')

  for POLICY in "${POLICIES[@]}"
  do
  1. Ensure that POLICIES_ROOT_DIR is defined before calling main (for example, the root directory under which policies live).
  2. If POLICIES was previously being set elsewhere (e.g., as a space-separated list), remove or adjust that logic so that mapfile is the single source of truth for the list of policy files.

@ringods ringods merged commit 54f8c88 into main May 18, 2026
4 checks passed
@ringods ringods deleted the add-policy-validation branch May 18, 2026 13:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant