Skip to content

don't run vmm-tests for Guide changes #2924

@mattkur

Description

@mattkur

Skip vmm-tests for lightweight PRs without weakening PR gates

Summary

I want to stop burning vmm-tests capacity on PRs that clearly are not product changes.

The immediate case is Guide/**, but I don’t think we should solve this as a docs-only special case. We should use this to add a small Flowey-level mechanism for classifying PRs into “product” vs “lightweight” buckets, then use that classification to skip the expensive vmm-tests jobs when the PR is lightweight-only.

That keeps the current PR gate model intact, fixes the docs case, and gives us a clean path to exempt other non-product areas later, like repo_support/**/*.py.


What’s wrong today

Right now the main PR workflow is Flowey-generated from .flowey.toml via ci checkin-gates --config=pr, with the logic in flowey/flowey_hvlite/src/pipelines/checkin_gates.rs.

That workflow always emits the full vmm-tests matrix, including the six heavy run vmm-tests [...] jobs. That makes sense for product changes. It does not make sense for changes that only touch docs or other repo-maintenance surfaces.

For example:

  • Guide/** changes already have their own docs validation path
  • repo_support/relabel_backported.py is repo automation, not product behavior

Those changes do not affect guest behavior, device behavior, save/restore behavior, boot behavior, or VM management semantics, but today they still consume the same scarce self-hosted test capacity as a real product change.

That is the real problem here. We are treating every PR like a product PR because we do not have a reusable way to say “this change is lightweight.”


Why I want to solve this more generally

I don’t want to hardcode one exception for Guide/** and then repeat the same discussion the next time we want to exempt another obviously non-product path.

The better model is:

  • if a PR touches product code, run full product validation
  • if a PR is entirely within approved lightweight buckets, skip vmm-tests
  • if a PR is mixed, take the stricter path and run vmm-tests

That makes the docs case easy, and it also gives us a clean way to handle future cases like repo_support/**/*.py without inventing another one-off rule.

The default should still be conservative: if a path is not explicitly classified as lightweight, it is treated as product-affecting.


Existing validation we already have

We already have a separate Flowey-generated docs PR workflow:

  • .github/workflows/openvmm-docs-pr.yaml
  • generated from .flowey.toml via ci build-docs --config=pr
  • implemented in flowey/flowey_hvlite/src/pipelines/build_docs.rs

That workflow builds the guide via flowey/flowey_lib_hvlite/src/build_guide.rs, which runs:

  • mdbook test
  • mdbook build

So for Guide/**, this is not about removing validation. It is about stopping redundant product validation for a change that already has an appropriate validation path.


Proposed shape

I want to add a small reusable Flowey helper that classifies a PR into named change buckets before we expand the expensive jobs.

Conceptually, the classifier should answer things like:

  • does this PR touch product code?
  • does this PR touch Guide/**?
  • does this PR touch repo_support/**/*.py?
  • is this PR lightweight-only?

I’m fine with backing that helper using a purpose-built GitHub Action. In fact, that is probably the cleanest implementation, as long as the Flowey interface stays simple and the action contract stays small.

Then checkin_gates.rs can use that classification to gate the six vmm-tests jobs on !lightweight_only.

So the behavior becomes:

  • Guide/**-only PR → skip vmm-tests
  • repo_support/**/*.py-only PR → skip vmm-tests
  • Guide/** + product code PR → run vmm-tests
  • product-only PR → run vmm-tests

That is the behavior I want.


Why I do not want to skip the whole PR workflow

The tempting shortcut here is to add workflow-level path filtering and just not run the main PR workflow for guide-only changes.

I don’t think that is the right shape.

The current PR pipeline already has an aggregate required-check job, openvmm checkin gates, which depends on the rest of the pipeline and treats only failure and cancelled as blocking. That is a good model. I want to preserve it.

If we skip only the vmm-tests jobs, we keep the existing required check surface and mixed-change behavior stays correct.

If we skip the entire workflow, required-check behavior gets more fragile and the whole thing becomes harder to reason about.

So I want job-level skipping of the expensive matrix, not workflow disappearance.


Goals

  • Stop scheduling vmm-tests for PRs that are entirely within approved lightweight buckets.
  • Keep running the existing vmm-tests matrix for anything that touches product code or unclassified paths.
  • Preserve the current required-check model.
  • Solve this in Flowey, not by hand-editing generated YAML.
  • Make the mechanism reusable so the next lightweight bucket is easy to add.

Non-goals

  • I am not trying to automatically treat every markdown file or every script in the repo as lightweight.
  • I am not trying to redesign the docs workflow in this change.
  • I am not trying to change the vmm-tests matrix itself.
  • I am not trying to pre-solve every future bucket; I just want the mechanism and a conservative initial policy.

Initial bucket policy

I think the initial policy should be conservative and explicit:

Lightweight buckets

  • Guide/**
  • repo_support/**/*.py

Product / full-validation by default

  • everything else

If we want to expand the lightweight set later, we can do that deliberately.


Tradeoffs

Why not do a one-off Guide/** special case?

Because that only solves today’s symptom.

The real issue is that we do not have a reusable CI concept for lightweight repo changes. If we add a classifier now, Guide/** becomes the first use case rather than a permanent special case.

Why use a purpose-built action?

Because changed-file classification is exactly the kind of thing that is cleaner to encapsulate once and reuse, instead of rebuilding with scattered string conditions.

As long as the action only does the minimal changed-file lookup and bucket evaluation, I think that is acceptable.

What’s the downside?

The initial change is a little bigger than a docs-only hack, because it adds a reusable classification mechanism instead of one condition. I think that extra work is worth it, because it gives us a sane model going forward.


Validation

I’d want to validate at least these cases:

  • Guide/**-only PR → vmm-tests skipped
  • repo_support/**/*.py-only PR → vmm-tests skipped
  • mixed lightweight + product PR → vmm-tests run
  • product-only PR → vmm-tests run

I’d also want to confirm that the aggregate openvmm checkin gates job still behaves correctly and remains suitable as a required check.


Rough implementation plan

  1. Add a Flowey-facing helper for lightweight PR classification.
  2. Back it with a purpose-built GitHub Action that evaluates changed files against named buckets.
  3. Use that helper in checkin_gates.rs to skip the vmm-tests fan-out when lightweight_only is true.
  4. Seed the initial policy with Guide/** and repo_support/**/*.py.
  5. Leave everything else on the full-validation path by default.

Open questions

  • Are Guide/** and repo_support/**/*.py the right initial lightweight buckets, or do we want to start even narrower? (Matt: yes)
  • Do we want the classifier to expose only lightweight_only, or also named per-bucket outputs so future policies can compose more easily? (Matt: let's come up with a different name, that clearly indicates that this is not product, not test, not CI, etc.)
  • Should the purpose-built action live in this repo, or in a shared CI repo? (Matt: in this repo)

Metadata

Metadata

Labels

CIImprovements or additions to our CI setup outside of flowey

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions