Skip to content

Commit 970f260

Browse files
FScholPerMaximilianSoerenPollaka-zwCopilotAlexanderLanin
authored
feat: traceability metrics (#484)
Signed-off-by: Frank Scholter Peres(MBTI) <145544737+FScholPer@users.noreply.github.com> Co-authored-by: Maximilian Sören Pollak <maximilian.pollak@qorix.com> Co-authored-by: Andreas Zwinkau <95761648+a-zw@users.noreply.github.com> Co-authored-by: Copilot <copilot@github.com> Co-authored-by: Alexander Lanin <Alexander.Lanin@etas.com>
1 parent c912093 commit 970f260

31 files changed

Lines changed: 2653 additions & 231 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ __pycache__/
2626

2727
# bug: This file is created in repo root on test discovery.
2828
/consumer_test.log
29+
.clwb

docs.bzl

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,16 +304,24 @@ def docs(source_dir = "docs", data = [], deps = [], scan_code = [], known_good =
304304
"--jobs",
305305
"auto",
306306
"--define=external_needs_source=" + str(data),
307-
] + metamodel_opts,
307+
"--define=score_sourcelinks_json=$(location :sourcelinks_json)",
308+
"--define=score_source_code_linker_plain_links=1",
309+
],
308310
formats = ["needs"],
309311
sphinx = ":sphinx_build",
310-
tools = data + metamodel_data,
312+
tools = data + [":sourcelinks_json"],
311313
visibility = ["//visibility:public"],
312314
# Persistent workers cause stale symlinks after dependency version
313315
# changes, corrupting the Bazel cache.
314316
allow_persistent_workers = False,
315317
)
316318

319+
native.alias(
320+
name = "traceability_gate",
321+
actual = "@score_docs_as_code//scripts_bazel:traceability_gate",
322+
tags = ["cli_help=Enforce traceability coverage thresholds:\nbazel run //:traceability_gate -- --metrics-json bazel-bin/needs_json/_build/needs/metrics.json"],
323+
)
324+
317325
def _sourcelinks_json(name, srcs):
318326
"""
319327
Creates a target that generates a JSON file with source code links.
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
..
2+
# *******************************************************************************
3+
# Copyright (c) 2026 Contributors to the Eclipse Foundation
4+
#
5+
# See the NOTICE file(s) distributed with this work for additional
6+
# information regarding copyright ownership.
7+
#
8+
# This program and the accompanying materials are made available under the
9+
# terms of the Apache License Version 2.0 which is available at
10+
# https://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# SPDX-License-Identifier: Apache-2.0
13+
# *******************************************************************************
14+
15+
Build Dashboards and Quality Gates
16+
==================================
17+
18+
Use this guide in repositories that consume docs-as-code as a Bazel
19+
dependency.
20+
21+
Goals:
22+
23+
1. Publish traceability dashboards from repository needs.
24+
2. Export machine-readable metrics.
25+
3. Enforce CI thresholds with ``traceability_gate``.
26+
27+
What You Get
28+
------------
29+
30+
With the ``docs(...)`` macro and ``score_metamodel`` extension enabled, your
31+
repository can:
32+
33+
- build an HTML dashboard from its own Sphinx needs,
34+
- include external needs from other repositories when desired,
35+
- export ``needs.json`` and ``metrics.json`` for machine-readable reporting,
36+
- gate CI on traceability thresholds via ``traceability_gate``.
37+
38+
Typical Setup
39+
-------------
40+
41+
For details, see :ref:`setup`.
42+
43+
Minimal Configuration Example
44+
-----------------------------
45+
46+
In ``docs/conf.py``:
47+
48+
.. code-block:: python
49+
50+
score_metamodel_requirement_types = "feat_req,comp_req,aou_req"
51+
score_metamodel_include_external_needs = False
52+
53+
Use ``score_metamodel_include_external_needs = True`` only in repositories that
54+
intentionally aggregate requirements across module dependencies, such as
55+
integration repositories. Use ``False`` for module repositories to gate only on
56+
local traceability.
57+
58+
Building the Dashboard
59+
----------------------
60+
61+
After building/running any docs command (i.e. ``bazel build //:needs_json`` or ``bazel run //:docs_check`` are the fastest):
62+
63+
The documentation build writes ``metrics.json`` via ``score_metamodel``, and the ``needs_json`` artifact contains:
64+
65+
- ``bazel-bin/needs_json/_build/needs/needs.json``
66+
- ``bazel-bin/needs_json/_build/needs/metrics.json``
67+
68+
The dashboard charts and the CI gate both use the same computed metrics.
69+
70+
Inputs for Linkage Metrics
71+
--------------------------
72+
73+
To get meaningful dashboard and gate values, consumer repositories typically
74+
need three inputs:
75+
76+
1. Requirement and architecture needs in the documentation itself.
77+
2. Source code references via :doc:`source_to_doc_links`.
78+
3. Test metadata via :doc:`test_to_doc_links`.
79+
80+
If one of those inputs is missing, the related chart or gate metric will remain
81+
empty or low.
82+
83+
Choosing Local vs Aggregated Views
84+
----------------------------------
85+
86+
There are two common modes:
87+
88+
**Module repository**
89+
90+
- Set ``score_metamodel_include_external_needs = False``.
91+
- Gate only on the needs owned by the repository itself.
92+
- Use this for per-module implementation progress and traceability.
93+
94+
**Integration repository**
95+
96+
- Set ``score_metamodel_include_external_needs = True``.
97+
- Aggregate requirements across module dependencies when that is the intended
98+
repository purpose.
99+
- Use this for system or integration-level dashboards.
100+
101+
CI Quality Gate
102+
---------------
103+
104+
Any docs build (``bazel run //:docs``, ``bazel run //:docs_check``, etc.)
105+
writes ``metrics.json`` alongside the build output. Run the gate on the
106+
exported metrics:
107+
108+
.. code-block:: bash
109+
110+
bazel run //:docs && \
111+
bazel run //:traceability_gate -- \
112+
--metrics-json bazel-bin/needs_json/_build/needs/metrics.json \
113+
--min-req-code 70 \
114+
--min-req-test 70 \
115+
--min-req-fully-linked 60 \
116+
--min-tests-linked 70
117+
118+
In CI, wire targets through Bazel dependencies so test execution and
119+
docs generation happen before the gate target.
120+
121+
In larger repositories, define a dedicated wrapper target for your standard
122+
gate thresholds so CI calls a single Bazel target.
123+
124+
Useful flags:
125+
126+
- ``--require-all-links`` for strict 100 percent gating
127+
128+
Recommended Rollout
129+
-------------------
130+
131+
For a new consumer repository:
132+
133+
1. Start with local-only metrics.
134+
2. Enable ``scan_code`` and verify ``source_code_link`` coverage first.
135+
3. Add test metadata and verify ``testlink`` coverage.
136+
4. Introduce modest thresholds in CI.
137+
5. Raise thresholds over time as the repository matures.
138+
139+
Related Guides
140+
--------------
141+
142+
- :ref:`setup`
143+
- :doc:`other_modules`
144+
- :doc:`source_to_doc_links`
145+
- :doc:`test_to_doc_links`

docs/how-to/get_started.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ In an existing S-CORE repository, you can build the documentation using Bazel:
2424
Open the generated site at ``_build/index.html`` in your browser.
2525

2626
In a new S-CORE repository, see :ref:`setup`.
27+
28+
After the initial setup, continue with :doc:`dashboards_and_quality_gates` to
29+
build a repository dashboard and enforce CI quality gates.

docs/how-to/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Here you find practical guides on how to use docs-as-code.
2727
write_docs
2828
faq
2929
other_modules
30+
dashboards_and_quality_gates
3031
source_to_doc_links
3132
test_to_doc_links
3233
add_extensions

docs/how-to/setup.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ The `docs()` macro accepts the following arguments:
7171
| `data` | List of `needs_json` targets that should be included in the documentation | No |
7272
| `deps` | Additional Bazel Python dependencies | No |
7373
| `scan_code` | Source code targets to scan for traceability tags | No |
74+
| `known_good` | Label to a "known good" JSON file for source links | No |
7475
| `metamodel` | Label to a custom `metamodel.yaml` that replaces the default metamodel | No |
7576

7677
### 4. Copy conf.py
@@ -88,3 +89,9 @@ bazel run //:docs
8889
#### 6. Access your documentation at
8990

9091
`/_build/index.html`
92+
93+
## Next Step
94+
95+
After basic setup, see {doc}`dashboards_and_quality_gates` to configure
96+
traceability dashboards, export `metrics.json`, and enforce CI quality gates in
97+
consumer repositories.

docs/how-to/test_to_doc_links.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
# SPDX-License-Identifier: Apache-2.0
1313
# *******************************************************************************
1414
15+
# Assisted-by: GitHub Copilot
16+
1517
Reference Docs in Tests
1618
=======================
1719

@@ -53,3 +55,9 @@ Limitations
5355
- Partial properties will lead to no Testlink creation.
5456
If you want a test to be linked, please ensure all requirement properties are provided.
5557
- Tests must be executed by Bazel first so `test.xml` files exist.
58+
59+
Related
60+
-------
61+
62+
For end-to-end dashboard and CI threshold setup, see
63+
:doc:`dashboards_and_quality_gates`.

docs/internals/requirements/implementation_state.rst

Lines changed: 69 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,58 @@
1111
#
1212
# SPDX-License-Identifier: Apache-2.0
1313
# *******************************************************************************
14+
15+
# Assisted-by: GitHub Copilot
1416
.. _docs_statistics:
1517

16-
Implementation State Statistics
17-
================================
18+
Tooling Coverage
19+
================
20+
21+
This page shows how the docs-as-code tooling covers process and tool
22+
requirements. It focuses on tooling capabilities offered to downstream
23+
repositories rather than on product-specific traceability inside those
24+
repositories.
1825

1926
Overview
2027
--------
2128

22-
.. needpie:: Requirements Status
23-
:labels: not implemented, implemented but not tested, implemented and tested
29+
.. needpie:: Tool Requirements Status
30+
:labels: not implemented, implemented but incomplete traceability, fully linked
2431
:colors: red,yellow, green
32+
:filter-func: src.extensions.score_metamodel.checks.traceability_dashboard.pie_requirements_status(tool_req)
33+
34+
Jump to evidence tables:
35+
36+
- :ref:`Tool Requirement Implementation and Links table <tooling_coverage_table_impl_links>`
37+
- :ref:`Process Requirement to Tool Requirement mapping table <tooling_coverage_table_process_mapping>`
38+
39+
How To Read These Levels
40+
------------------------
41+
42+
The overview pie combines implementation state and traceability evidence:
43+
44+
- ``not implemented``:
45+
requirement has ``implemented == NO``.
46+
- ``implemented but incomplete traceability``:
47+
requirement has ``implemented == YES`` or ``implemented == PARTIAL``,
48+
but is missing at least one traceability link (code link and/or test link).
49+
- ``fully linked``:
50+
requirement is implemented and has both ``source_code_link`` and ``testlink``.
2551

26-
type == 'tool_req' and implemented == 'NO'
27-
type == 'tool_req' and testlink == '' and (implemented == 'YES' or implemented == 'PARTIAL')
28-
type == 'tool_req' and testlink != '' and (implemented == 'YES' or implemented == 'PARTIAL')
52+
Implementation labels used on this page:
53+
54+
- ``NO``: requirement is not implemented.
55+
- ``PARTIAL``: requirement is partly implemented.
56+
- ``YES``: requirement is implemented.
57+
58+
Why multiple pies are shown:
59+
60+
- ``Requirements with Codelinks`` shows requirement-to-implementation traceability.
61+
- ``Requirements with linked tests`` shows requirement-to-verification traceability.
62+
- ``Requirements fully linked`` is the strict roll-up (both links present).
63+
64+
These are intentionally separate because they answer different diagnostics:
65+
missing code links, missing test links, or both.
2966

3067
In Detail
3168
---------
@@ -48,78 +85,43 @@ In Detail
4885
.. needpie:: Requirements with Codelinks
4986
:labels: no codelink, with codelink
5087
:colors: red, green
51-
52-
type == 'tool_req' and source_code_link == ''
53-
type == 'tool_req' and source_code_link != ''
88+
:filter-func: src.extensions.score_metamodel.checks.traceability_dashboard.pie_requirements_with_code_links(tool_req)
5489

5590
.. grid-item-card::
5691

57-
.. needpie:: Test Results
58-
:labels: passed, failed, skipped
59-
:colors: green, red, orange
60-
61-
type == 'testcase' and result == 'passed'
62-
type == 'testcase' and result == 'failed'
63-
type == 'testcase' and result == 'skipped'
64-
65-
.. grid:: 2
92+
.. needpie:: Requirements with linked tests
93+
:labels: no test link, with test link
94+
:colors: red, green
95+
:filter-func: src.extensions.score_metamodel.checks.traceability_dashboard.pie_requirements_with_test_links(tool_req)
6696

6797
.. grid-item-card::
6898

69-
Failed Tests
70-
71-
*Hint: this table is empty by definition, as PRs with failing tests are not allowed to be merged in docs-as-code repo.*
72-
73-
.. needtable:: FAILED TESTS
74-
:filter: result == "failed"
75-
:tags: TEST
76-
:columns: name as "testcase";result;fully_verifies;partially_verifies;test_type;derivation_technique;id as "link"
99+
.. needpie:: Requirements fully linked (code + tests)
100+
:labels: not fully linked, fully linked
101+
:colors: orange, green
102+
:filter-func: src.extensions.score_metamodel.checks.traceability_dashboard.pie_requirements_fully_linked(tool_req)
77103

78104
.. grid-item-card::
79105

80-
Skipped / Disabled Tests
81-
82-
*Hint: this table is empty by definition, as we do not allow skipped or disabled tests in docs-as-code repo.*
83-
84-
.. needtable:: SKIPPED/DISABLED TESTS
85-
:filter: result != "failed" and result != "passed"
86-
:tags: TEST
87-
:columns: name as "testcase";result;fully_verifies;partially_verifies;test_type;derivation_technique;id as "link"
88-
89-
90-
91-
92-
All passed Tests
93-
-----------------
94-
95-
.. needtable:: SUCCESSFUL TESTS
96-
:filter: result == "passed"
97-
:tags: TEST
98-
:columns: name as "testcase";result;fully_verifies;partially_verifies;test_type;derivation_technique;id as "link"
99-
106+
.. needpie:: Process requirements linked by tool requirements
107+
:labels: not linked, linked
108+
:colors: red, green
109+
:filter-func: src.extensions.score_metamodel.checks.traceability_dashboard.pie_process_requirements_linked(tool_req,true)
100110

101-
Details About Testcases
102-
------------------------
103-
*Data is not filled out yet within the test cases.*
104111

105-
.. needpie:: Test Types Used In Testcases
106-
:labels: fault-injection, interface-test, requirements-based, resource-usage
107-
:legend:
112+
Process-to-Tool Mapping
113+
-----------------------
108114

109-
type == 'testcase' and test_type == 'fault-injection'
110-
type == 'testcase' and test_type == 'interface-test'
111-
type == 'testcase' and test_type == 'requirements-based'
112-
type == 'testcase' and test_type == 'resource-usage'
115+
.. _tooling_coverage_table_process_mapping:
113116

117+
.. needtable:: Process requirement -> tool requirement mapping
118+
:types: tool_req
119+
:columns: satisfies as "Process Requirement";id as "Tool Requirement"
120+
:style: table
114121

115-
.. needpie:: Derivation Techniques Used In Testcases
116-
:labels: requirements-analysis, design-analysis, boundary-values, equivalence-classes, fuzz-testing, error-guessing, explorative-testing
117-
:legend:
122+
.. _tooling_coverage_table_impl_links:
118123

119-
type == 'testcase' and derivation_technique == 'requirements-analysis'
120-
type == 'testcase' and derivation_technique == 'design-analysis'
121-
type == 'testcase' and derivation_technique == 'boundary-values'
122-
type == 'testcase' and derivation_technique == 'equivalence-classes'
123-
type == 'testcase' and derivation_technique == 'fuzz-testing'
124-
type == 'testcase' and derivation_technique == 'error-guessing'
125-
type == 'testcase' and derivation_technique == 'explorative-testing'
124+
.. needtable:: Tool requirement implementation and links
125+
:types: tool_req
126+
:columns: id as "Tool Requirement";implemented;source_code_link;testlink
127+
:style: table

0 commit comments

Comments
 (0)