10. Reference#
This section is a catalogue of what already exists in the integration — the CI checks that run on every change and the consolidated reports — together with the touch-point a new module has in each. Use it to understand where your module shows up once it is wired in via the steps above. The supported target platforms and their images are listed in Supported target platforms (Step 4).
10.1. CI checks#
The pipelines live under .github/workflows. Most
operate on //... and pick up your module without changes; the table says
what each check verifies and whether you typically need to touch anything.
Gating marks the checks that run in the merge queue
(merge_group) and must therefore be green before a pull request can be
merged. The remaining checks are informational, run only on push/schedule,
or gate a different event (release approvals). The definitive list of required
status checks is configured in the repository’s GitHub branch-protection /
merge-queue settings; the column below reflects merge-queue participation
declared in the workflows.
Check (workflow) |
What it verifies |
Gating |
Your action |
|---|---|---|---|
Builds the QNX IFS and runs integration tests on QEMU. |
yes |
none (graph-wide) |
|
Builds the AutoSD OCI image with the Automotive Image Builder. |
yes |
none (graph-wide) |
|
Builds the EBcLfSA image and runs the high-integrity safety tests. |
yes |
none (graph-wide) |
|
Fails if the generated Bazel fragments drift from |
yes |
commit step 1.2 output |
|
Verifies |
yes |
update lockfile if it fails |
|
Runs the code-formatting checks. |
yes |
run the format targets |
|
Multi-repository CodeQL security scan across the integrated modules. |
yes |
none |
|
Code-quality checks, builds the docs and reports, publishes to Pages. |
yes |
wire docs in Step 2, reports in Step 7 |
|
Fails while the |
yes |
none |
|
Enforces required approvals on PRs targeting |
release branches only |
none |
|
Builds the Linux x86_64 image and runs feature integration tests on Docker. |
no |
none (graph-wide) |
|
Runs the integration tooling tests ( |
no |
only if you change scripts |
|
Scheduled cleanup of published documentation versions. |
no |
none |
|
test_integration.yml / reusable_smoke-test.yml / reusable_integration-build.yml |
Smoke-test / reusable build of the latest module |
no |
add runtime targets to ci/showcase_targets_run.txt |
10.2. Staged CI for integration pull requests#
A “come together” pull request that bumps every module hash in
known_good.json at once often fails for a reason that is visible long before
the hour-long image builds finish — a module no longer resolves, a target was
renamed, a documentation mount broke. Waiting for the full pipeline on every
push wastes both runner time and the integrator’s time.
Adding the staged-ci label to such a pull request skips the expensive jobs
and leaves only the cheap, known_good.json-derived validation running:
Check |
with |
without the label |
|---|---|---|
|
runs |
runs |
|
runs |
runs |
|
skipped |
runs |
|
skipped |
runs |
|
skipped |
runs |
|
fails (blocks merge) |
passes |
10.2.1. Workflow#
Add the
staged-cilabel when opening the integration pull request.Iterate until the documentation preflight and the generator checks are green.
Remove the label. The full pipeline runs, and
Staged CI Guardturns green.Merge once everything passes.
The label only takes effect on the next workflow run, which is why every gated
workflow listens for the labeled and unlabeled pull-request events.
Note
Staged CI Guard must be configured as a required status check in the
repository’s branch-protection settings. GitHub reports a job skipped via an
if: condition as skipped and treats a skipped required check as
satisfied — without the guard, a staged pull request would be mergeable even
though none of the heavy checks ever ran.
Staging is a manual override for a supervised integration pull request, not a way to merge unvalidated changes. The full pipeline still has to pass before the merge.
10.3. Temporarily disabling a module#
Staging CI buys time to look at a failure; it does not remove the failure. When a single module blocks the whole integration — an upstream change that will not land before the next cycle, a broken dependency, a test that cannot pass yet — that module can be taken out of the integration without losing its pinned state.
Add "enabled": false together with a mandatory "disabled_reason" to its
entry in known_good.json:
"score_example": {
"repo": "https://github.com/eclipse-score/example.git",
"hash": "0123456789abcdef0123456789abcdef01234567",
"enabled": false,
"disabled_reason": "blocked by eclipse-score/example#123, re-enable after it lands",
"metadata": { }
}
The hash, the bazel_patches list and the metadata stay in the file, so
re-enabling the module is a two-line revert rather than a reconstruction from
the git history. Deleting the entry instead would discard exactly the state the
next integrator needs.
After the edit, regenerate the Bazel fragments as usual (Step 1) and commit them
together with the known_good.json change:
python3 scripts/known_good/update_module_from_known_good.py
A disabled module then contributes no bazel_dep/git_override entry, no
coverage target, no documentation mount, no unit-test run and no SBOM entry.
The generator prints every disabled module and its reason on each run, so the
state cannot decay into an unnoticed permanent one.
10.3.1. Module-specific .bazelrc flags#
A --@score_module//path:flag=value line is the most hostile thing that can
outlive its module. Bazel resolves it on every invocation, so a flag naming a
repository that is no longer in the graph breaks the entire workspace — not just
the build, but bazel query and bazel mod as well, which are exactly the
commands needed to diagnose the problem.
Such flags therefore do not live in the root .bazelrc. Each is placed in the
fragment of the module whose repository it names:
bazel_common/bazelrc/score_baselibs.bazelrc
bazel_common/bazelrc/score_logging.bazelrc
...
Grouping by owning repository, rather than by the --config the flag belongs
to, is what makes deactivation a deletion: every line that becomes unresolvable
when a module leaves sits in that module’s file and in no other. A single
fragment may contribute to several configs.
update_module_from_known_good.py generates
bazel_common/module_flags.bazelrc, a plain list of import lines covering
the enabled modules that have a fragment. The root .bazelrc imports that one
file from its build:_common block. A disabled module is simply absent from
the generated list, so its flags are gone without its fragment being touched —
and come back unchanged when the module is re-enabled.
The generator refuses to proceed if a --@score_*// flag appears in the root
.bazelrc, if a fragment holds a flag belonging to a different module, or if
a fragment exists for a module that is not in known_good.json.
10.3.2. Why disabling is not always possible#
Removing a module’s bazel_dep removes this repository’s request for it.
It does not remove the module from the build. If any other module declares its
own dependency — score_persistency requires score_logging, for instance
— Bazel still needs it, cannot find an override any more, and resolves it from
the registry instead: at a released version, not the commit known_good.json
pinned. The build succeeds. It just builds code nobody selected, and nothing in
the output says so.
Disabling is therefore only permitted when no enabled module requires the
module. scripts/known_good/check_disabled_modules.py enforces this in CI by
resolving the real graph and failing with the list of modules that pull a
disabled one back in. It exits before invoking Bazel when nothing is disabled,
so it is free on an ordinary pull request.
At the time of writing only score_config_management, score_kyron and
score_time are leaves that can be disabled on their own. Anything else has
to be disabled together with its consumers, which is usually the point at which
staging the CI (Staged CI for integration pull requests) is the better answer.
10.3.3. What the flag does not do#
The flag governs the generated artefacts only. Anything that names the
module by hand keeps naming a module that no longer exists, and Bazel reports
that far away from known_good.json. These references are handled explicitly:
Reference |
How it is handled |
|---|---|
|
Removed automatically, because they live in the module’s own
|
|
Filtered automatically. The entry stays in |
|
Aborts the regeneration with the offending entry: it points into a module the build no longer contains, and only a human can decide whether to drop the flag or keep the module. |
A |
Aborts in CI (see above). There is no way to express this in
|
Other references are not detected automatically and have to be removed by
hand — hand-written BUILD files such as images/*/BUILD,
showcases/standalone/BUILD and the feature-integration test scenarios, plus
any test in feature_integration_tests/itf/ that exercises the module. In
practice the flag is therefore sufficient for a module that only contributes
documentation, coverage and unit tests, and is only the first step for a module
that is wired into the images, the showcases or the integration tests.
10.4. Reports#
The consolidated outputs published by the integration. They are built by
test_and_docs.yml and rendered into the documentation site.
Report |
Contents |
Source / target |
|---|---|---|
Consolidated documentation |
All integrated module docs merged into one Sphinx site. |
BUILD |
Platform verification report |
Per-release requirements/architecture verification, safety analyses and per-test-case results. |
|
Unit test summary |
Per-module unit-test execution table (generated at build time by
|
|
Coverage summary |
Per-module C++ and Rust coverage table (generated at build time by
|
|
C++ coverage (per module) |
lcov/genhtml line/function/branch report for modules declaring |
scripts/quality_runners.py →
|
Rust coverage reports |
Per-module Rust line coverage (C0/C1) for modules declaring |
rust_coverage/BUILD →
|
Overall feature & process status |
Feature/process completion dashboard derived from the pinned module repos. |
|
Integration status dashboard |
Live build/health overview of the integration. |