Commit graph zephyr/scripts
Author SHA1 Message Date
Ioannis Damigos
6f2b972dbf checkpatch: Add support for Assisted-by tag
Assisted-by tag was introduced in doc/contibute/guidelines.rst
for attributing AI tool contributions.

checkpatch.pl doesn't recognise this tag and throws BAD_SIGN_OFF
issues for missing email address.

This fix imports linux kernel support for Assisted-by tag to
zephyr (d1db411).
It adds Assisted-by to the recognised $signature_tags list,
skips email validation since Assisted-by uses the
[Agent Name]:[Model Version] format and throws a warning
if the value doesn't match the expected format.

Signed-off-by: Ioannis Damigos <ioannis.damigos.uj@renesas.com>
2026-07-31 13:20:58 -04:00
Fin Maaß
aec3132f1d scripts: checkpatch.pl: relax Missing a blank line
add the delaring macros from
zephyr/sys/device_mmio.h
as to list so it does not complain about it.

Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
2026-07-31 13:05:26 -04:00
Anas Nashif
e4420e41b5 twister: de-duplicate helpers and literals in TestPlan
Several small copy-paste items in testplan.py:

- The `set(p.platform.name for p in self.instances.values())` expression
  used to refresh selected_platforms appeared four times (three in load()
  and once in apply_filters()); extract _refresh_selected_platforms().
- The five-argument instance.create_overlay(...) call with the same asan/
  ubsan/coverage options appeared in load_from_file() and apply_filters();
  extract _create_overlay(instance). The loop variable `platform` at the
  first site equals instance.platform (the instance is built for it), so
  reading instance.platform is equivalent.
- The three YAML schema paths all rebuilt the ZEPHYR_BASE/scripts/schemas/
  twister prefix; hoist it to a TWISTER_SCHEMA_DIR constant.
- The "Not runnable on device" reason was set in one method and string-
  compared in another 400 lines away; promote it to the module constant
  NOT_RUNNABLE_ON_DEVICE_REASON so the two cannot drift.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-31 13:05:16 -04:00
Anas Nashif
fc4b32711d twister: cache module scan and fold the *_roots loop
zephyr_module.parse_modules(ZEPHYR_BASE) walks the whole workspace for
module manifests, and twister ran it twice per invocation: once in
add_parse_arguments() to build the --board-root default and again in
TwisterEnv.__init__() to collect the snippet/soc/dts/arch roots. Wrap it
in a functools.cache helper (_parse_modules) so the scan happens once; the
result is read-only at both sites, so sharing it is safe.

While there, replace the five near-identical "settings.get('<x>_root')
-> append to self.<x>_roots" blocks in TwisterEnv.__init__ with a single
loop over a {setting_key: roots_list} mapping. project / snippet_root and
project / Path(soc_root) are equivalent, so wrapping every value in Path()
is a no-op.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-31 13:05:16 -04:00
Anas Nashif
8c968a3070 twister: turn ProjectBuilder.process into a dispatch table
process() was a 287-line if/elif chain over nine pipeline ops, and every
branch repeated the same ~5-line "except StatusAttributeError" handler
(force ERROR, set the 'Incorrect status assignment' reason, block the
remaining cases) followed by a finally that enqueues the next op.

Split each op into its own _op_<name> method and drive them from a
_PIPELINE_OPS name->method table, so process() is now a short dispatcher.
The repeated exception body becomes a single _mark_status_error() helper
(the coverage op keeps its "on <op>" reason variant via op_label). Each
handler keeps its own control flow, including the irregular cases: 'run'
still re-queues the message on NoDeviceAvailable/RequiredAppNotReady,
'report' still clears next_op on error, and 'cleanup' still neither
enqueues nor reports.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-31 13:05:16 -04:00
Anas Nashif
ecb6d8d3f4 twister: de-duplicate XUnitXMLReport.create paths
XUnitXMLReport.create() and create_with_all_testsuites() shared ~70% of
their bodies: loading the JSON, building the <testsuite> element with its
eight zeroed attributes and version property, the full-report testcase
loop, the counter-finalisation block, and the indent/tostring/write tail.

Factor these into _read_json(), _new_testsuite(), _finalize_testsuite(),
_emit_full_report_testcases() and _write_report(), and rewrite both public
methods in terms of them. create() keeps its per-platform grouping and its
full_report vs per-suite-summary branch; create_with_all_testsuites() keeps
its per-suite grouping and extra platform/architecture properties.

No behaviour change: rendering both methods over a synthetic report and
comparing canonicalised XML (ET.canonicalize) is byte-identical to the
previous code across full/summary/target/all-testsuites variants and both
detailed_skipped_report settings. The only difference is that the
all-testsuites <testsuite> now emits its time/timestamp attributes in the
same order as create() - JUnit attribute order is not significant and no
test pins it.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-31 13:05:16 -04:00
Anas Nashif
ff01135e81 twister: extract QEMUHandlerBase for the shared QEMU handler logic
QEMUHandler (POSIX) and QEMUWinHandler (Windows) duplicated _get_cpu_time,
_create_command, get_fifo, the pid-file half of _set_qemu_filenames, and a
byte-identical instance-info updater that had drifted into two names
(_thread_update_instance_info vs _monitor_update_instance_info). The
post-status timeout-extension block, with its bare 30/2 second literals,
was copied into both monitor loops.

Introduce a QEMUHandlerBase(Handler) holding these shared pieces and have
both handlers inherit it. The magic timeout values become the
COVERAGE_TIMEOUT_EXTENSION / POST_STATUS_TIMEOUT_EXTENSION constants,
consumed through a single _extend_timeout_on_status() helper. The Windows
handler drops its now-identical _set_qemu_filenames entirely; the POSIX
one keeps a two-line override that also sets the fifo path.

The two monitor loops themselves are deliberately left in the subclasses:
their wait/read mechanisms differ fundamentally (select.poll on POSIX
fifos vs a reader-thread Queue on Windows) and the Windows path is not
exercised by Linux CI, so merging them would risk an untestable
regression. The public method names the tests patch (_get_cpu_time,
_thread_update_instance_info, _thread_get_fifo_names, _set_qemu_filenames)
are preserved, so behaviour is unchanged.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-31 13:05:16 -04:00
Anas Nashif
cf9aa5d8ea twister: share run/status logic across report-based harnesses
Pytest and Ctest each duplicated an almost identical run() skeleton and a
byte-identical _update_test_status(); the two differed only in the tool
name used in reason strings, the exception type run() catches, and
whether pytest's PYTHONPATH env dependencies are injected.

Introduce a ReportHarness(Script) base that owns run() and
_update_test_status(). Subclasses now declare a report_tool label and a
run_exception type, and override the _run_report_command() hook when they
need to alter how the tool is invoked (Pytest injects env dependencies).
The triple of ExitCodes meaning "the tool errored" becomes the module
constant REPORT_ERROR_EXIT_CODES. Script keeps its own script-oriented
run()/_update_test_status(); Bsim is unaffected.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-31 13:05:16 -04:00
Graham Roff
f71c676b66 scripts: dashboard: Add copy button to build command and file paths.
Add a copy-to-clipboard button next to the build command and the
various file path values.

Signed-off-by: Graham Roff <grahamr@qti.qualcomm.com>
2026-07-30 21:29:26 -04:00
Anas Nashif
4b97a74880 ci: set_assignees: mention reviewers that cannot be requested
A formal review request is not always possible.  GitHub rejects one for
anybody without collaborator status, so an area maintainer or collaborator
listed in MAINTAINERS.yml who lacks push access was silently dropped, and
the request as a whole may be refused for reasons the script cannot
anticipate.  In both cases the people responsible for the changed code
never learned the PR existed.

Fall back to asking them by name.  Users who cannot be added to the review
request are @mentioned in a comment requesting their review, which
notifies them regardless of their permissions.  This covers both the
non-collaborator case and whatever the review request could not
accommodate, including the tail dropped when a rejected bulk request is
retried with fewer candidates.

The comment is maintained in place rather than appended: it carries a
hidden MENTION_MARKER, so a re-run finds its own previous comment and
edits it only when the set of people actually changed.  Re-running over a
PR therefore neither duplicates the comment nor adds timeline noise.

Users who removed themselves from the review request are excluded, and
the self-removal test now runs before the collaborator test so that an
opt-out is never routed to the mention path instead.  Deleted accounts are
still skipped outright, there being nobody to mention.  A failure to post
the comment is logged and swallowed, like the review request itself, so
that a repository without comment write access still completes its run.

Assisted-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-30 21:29:05 -04:00
Anas Nashif
fb52cdf1e0 ci: set_assignees: stop capping the number of reviewers
MAX_REVIEWERS (15) drove two behaviours: the candidate list was truncated
to the remaining vacancy, and a PR already holding that many reviewers
discarded its candidate list entirely in favour of the primary area's
maintainers.  Both predate the tiered candidate ordering, and neither
still earns its keep.

The cap was never GitHub's.  GitHub documents no limit on how many
reviewers a pull request may carry, and PRs with more than 15 individual
reviewers requested (no teams involved) are observable in this very
repository, so the number was self-imposed.  Its only effect was to drop
people who were legitimately responsible for part of the change.

The overflow strategy was worse than redundant.  It compared
MAX_REVIEWERS against a set that unions submitted reviews with pending
review requests, so a well-reviewed PR could take the restricted path
with no pending requests at all and plenty of room to add more.  Now that
maintainers are ordered ahead of collaborators, the ordering already does
what the strategy was reaching for.

Drop the cap and request everyone eligible.  This also retires
_add_reviewers()'s primary_maintainers and extra_reviewers parameters,
which were referenced only from the removed branch; additional_reviews is
folded into the candidate list by _build_reviewer_candidates and needs no
separate path.  Should GitHub refuse the full set anyway, the call is
retried once with the first REVIEWER_RETRY_BATCH candidates, which the
tier ordering makes the maintainers, so a rejection cannot leave the PR
with no reviewers at all.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
Assisted-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 21:29:05 -04:00
Anas Nashif
2809740625 ci: set_assignees: find reviewers for files matching no area
Every reviewer tier is derived from the areas a changed file maps to, so a
file that matches no area in MAINTAINERS.yml contributes nobody.  A PR
made up only of such files ends up with an empty candidate list, and the
review request is skipped entirely: nobody is asked to look at it.

Feed unmatched files into the same heuristics already used for
under-covered areas.

The heuristic pass now triggers on the union of under-covered-area files
and orphaned files, so a mixed PR still walks only the files that are
actually unstaffed, and a fully covered PR still issues no extra query.
Heuristic picks stay appended after the maintainer and collaborator
tiers, so they only ever fill leftover review slots.

Assisted-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-30 21:29:05 -04:00
Anas Nashif
9b5bddbed6 ci: set_assignees: add heuristic reviewers for under-covered areas
Some areas in MAINTAINERS.yml name no maintainers, or only a handful of
collaborators.  When a PR touches such an area, the reviewer candidate
list built from MAINTAINERS.yml alone is too thin to attract a meaningful
review, and nobody responsible for the change is requested.

Supplement these areas heuristically.  An area is treated as
under-covered when it names no maintainers, or at most
THIN_AREA_COLLABORATORS (2) collaborators.  For every such area two
sources are tried in order, and the result is appended after the
maintainer and collaborator tiers so that it only ever fills leftover
review slots.

First, GitHub's own suggestions for the pull request
(PullRequest.suggestedReviewers), which GitHub derives from both commit
history and past review comments.  That is the better-informed signal and
costs a single query instead of one per changed file, so suggestions
GitHub flagged as authors of the changed code are ranked ahead of
comment-only ones.  The field is only available over GraphQL, so this
issues a raw query through PyGithub's requester, which reuses the
existing token and session; no new dependency is needed.  Every failure
path (transport error, GraphQL errors, unexpected shape, null list)
degrades to an empty list, so a bad response can only cost the
suggestion, never the run.

Second, when GitHub suggests nobody, the recent contributors to the
changed files the under-covered areas own, read from the commit history.
This fallback is not redundant: sampling a dozen open PRs showed GitHub
returning suggestions for only about a third of them, with no visible
correlation to how many reviewers were already requested.  The commit
walk also stays scoped to the files that are actually short of reviewers,
whereas GitHub's suggestions cover the PR as a whole.  History is read
through the GitHub API rather than a local 'git log'/'git blame': the API
resolves commits to real GitHub logins (author emails cannot be mapped to
logins reliably) and does not depend on the CI checkout having full
history.

In both cases the PR author and everyone already on the candidate list
are excluded, so these last-resort slots are not spent on reviewers the
PR already has, and the commit walk is bounded by
HISTORY_COMMITS_PER_FILE, MAX_HISTORY_FILES, and MAX_HISTORY_REVIEWERS to
keep the API cost predictable.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
Assisted-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 21:29:05 -04:00
Anas Nashif
7a91555e0e ci: set_assignees: request all area maintainers before collaborators
The reviewer candidate list was built by iterating touched areas in
descending weight order and appending each area's maintainers immediately
followed by its collaborators.  _add_reviewers() then truncates the
filtered list to the remaining reviewer vacancy (MAX_REVIEWERS minus the
existing reviewer count).

On a fresh PR that touches many areas, the collaborators of the
highest-weight areas were reached before the maintainers of the
lower-weight areas, so the review-request slots could be filled with
collaborators while the maintainers of several touched areas were never
requested.

Build the candidate list in two tiers instead: every touched area's
maintainers first (in descending weight order), plus the manifest /
MAINTAINERS.yml-change and deferred-file-group maintainers, followed by
all area and path-specific collaborators.  Truncation to the vacancy now
drops collaborators before it drops any maintainer.  Set-derived inputs
are sorted so candidate ordering is deterministic.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-30 21:29:05 -04:00
Anas Nashif
2d84f54ccd scripts: ci: test_plan_v2: fail closed when twister crashes
TwisterExecutor.execute() ran twister to enumerate the tests matching a
strategy's patterns and, on any failure, logged a warning and returned
an empty list. A crash - a missing Python dependency, an import error,
an OOM kill, a test config that fails schema validation - was therefore
indistinguishable from "this change needs no tests": the plan came back
empty, .testplan reported zero nodes, and the workflow skipped the whole
twister-build matrix. A change could merge with no coverage at all
because the selector broke, not because it was safe.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-30 07:42:25 -05:00
Anas Nashif
034937ea9c twister: on load_errors, abort early
With no tests found when pointing to a directory with no tests, which is
not wrong, we were exiting with 1, when twister was crashing because of
bad syntax or when not able to load a python module, same thing.

Now fail early when there are schema errors or other issues, and fail
with a warning when no tests are found, which should be fine given that
a warning is emitted, but not an error.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-30 07:42:25 -05:00
Pieter De Gendt
ae55454cc3 ci: check DCO sign-off with a dedicated workflow
Add a dco.yml workflow that runs the action-dco composite action over a
pull request's commits, verifying each carries a Signed-off-by line
matching the author (First Last <email>) as required by the DCO.

Drop the now-redundant Identity compliance check, along with its
.gitignore output entry and the dependabot exclude in compliance.yml.
The empty-body check it also did stays covered by gitlint's
body-is-missing rule.

Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
Assisted-by: Claude:claude-opus-4.8
2026-07-30 09:52:32 +02:00
Omar Naffaa
fd701acfe6 scripts: dts: Loosen type annotation on "val"
Update "out_dt_define" macro to allow integer types
as the value parameter. Prevents unneeded warning
when "val" is specified as an integer.

Signed-off-by: Omar Naffaa <onaffaa@qti.qualcomm.com>
2026-07-28 18:11:22 -04:00
Nikodem Kastelik
d959c961ff scripts: requirements: pin tree-sitter below 0.26
tree-sitter 0.26.0 corrupts memory when traversing nodes from the
tree-sitter-cmake grammar, causing cmake_style.py to segfault. This is
reproducible by running the checker on
modules/hal_nordic/nrfx/CMakeLists.txt:
  scripts/cmake/cmake_style.py modules/hal_nordic/nrfx/CMakeLists.txt
Cap the dependency at <0.26 and pin the lock back to the working 0.25.2.

Assisted-by: Claude:opus-4.8
Signed-off-by: Nikodem Kastelik <nikodem.kastelik@nordicsemi.no>
2026-07-28 11:32:36 +01:00
Juergen Werner
2dfdec7f37 scripts: import sys was removed from guiconfig.py but is still in use
This is a recent regression from commit e95e5b8.

Signed-off-by: Juergen Werner <j.werner@aduart.de>
2026-07-27 14:42:58 +02:00
Anas Nashif
f75eaf5733 scripts: twister: skip valgrind blackbox test when valgrind is missing
Twister exits with an error when --enable-valgrind is given but the
valgrind executable is not on PATH. The blackbox test calls twister
in-process, so that exit propagated as SystemExit and failed the test
on hosts without valgrind installed.

Add a requires_tool() helper to the blackbox conftest that builds a
skipif marker from shutil.which(), and apply it to the valgrind
parametrization. The baseline case without the option is unaffected and
still runs everywhere.

Assisted-by: Claude:opus-4.8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-27 09:21:02 +02:00
Anas Nashif
d9b07f41d9 scripts: twister: refactor blackbox tests
Replace the importlib-based module loader pattern used across blackbox
tests with direct calls to twister_main(), and overhaul the shared
conftest.py: rename fixtures for clarity, isolate logging state via a
dedicated _reset_logging() helper and autouse fixture, add helper
functions read_testplan(), active_testcases(), and active_testsuites(),
and introduce session-scoped hello_world_elf and out_path fixtures.
Add pytest markers fast, build, and run. Rename test_filename_mock to
TEST_FILENAME_MOCK and resolve TEST_DATA through os.path.realpath() to
avoid symlink mismatches. Delete test_addon.py and restructure
test_config.py and test_coverage.py into focused classes grouped by
feature.

Assisted-by: Claude:opus-4.8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-27 09:21:02 +02:00
Anas Nashif
2e55626785 scripts: twister: derive the CMake generator from the parsed arguments
The default for --ninja was computed from sys.argv:

    default=not any(a in sys.argv for a in ("-k", "--make"))

sys.argv is the process argument list, which only coincides with the
argument list twister acts on when twister runs as a CLI. Calling
twister_main(args) in-process, as the blackbox tests do, therefore
selects the generator based on whatever launched the interpreter:

  - twister_main(['--make', ...]) still builds with Ninja, silently
    ignoring --make.
  - Running the blackbox suite as 'pytest -k <expr>' puts '-k' into
    sys.argv, so every build switches to Unix Makefiles.

Drop the sys.argv sniffing and derive options.ninja from options.make
after parsing, so the generator follows the arguments twister was
actually given.

Assisted-by: Claude:opus-4.8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-27 09:21:02 +02:00
Anas Nashif
b95c99d979 scripts: twister: cache version, toolchain and platform lookups
Add process-level caches to TwisterEnv.check_zephyr_version() and
get_toolchain() so repeated twister_main() calls within the same
process skip slow git/cmake subprocess re-runs, and add a module-level
cache to generate_platforms() keyed on the board/soc/arch root tuples.
This significantly speeds up in-process invocations such as the
blackbox test suite.

Assisted-by: Claude:opus-4.8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-27 09:21:02 +02:00
Reto Schneider
07eddea693 twister: Deal with trailing slash in outdir
This change allows the following command to be run more than once
without crashing:

> twister --outdir directory-with-trailing-slash/

Without this fix, the 2nd run would abort with an error like this:

> shutil.Error: Cannot move a directory 'directory-with-trailing-slash/'
> into itself 'directory-with-trailing-slash/.1'.

Signed-off-by: Reto Schneider <code@reto-schneider.ch>
2026-07-26 20:47:45 +02:00
Henrik Brix Andersen
c5c18b66af scripts: requirements: actions: basic: refresh pinned versions
Run the uv command to update the pinned versions in
requirements-actions-basic.txt.

Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2026-07-26 08:14:41 -04:00
Henrik Brix Andersen
1115f8c572 scripts: requirements: actions: refresh pinned versions
Run the uv command to update the pinned versions in
requirements-actions.txt.

Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2026-07-26 08:14:41 -04:00
James Growden
f415f80cbd runners: pyocd: add reset
Add the ability for the pyocd runner to reset the device.
Add pytest to cover use case.

Signed-off-by: James Growden <jgrowden@tenstorrent.com>
2026-07-24 12:40:05 -07:00
Grzegorz Chwierut
a18fd195bf twister: harness: handle missing robot executable
When the Robot Framework executable is not found, subprocess
raised an unhandled FileNotFoundError that aborted the entire
Twister run instead of just the affected test.

Catch the exception in the Robot harness, mark the instance as
skipped with a descriptive reason, and continue so remaining
tests still execute.

Signed-off-by: Grzegorz Chwierut <grzegorz.chwierut@nordicsemi.no>
2026-07-24 12:39:50 -07:00
Anas Nashif
97070087f8 ci: set_assignees: diff manifest/maintainers against PR fork point
The assigner compared the PR's west.yml and MAINTAINERS.yml against the
checked-out base-branch tip. For pull_request_target the working tree is
the base branch HEAD, while pr_west.yml/pr_MAINTAINERS.yml come from the
asynchronously-recomputed pull/<N>/merge ref, whose base can lag well
behind that tip. The diff therefore reported not only the projects/areas
the PR actually changed but also everything that advanced on the base
branch after the PR was created, and added all of those maintainers and
collaborators as reviewers.

Compare instead against the merge ref's first parent (FETCH_HEAD^1), the
base the merge was computed from, so the diff isolates exactly the PR's
own changes regardless of how stale the merge ref is. The workflow now
writes base_west.yml and base_MAINTAINERS.yml from FETCH_HEAD^1 and
passes them via the new --base-manifest and --base-maintainer-file
options. Both options default to the checked-out files when omitted, so
local and manual invocations keep working.

Fixes #110422

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-24 15:34:04 -04:00
Alberto Escolar Piedras
e158bdf5d3 twister: reports: Also report toolchain in synopsis shortlist
Now that we are building with multiple toolchains some failures will only
happen with one toolchain.
So, also print the toolchain used, so it is easier to identify the issue.

And update the twister blackbox tests reference data.

Signed-off-by: Alberto Escolar Piedras <alberto.escolar.piedras@nordicsemi.no>
2026-07-23 18:01:27 -04:00
Alberto Escolar Piedras
60643b7b05 twister: script harness: Properly log script not found failures
Before this patch, when a script is not found, `twister_harness.log` would
not be created.

This would result in the error reporting in runner.py to refer users to
the build.log; and if `--inline-logs` was used, it would inline the
build.log in the console output which was just a lot of confusing noise
for users.

Instead let's create twister_harness.log logging a "not found" error.
So we both refer users to it in the console output, and if we inline
anything we inline that.

Signed-off-by: Alberto Escolar Piedras <alberto.escolar.piedras@nordicsemi.no>
2026-07-23 16:09:16 +02:00
Anas Nashif
788f7ae977 ci: test_plan_v2: load ci configuration.
add --test-config tests/test_config_ci.yaml when executing twister
during generation of test plan, so we can get the coverage based on the
configuration.

Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-22 20:57:44 -04:00
Anas Nashif
00b73e03a4 twister: allow building a platform with multiple toolchains
Twister picks exactly one toolchain per platform, so a board that is
buildable with several toolchains only ever gets coverage for one of
them. The only way to build a test more than once was the test scenario
level integration_toolchains option, which cannot express "build
everything on this platform with both GCC and Clang".

Add a build_toolchains option listing the toolchains every test assigned
to a platform should be built with. Twister then creates one test
instance per toolchain, each in its own build directory. The option can
be set in the board configuration, or per platform in the twister
configuration file, which lets multi-toolchain coverage be enabled for
CI only while local runs keep building each test once. An empty list in
the twister configuration disables it for a platform that requests it.

The toolchain resolution chain moves into get_toolchains(), keeping the
existing precedence, with build_toolchains taking effect just below a
scenario's integration_toolchains.

Toolchain is also added to the platform_key deduplication key. That key
deduplicates platforms, not toolchains, and without this every extra
toolchain of a scenario using platform_key is discarded as already
covered.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-22 20:57:44 -04:00
Alberto Escolar Piedras
a945d0ee03 twister: Do not print twice logs with inline_logs for script harness
For `script` type harnesses, when `--inline_logs` is used,
the output of all the scripts which are part of the test are printed
to console first (both passed and failed ones).
And then again the failed ones.
This is quite undesirable, as it fills the console with unnecessary
logs, which makes it more difficult and slow to find the problem.

Instead, for the script harness, let's print only the failed ones.

Signed-off-by: Alberto Escolar Piedras <alberto.escolar.piedras@nordicsemi.no>
2026-07-21 10:14:49 -04:00
Alberto Escolar Piedras
dc3634992c twister: runner/reports: Correct log variable name
The pytest harness now is a child of the script harness.
And all script harnesses use twister_harness.log for their
output.
Let's correct the variable name to not confuse readers.

Signed-off-by: Alberto Escolar Piedras <alberto.escolar.piedras@nordicsemi.no>
2026-07-21 10:14:49 -04:00
Fin Maaß
71aadac132 dts: tests: allow cpu props be set in cpus
Add a test to check that putting common
cpu props in the parent cpus node works.

Assisted-by: GitHub Copilot:GPT-5.3-Codex

Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
2026-07-20 17:30:37 -05:00
Fin Maaß
11dc56c5c7 dts: allow cpu props be set in cpus
This allows to put common props of
cpu nodes in the parent cpus node, as
specified in the devicetree spec in 3.8.

Assisted-by: GitHub Copilot:GPT-5.3-Codex

Signed-off-by: Fin Maaß <f.maass@vogl-electronic.com>
2026-07-20 17:30:37 -05:00
Anas Nashif
ff848277b8 twister: add the virtiofs sidecar
Add the first concrete sidecar. It shares a host directory with the
guest over virtiofs: tests run on QEMU with a vhost-user-fs-pci device,
which needs a virtiofsd daemon on a per-build-dir UNIX socket that QEMU
connects to before it boots. The sidecar starts virtiofsd in setup()
(seeding a private writable copy of the shared directory) and stops it
in teardown(), skipping the run cleanly if virtiofsd is not installed.
The runner injects the dynamic -chardev socket path via
QEMU_EXTRA_FLAGS.

Configured through the virtiofs_shared / virtiofsd_bin /
virtiofs_extra_args harness_config keys. Adds unit tests.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-20 08:33:51 -05:00
Anas Nashif
12aeb999ea twister: introduce the host-sidecar concept
Some QEMU tests need a host-side process running for the guest to talk to
(a virtiofsd daemon, an ivshmem reader, a network tap). Model this as a
first-class "sidecar": a testsuite field orthogonal to the harness, so a
test keeps its normal harness (ztest, console, ...) and just declares a
sidecar, and twister may also attach one itself.

This commit adds only the plumbing and the base concept:

- A Sidecar base class with configure()/setup()/teardown() and a
  SidecarImporter registry (empty here; concrete sidecars register in
  later commits), in twisterlib/sidecar.py.
- The `sidecar:` testsuite field (config_parser, TestSuite) and the
  per-instance sidecar/dtc_overlay attributes (TestInstance).
- The runner wraps handler.handle() with the sidecar's setup/teardown and
  skips the run cleanly if setup() reports the host side is unavailable.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-20 08:33:51 -05:00
Omar Naffaa
68708d45c6 scripts: add device_type as binding exception
"device_type" is a yaml property that needs to use an underscore
rather than a dash. This is a special case to maintain compatibility
with legacy FCode devicetrees and should not be flagged.

Signed-off-by: Omar Naffaa <onaffaa@qti.qualcomm.com>
2026-07-20 08:30:45 -05:00
Reto Schneider
1938e2061f scripts: footprint: Improve function name
The previous function name was a bit misleading, as the actual work it
does it using "git reset", not "git checkout".

Signed-off-by: Reto Schneider <code@reto-schneider.ch>
2026-07-17 13:32:16 -05:00
David Nepožitek
88d6d91753 scripts: zspdx: Fix relationship mapping in SDPX 3
Add translation of DEPENDENCY_OF, CONTAINED_BY, DESCRIBED_BY,
and PREREQUISITE_FOR to SDPX3 relationships. Fix HAS_PREREQUISITE
to be mapped as hasPrerequisite relationship.

Signed-off-by: David Nepožitek <david@nepozitek.cz>
2026-07-17 11:56:06 -04:00
Appana Durga Kedareswara rao
f86e46fe61 west: xsdb: Document AMD host tool and harden runner tests
- Add XSDB subsection to Flash & Debug Host Tools (Vitis/PATH, not SDK)
- Raise a clear MissingProgram message when xsdb is absent
- Patch require() in the remaining unit tests so CI does not need xsdb
  installed

Signed-off-by: Appana Durga Kedareswara rao <appana.durga.kedareswara.rao@amd.com>
2026-07-17 08:42:21 +02:00
Appana Durga Kedareswara rao
67a8b58d15 runners: xsdb: Add native debugging with board config integration
Enable native XSDB interactive debugging using board-specific xsdb.cfg
files for automatic target selection and platform initialization.

- Add do_debug_native() for interactive debugging
- Auto-detect board config from support/xsdb.cfg
- Prevent auto-execution to enable breakpoint debugging
- Add --hw-server for remote board support
- Display XSDB command reference on startup

Splitting do_run() into do_flash()/do_debug_native() adds an explicit
self.require('xsdb') check on the flash path, which do_run() did not
have before.

The generated debug parameter file reuses the same ordered key/value
"boot_arg" list as flashing, so a native debug session loads the
identical set of boot artifacts, in the same board-defined order, as
a flash.

Boards with multi-stage bring-up (e.g. zynqmp_apu/zynqmp_rpu running
FSBL or PMUFW before the final application load) call "con" one or
more times before the load that should stay paused for breakpoints.
Only the LAST standalone "con" and "exit" in the board cfg are
neutralized, so earlier bring-up stages still run to completion.

Signed-off-by: Appana Durga Kedareswara rao <appana.durga.kedareswara.rao@amd.com>
2026-07-17 08:42:21 +02:00
Appana Durga Kedareswara rao
29ecb2f695 runners: xsdb: Pass boot artifacts to xsdb.cfg as key/value pairs
Board xsdb.cfg/xsdb_cfg.tcl scripts previously read their boot
artifacts (bitstream, FSBL, PDI, bl31, system.dtb, PMU firmware) as
positional arguments. That only works if every artifact lands in
exactly the position each board's load_image proc expects, which
breaks down as soon as two boards disagree on the set or order of
artifacts they take (e.g. PDI-based Versal boots vs. bitstream+FSBL
ZynqMP/Kria boots), and gives boards no way to validate what they
were actually given.

Give each board a small shared parse_args helper
(boards/amd/common/xsdb_parse_args.tcl, sourced by every board's
xsdb.cfg/xsdb_cfg.tcl instead of duplicating it 11 times) that turns
argv into an associative array from explicit "key value" pairs,
validating required/optional/unknown keys with a clear Tcl-level
error. The west runner builds that flat key/value list instead of a
positional one; order no longer matters, and each board only has to
declare the keys it understands. Every artifact keeps the exact
required/optional status it had before this change: bl31 stays
required on versal_apu/versal2_apu/versalnet_apu (previously loaded
unconditionally, no presence check), and bitstream/FSBL/bl31/PMUFW
stay optional wherever they were guarded by a "string length" check
(zynqmp_apu, zynqmp_rpu, kv260_r5).

Also add a generic, repeatable "--param NAME VALUE" option for
anything not covered by the existing --bitstream/--fsbl/--pdi/--bl31/
--system-dtb/--pmufw options -- e.g. "--param pl_pdi <path>" to
program a PL PDI (FPGA fabric) on boards whose xsdb.cfg declares a
"pl_pdi" parameter. Repeated --param calls sharing a NAME are merged
into one space-joined Tcl list value, since Tcl's "array set" would
otherwise keep only the last value for a duplicate key; this lets
partial-reconfiguration designs load any number of PL PDIs, in order,
without the runner needing to know about that use case specifically.

Signed-off-by: Appana Durga Kedareswara rao <appana.durga.kedareswara.rao@amd.com>
2026-07-17 08:42:21 +02:00
Appana Durga Kedareswara rao
bc6e8fe33c scripts: west_commands: xsdb: Simplify test_xsdb.py test case data
TEST_CASES repeated every field as an explicit None in every case even
when unused, which is not needed: dict.get() already returns None for
an absent key. Each case now only lists the keys it overrides, and the
two runner-construction tests read the rest via tc.get(key). No
behavior change.

Signed-off-by: Appana Durga Kedareswara rao <appana.durga.kedareswara.rao@amd.com>
2026-07-17 08:42:21 +02:00
Minyuan Xue
1f52424973 ci: test_plan_v2: fix ManifestStrategy crash on unchanged revisions
ManifestStrategy.analyze() returned set(manifest_files) - the set of
consumed filenames - as the calls list when west.yml changed but no
project revision differed (e.g. an unrelated field or formatting
edit). TestPlanOrchestrator.run() iterates calls and accesses
call.full_run, so a plain filename string raised:

  AttributeError: 'str' object has no attribute 'full_run'

This affects any PR that touches west.yml without bumping a project
revision, independent of the actual manifest change. Return an empty
calls list instead, and add regression tests covering both the
no-revision-change and revision-change paths.

Assisted-by: Claude:claude-sonnet-5
Signed-off-by: Minyuan Xue <minyuan_xue@realsil.com.cn>
2026-07-16 10:52:02 -04:00
Tim Pambor
d7ba1048cb Revert "scripts: pylib: make jsonschema import in domains optional"
This reverts commit 26ad9ce22e.

Signed-off-by: Tim Pambor <tim.pambor@codewrights.de>
2026-07-16 10:50:15 -04:00
Anas Nashif
28c05923ff twister: coverage: fail clearly on an empty tracefile merge
When no per-instance tracefiles exist, the merge stage built an lcov
command with just --output-file and no action option, which lcov rejects
with an opaque "capture report stage failed with 255".

Report the missing tracefiles instead.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Anas Nashif <anas.nashif@intel.com>
2026-07-16 10:49:47 -04:00