feat: scope verification reports to a report_version via valid_from - #843
Conversation
4a2ba64 to
11e4c89
Compare
|
Documentation preview for this pull request is available at: |
2e26aec to
c565de1
Compare
|
@AlexanderLanin as requested, please review |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Release scoping ignores the exclusive valid_until boundary and lacks focused behavioral tests.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
Open (2)
What changed in this PR
Adds opt-in release-version scoping to module and platform verification reports.
Changes:
- Adds
report_versionmetadata and requirement-scope helpers. - Filters report sections, statistics, and tables by requirement validity.
- Updates generated Needs JSON fixtures.
| File | Description |
|---|---|
src/extensions/score_metamodel/metamodel.yaml |
Defines report_version. |
src/extensions/score_sphinx_needs_templates/__init__.py |
Implements scope helpers. |
src/needs_templates/module_verification_report.need |
Scopes component reporting. |
src/needs_templates/platform_verification_report.need |
Scopes feature reporting. |
src/tests/docs_bzl/scenarios/basic_docs/_expected/needs_json/needs.json |
Updates expected schema. |
src/tests/docs_bzl/scenarios/data_files_runfiles/_expected/data_bundle_needs/needs.json |
Updates expected schema. |
src/tests/docs_bzl/scenarios/data_files_runfiles/_expected/isolated_source_bundle_needs/needs.json |
Updates expected schema. |
src/tests/docs_bzl/scenarios/data_files_runfiles/_expected/needs_json/needs.json |
Updates expected schema. |
src/tests/docs_bzl/scenarios/nested_bundles/_expected/needs_json/needs.json |
Updates expected schema. |
src/tests/docs_bzl/scenarios/reference_integration/_expected/needs_local.json |
Updates expected schema. |
src/tests/docs_bzl/scenarios/reference_integration/legacy_module/_expected/needs_json/needs.json |
Updates expected schema. |
src/tests/docs_bzl/scenarios/reference_integration/legacy_module/docs/components/component/_expected/needs_local.json |
Updates expected schema. |
src/tests/docs_bzl/scenarios/reference_integration/modern_module/_expected/needs_json/needs.json |
Updates expected schema. |
src/tests/docs_bzl/scenarios/reference_integration/modern_module/docs/components/unlinked_component/_expected/needs_local.json |
Updates expected schema. |
src/tests/docs_bzl/scenarios/reference_integration/score_platform/_expected/needs_json/needs.json |
Updates expected schema. |
src/tests/docs_bzl/scenarios/subdirectory_bundle/consumer/_expected/needs_json/needs.json |
Updates expected schema. |
src/tests/docs_bzl/scenarios/subdirectory_bundle/producer/_expected/needs_json/needs.json |
Updates expected schema. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| valid_from = need.get("valid_from") | ||
| if valid_from: | ||
| try: | ||
| return _parse_version(valid_from) <= _parse_version(report_version) | ||
| except ValueError: | ||
| return False |
There was a problem hiding this comment.
Good catch, and you're right that it's inconsistent with the documented valid_from/valid_until semantics (tool_req__docs_req_attr_validity_correctness: "from" inclusive, "until" exclusive).
This is intentional scope for this PR, though: report_version here answers "everything relevant as of release X" (a snapshot of what should exist by then), not "everything still valid in release X" (which would additionally need the valid_until exclusion you describe). We deliberately kept it to the simpler valid_from-only check for the initial version of this feature - happy to open a follow-up to add report_version < valid_until support (with comp_req inheriting the full interval via derived_from, as you suggest) once there's a concrete need for it, rather than speculatively building it now.
Added focused unit tests for the current behavior (including the comp_req/derived_from inheritance path and malformed-value handling) in b71c770.
| before. | ||
| """ | ||
|
|
||
| def __call__(self, need: NeedItem, report_version: str | None) -> bool: |
| ) | ||
| app.config.needs_render_context.setdefault("linked_needs", _linked_needs_callable) | ||
| app.config.needs_render_context.setdefault("needs_of_type", _needs_of_type_callable) | ||
| app.config.needs_render_context.setdefault("req_in_scope", _req_in_scope_callable) |
There was a problem hiding this comment.
req_in_scope does not really imply "version". Maybe "req_in_report_version"?
There was a problem hiding this comment.
Good point, renamed to req_in_report_version in 0cd3801.
| app.config.needs_render_context.setdefault("needs_of_type", _needs_of_type_callable) | ||
| app.config.needs_render_context.setdefault("req_in_scope", _req_in_scope_callable) | ||
| app.config.needs_render_context.setdefault( | ||
| "any_req_in_scope", _any_req_in_scope_callable |
There was a problem hiding this comment.
same here. Like any_req_in_report_version. Or something prettier.
There was a problem hiding this comment.
Renamed to any_req_in_report_version in 0cd3801, thanks.
module_verification_report previously rendered both the module's own
components AND every Feature reachable from those components, mixing
module-scoped and platform-scoped statistics into a single report.
- module_verification_report.need: drop the feature-loop section
(Requirements/Architecture/Inspection Statistics per Feature). The
report now covers Components only, as its name implies.
- platform_verification_report.need (new): the feature-scoped
counterpart, listing every Feature in the current build (via the
existing needs_of_type("feat") helper) with the same statistics that
were removed from the module report.
11e4c89 to
3046110
Compare
Adds an optional report_version attribute on document Needs. When set, module_verification_report and platform_verification_report only show requirements (and the Features/Components that own them) with valid_from <= report_version. comp_req has no valid_from of its own, so its scope is inherited from the feat_req it is derived_from. Features/Components with no in-scope requirement are dropped from the report entirely instead of rendering an empty section. Unset/empty report_version keeps reports unscoped, matching prior behavior.
- ruff-format src/extensions/score_sphinx_needs_templates/__init__.py (2 lines that now fit on one line each). - Regenerate the 13 checked-in _expected/needs_json + needs_local.json fixtures under src/tests/docs_bzl/scenarios to include the new report_version extra-option schema entry, matching what test_docs_bzl_scenario_expected_output already wrote locally when it detected the diff (CI fails this test on purpose after auto-updating, so the updated files can be reviewed and committed).
Adds focused unit tests for the report_version scoping helpers added in a previous commit, addressing a PR review finding that only the generated-schema fixtures exercised report_version, with no direct coverage of the filtering logic itself: - unscoped (no report_version) always includes everything - valid_from boundary is inclusive - malformed valid_from is excluded rather than raising - comp_req with no valid_from and nothing to inherit is excluded - comp_req inherits its scope from the feat_req it is derived_from - any_req_in_scope for empty/matching/non-matching requirement lists
Per review feedback: 'scope' didn't make clear these helpers are about report_version specifically. Renames the Jinja render-context globals and their backing classes/instances: - req_in_scope -> req_in_report_version (_RequirementInScope -> _RequirementInReportVersion) - any_req_in_scope -> any_req_in_report_version (_AnyRequirementInScope -> _AnyRequirementInReportVersion) Updates the two .need template call sites and the unit tests accordingly. No behavior change.
0cd3801 to
9c26357
Compare
|
LGTM, but I would like to merge #841 first |
|
Hey @AlexanderLanin , why should #841 first? From my point of view there are no correlations. |
|
@copilot resolve the merge conflicts in this pull request. This PR adds report_version support to the templates. |
MaximilianSoerenPollak
left a comment
There was a problem hiding this comment.
Some comments.
I think this is a good idea, just had some questions.
| except ValueError: | ||
| return False |
There was a problem hiding this comment.
In my opinion this can never happen, or am I thinking wrong?
I do like defensive programming, but this seems a bit weird.
If anything this defence may should be in the parser.
| return any(self(feat_req, report_version) for feat_req in linked_feat_reqs) | ||
|
|
||
|
|
||
| _req_in_report_version_callable = _RequirementInReportVersion() |
There was a problem hiding this comment.
Single variable indirections are useless imo.
Makes it harder to read.
You are only using htem on 2 places, so this makes no sense to put into a variable that is also the same lenght...
…coping # Conflicts: # src/needs_templates/module_verification_report.need # src/needs_templates/platform_verification_report.need Co-authored-by: AlexanderLanin <5074553+AlexanderLanin@users.noreply.github.com>
Resolved by merging |


Stacked on #839 (targets that branch, not
main, so the diff here only shows the two commits below; it will show againstmainonce #839 merges and this PR's base is retargeted).Why
module_verification_reportandplatform_verification_report(see #839) always show every Requirement/Feature/Component in the current build. There is no way to scope either report to "everything relevant for release X", even though the metamodel already has avalid_from/valid_untilattribute onfeat_req/stkh_reqfor exactly this purpose (seetool_req__docs_req_attr_validity_correctness).What changed
src/extensions/score_metamodel/metamodel.yaml: new optionalreport_versionattribute on thedocumentneed type, using the samevMAJOR.MINOR[.PATCH]format already enforced forvalid_from/valid_until.src/extensions/score_sphinx_needs_templates/__init__.py: two new render-context helpers.req_in_scope(need, report_version)decides whether a single requirement Need is in scope.feat_req/stkh_reqcarryvalid_fromdirectly;comp_reqhas novalid_fromof its own, so it inherits scope from thefeat_reqit isderived_from. A requirement with no resolvablevalid_fromis excluded whenever areport_versionis set.any_req_in_scope(reqs, report_version)decides whether a Feature/Component has any requirement in scope.src/needs_templates/module_verification_report.needandsrc/needs_templates/platform_verification_report.needuse these helpers to:id in [...]the in-scope requirement IDs, andreport_versionkeeps a report fully unscoped (all Features/Components/requirements shown), which is whatdoc__platform_verification_report_latestand similar "latest" reports rely on — this is opt-in and backward compatible.