* ci(pr-review-poster): add line-anchored review poster and migrate clang-tidy
Adds a generic PR review-comment poster as a sibling of the issue-comment
poster from #27021. Replaces platisd/clang-tidy-pr-comments@v1 in the
Static Analysis workflow with an in-tree, fork-friendly producer + poster
pair so fork PRs get inline clang-tidy annotations on the Files changed
tab without trusting a third-party action with a write token.
Architecture mirrors pr-comment-poster: a producer (clang-tidy.yml) runs
inside the px4-dev container and writes a `pr-review` artifact containing
manifest.json and a baked comments.json. A separate workflow_run-triggered
poster runs on ubuntu-latest with the base-repo write token, validates the
artifact, dismisses any stale matching review, and posts a fresh review
on the target PR. The poster never checks out PR code and only ever reads
two opaque JSON files from the artifact.
Stale-review dismissal is restricted to reviews authored by
github-actions[bot] AND whose body contains the producer's marker. A fork
cannot impersonate the bot login or inject the marker into a human
reviewer's body, so the poster can never dismiss a human review. APPROVE
events are explicitly forbidden so a bot cannot approve a pull request.
To avoid duplicating ~120 lines of HTTP plumbing between the two posters,
the GitHub REST helpers (single-request, pagination, error handling) are
extracted into Tools/ci/_github_helpers.py with a small GitHubClient
class. The existing pr-comment-poster.py is refactored to use it; net
change is roughly -80 lines on that script. The shared module is
sparse-checked-out alongside each poster script and is stdlib only.
The clang-tidy producer reuses MIT-licensed translation logic from
platisd/clang-tidy-pr-comments (generate_review_comments,
reorder_diagnostics, get_diff_line_ranges_per_file and helpers) under a
preserved attribution header. The HTTP layer is rewritten on top of
_github_helpers so the producer does not pull in `requests`. Conversation
resolution (the GraphQL path) is intentionally dropped for v1.
clang-tidy.yml now produces the pr-review artifact in the same job as
the build, so the cross-runner compile_commands.json hand-off and
workspace-path rewriting are no longer needed and the
post_clang_tidy_comments job is removed.
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
* ci(workflows): bump action versions to clear Node 20 deprecation
GitHub has deprecated the Node 20 runtime for Actions as of
September 16, 2026. Bump the pinned action versions in the three poster
workflows to the latest majors, all of which run on Node 24:
actions/checkout v4 -> v6
actions/github-script v7 -> v8
actions/upload-artifact v4 -> v7
No behavior changes on our side: upload-artifact v5/v6/v7 only added an
optional direct-file-upload mode we do not use, and checkout v5/v6 are
runtime-only bumps. The security-invariant comment headers in both
poster workflows are updated to reference the new version so they stay
accurate.
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
* ci(pr-posters): skip job when producer was not a pull_request event
Both poster workflows previously ran on every workflow_run completion of
their listed producers and then silently no-oped inside the script when
the triggering producer run was a push-to-main (or any other non-PR
event). That made the UI ambiguous: the job was always green, never
showed the reason it did nothing, and looked like a failure whenever
someone clicked in looking for the comment that was never there.
Gate the job at the workflow level on
github.event.workflow_run.event == 'pull_request'. Non-PR producer runs
now surface as a clean "Skipped" entry in the run list, which is
self-explanatory and needs no in-script summary plumbing.
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
---------
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Adds a stand-alone workflow that posts or updates sticky PR comments on
behalf of any analysis workflow, including those triggered by fork PRs.
The poster runs on `workflow_run` in the base repo context, which is the
standard GitHub-sanctioned way to get a write token on events that
originate from untrusted forks without ever checking out fork code.
All validation, GitHub API interaction, and upsert logic lives in
Tools/ci/pr-comment-poster.py (Python 3 stdlib only, two subcommands:
`validate` and `post`). The workflow file itself is a thin orchestrator:
sparse-checkout the script, download the pr-comment artifact via
github-script, unzip, then invoke the script twice. No inline jq, no
inline bash validation, no shell-interpolated marker strings. The
sparse-checkout ensures only Tools/ci/pr-comment-poster.py lands in the
workspace, never the rest of the repo.
Artifact contract: a producer uploads an artifact named exactly
`pr-comment` containing `manifest.json` (with `pr_number`, `marker`, and
optional `mode`) and `body.md`. The script validates the manifest
(positive integer pr_number, printable-ASCII marker bounded 1..200
chars, UTF-8 body under 60000 bytes, mode in an allowlist), finds any
existing comment containing the marker via the comments REST API, and
either edits it in place or creates a new one.
The workflow file header documents six security invariants that any
future change MUST preserve, most importantly: NEVER check out PR code,
NEVER execute anything from the artifact, and treat all artifact
contents as opaque data.
Why a generic poster and not `pull_request_target`: `pull_request_target`
is the tool people reach for first and the one that most often turns
into a supply-chain vulnerability, because it hands a write token to a
workflow that is then tempted to check out the PR head. `workflow_run`
gives the same write token without any check-out temptation, because
the only input is a pre-produced artifact treated as opaque data.
Producer migrations
===================
flash_analysis.yml:
- Drop the fork gate on the `post_pr_comment` job.
- Drop the obsolete TODO pointing at issue #24408 (the fork-comment
workflow does not error anymore; it just no-ops).
- Keep the existing "comment only if threshold crossed or previous
comment exists" behaviour verbatim. peter-evans/find-comment@v3
stays as a read-only probe (forks can read issue comments just fine);
its body-includes is updated to search for the new marker
`<!-- pr-comment-poster:flash-analysis -->` instead of the old
"FLASH Analysis" heading substring.
- Replace the peter-evans/create-or-update-comment@v4 step with two
new steps that write pr-comment/manifest.json and pr-comment/body.md
and then upload them as artifact pr-comment. The body markdown is
byte-for-byte identical to the previous heredoc, with the marker
prepended as the first line so subsequent runs can find it.
- The threshold-or-existing-comment gate is preserved on both new
steps. When the gate does not fire no artifact is uploaded and the
poster no-ops.
docs-orchestrator.yml (link-check job):
- Drop the fork gate on the sticky-comment step.
- Replace marocchino/sticky-pull-request-comment@v2 with two new steps
that copy logs/filtered-link-check-results.md into pr-comment/body.md,
write a pr-comment/manifest.json with the marker
`<!-- pr-comment-poster:docs-link-check -->`, and upload the directory
as artifact pr-comment.
- The prepare step checks `test -s` on the results file and emits a
prepared step output; the upload step is gated on that output. In
practice the existing link-check step always writes a placeholder
("No broken links found in changed files.") into the file when empty,
so the guard is defensive but not load-bearing today.
- Tighten the link-check job's permissions from `pull-requests: write`
down to `contents: read`; writing PR comments now happens in the
poster workflow.
The poster's workflows allowlist is seeded with the two active
producers: "FLASH usage analysis" and "Docs - Orchestrator".
clang-tidy (workflow name "Static Analysis") is not in the list because
platisd/clang-tidy-pr-comments posts line-level review comments, a
different REST API from issue comments that the poster script does not
handle. Extending the poster to cover review comments is a follow-up.
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Add four reusable building blocks that upcoming CI optimization PRs will
consume. No existing workflow is modified; these files are dormant until
referenced.
- .github/actions/setup-ccache: restore ~/.ccache with content-hash keys,
write ccache.conf with compression and content-based compiler check
- .github/actions/save-ccache: print stats and save the cache under the
primary key produced by setup-ccache
- .github/actions/build-gazebo-sitl: build px4_sitl_default plus the
Gazebo Classic plugins with ccache stats between stages
- Tools/ci/run-clang-tidy-pr.py: compute the translation units affected
by a PR diff and invoke Tools/run-clang-tidy.py on that subset only,
exiting silently when no C++ files changed
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
The mirror swap was duplicated across two workflows. Move it into
Tools/ci/use_aws_apt_mirror.sh and call the script from each workflow
after checkout but before any heavy apt work like Tools/setup/ubuntu.sh.
The script no-ops outside runs-on (RUNS_ON_AWS_REGION unset), so it is
safe to call from forks, self-hosted runners, or local container runs
without changing behavior there. The region is read from the runs-on
environment instead of being hardcoded, so future region changes only
need updating where the runner is provisioned.
The bootstrap 'apt install git' step keeps the default mirror because
git is one package and is unlikely to hit the dep11 desync issue that
broke ubuntu.sh.
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
The SIH image is the canonical PX4 SITL container, so drop the redundant
-sih suffix and publish it as px4io/px4-sitl. Gazebo continues to publish
as px4io/px4-sitl-gazebo.
Decouples the published image name from the matrix.image identifier by
introducing a matrix.repo field, so renames like this don't require
touching the matrix logic.
This is a breaking change for anyone pulling px4io/px4-sitl-sih directly;
the old tags remain available but no new ones will be published under
that name.
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
The SIH container entrypoint resolves host.docker.internal via getent
hosts and feeds the first result to mavlink -t and uxrce_dds_client -h.
On Docker Desktop for Windows the lookup can return an IPv6 ULA first,
and both PX4 modules only parse IPv4, so they error out with
'invalid partner ip' and PX4 boots with no working MAVLink or DDS link.
Switch to getent ahostsv4, which only returns IPv4 records, so the IP
injected into the startup scripts is always parseable.
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
The packaging script only placed all_events.json.xz in an events/
subdirectory, but the firmware advertises the metadata URI at the
board directory top level. New build targets added after the
Jenkins-to-GHA migration had no legacy top-level copy, causing
QGC to get a 404 when fetching component metadata.
Fixes#26963
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Add cmake/cpack infrastructure for building .deb packages from
px4_sitl_sih and px4_sitl_default targets. Includes install rules,
package scripts, Gazebo wrapper, and CI workflow.
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Three issues caused the monthly audit to report already-resolved submodules:
1. The audit workflow grepped for "NOASSERTION" anywhere in the output,
matching the Detected column even when the Final column had a valid
override (e.g. libtomcrypt detected as NOASSERTION but overridden to
Unlicense). Changed to grep for "<-- UNRESOLVED" marker instead.
2. Submodules with an explicit NOASSERTION override in license-overrides.yaml
(like libfc-sensor-api, which is proprietary) were still counted as
failures. Now treated as "acknowledged" since someone intentionally
added the override entry.
3. Added missing BSD-3-Clause override for sitl_gazebo-classic (PX4 org
project with no LICENSE file in repo).
Fixes#26932
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Several helper scripts assumes bash is available at /bin/bash. That breaks on systems
such as NixOS, where bash is resolved from PATH instead of a fixed /bin location and
causes failures like `bad interpreter` during `make format`, e.g., on my host machine:
```sh
$ make format
/PX4-Autopilot/Tools/astyle/check_code_style.sh: /PX4-Autopilot/Tools/astyle/fix_code_style.sh: /bin/bash: bad interpreter: No such file or directory
```
This change switches these entrypoints to `#!/usr/bin/env bash` so they locate bash properly.
No functional changes intended.
Signed-off-by: Onur Özkan <work@onurozkan.dev>
- migrate_c_params.py: preserve newlines and paragraph breaks in long
descriptions, use YAML block scalars for multi-line strings
- generate_params.py: support @value tags on float type parameters
(fixes RC*_REV enum values being lost during yaml generation)
Add a scalable .deb packaging framework for VOXL2, built on the
existing cmake/package.cmake CPack infrastructure. The framework
handles multi-processor boards by having the POSIX (_default) build
own the .deb and pull in the companion SLPI build's artifacts.
Board-specific files:
- cmake/package.cmake: CPack variable overrides (name, deps, version)
- cmake/install.cmake: install() rules for all .deb contents
- debian/postinst: px4-* symlinks, DSP signature, directory setup
- debian/prerm: service stop, symlink cleanup
- debian/voxl-px4.service: systemd unit (after sscrpcd)
Infrastructure changes:
- cmake/package.cmake: hook for board-specific CPack overrides
- platforms/posix/CMakeLists.txt: hook for board install.cmake
- Makefile: %_deb pattern rule (build _default, then cpack -G DEB)
- CI: auto-discover _deb targets, collect .deb artifacts, upload
to GitHub Releases
Future boards: add cmake/package.cmake + cmake/install.cmake and
CI discovers it automatically. No new file formats or tools needed.
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Read companion_targets files from board directories and exclude those
targets from CI grouped builds. The parent target builds them via
Make prerequisite, avoiding redundant CI jobs.
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Line 319 used nested quotes inside f-strings, a feature only available
in Python 3.12+. The CI Docker image (px4-dev-base-focal:2021-08-18)
runs Python 3.8, causing the "msg file docs" Jenkins stage to fail on
every main build since 6bf73d9d89.
Extract the join expressions into local variables to restore
compatibility with Python 3.8+.
airframes.xml and all_events.json.xz on the px4-travis S3 bucket have
been stale since October 2025 because package_build_artifacts.sh had
wrong paths for both files after the migration from metadata.yml to
build_all_targets.yml.
- airframes.xml: SITL builds produce it under docs/, not at the build
root (only NuttX does that). Use explicit file checks to try both.
- all_events.json.xz: was copied flat into artifacts/$build_dir/ but
the _general section expected it under events/. Preserve the
subdirectory so the copy to _general/ actually finds the file.
- Remove duplicate cp lines that were misleadingly commented as
"ROS 2 msgs".
- Fail with an error when critical _general metadata files are missing
rather than silently producing incomplete artifacts.
Also uploaded fresh metadata to S3 manually to unblock Flight Review.
Fixes#26713
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Add CI enforcement of conventional commit format for PR titles and
commit messages. Includes three Python scripts under Tools/ci/:
- conventional_commits.py: shared parsing/validation library
- check_pr_title.py: validates PR title format, suggests fixes
- check_commit_messages.py: checks commits for blocking errors
(fixup/squash/WIP leftovers) and advisory warnings (review-response,
formatter-only commits)
The workflow (.github/workflows/commit_checks.yml) posts concise
GitHub PR comments with actionable suggestions and auto-removes them
once issues are resolved.
Also updates CONTRIBUTING.md and docs with the conventional commits
convention.
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
os.scandir() returns entries in non-deterministic order, which caused
voxl2-slpi to sometimes build before voxl2_default (which it depends
on). Sort all os.scandir() calls lexicographically by name so the
shorter prefix voxl2 always precedes voxl2-slpi.
* removed commented out parts
* changed the height controller to work in Altitude mode and moved the controller to the uuv_pos_control.hpp instead of uuv_att_control.hpp
* Updated format changes etc. Removed one parameter, that is not used anymore(UUV_HGT_MODE) added my correct email
* added a rotation to the thrust, that with different roll and pitch values, x y z thrust is still working as if roll/pitch is zero.
* fixed constant roll/pitch to be 0.0 again
* added parameter for maximum distance between controlled des height and current height.
Added state observation to reset the desired height to current height when altitude mode is turned on.
* added first short descriptions of manual modes.
* update descriptions
* removed vector dependency
* feat: updated gz submodule
* fix: newline
* fix: gz submodule
---------
Co-authored-by: Pedro Roque <roque@caltech.edu>
Fix generate_msg_docs.py IndexError when a .msg file declares a single
topic that does not match the camel_to_snake default (e.g.
AuxGlobalPosition.msg). The error message referenced self.topics[1]
(out of bounds) instead of self.topics[0].
Fix camel_to_snake() regex to correctly convert names like
"AuxGlobalPosition" to "aux_global_position". The previous regex
produced "aux_globalposition" because it failed to insert an underscore
between a lowercase letter and an uppercase letter mid-word.
Also remove stderr redirection (2>&1) from all make targets in
metadata_sync.sh so that errors are visible in CI logs even in
non-verbose mode, making failures easier to diagnose.
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
* Initial changes
* index fix
* gz index fix2
* gz index fix 3
* updates
* Run prettier
* zsh env
removed gz classic
* Corrections 2
* Cleanups
* Update docs/en/dev_setup/dev_env_mac.md
* Apply suggestions from code review
* Minor subedit and prettier
* small correction
* cleanups gz harmonic brew formula
* fix(macos.sh): invert px4-sim install condition for --sim-tools
The condition checked if px4-sim WAS installed before running
brew install, meaning it would never install on a fresh system.
Add the missing negation so it installs when NOT already present.
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
* docs: rewrite macOS dev environment setup guide
- Add Xcode Command Line Tools as prerequisite
- Default to ~/.zshrc (macOS default since Catalina)
- Explain why ulimit change is needed and why in startup file
- Add reminder to open new terminal after shell config changes
- Remove broken pip3 alias workaround
- Split git clone into clone + submodule update (canonical form)
- Recommend --sim-tools flag since first build uses gz_x500
- Document what macos.sh installs and its --reinstall flag
- Clarify Gazebo comes from --sim-tools / px4-sim formula
- Add XQuartz requirement for Gazebo display
- Add verification section with key tool checks and smoke test
- Remove outdated video guide comment block
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
* conventions
---------
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
Co-authored-by: Ramon Roche <mrpollo@gmail.com>
Replace the two separate echo lines ("Starting" and "(arch)") with a
single line showing architecture and UTC timestamp:
[docker-entrypoint.sh] aarch64 | 2026-02-09T15:23:45Z
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Update the local Docker convenience script to use the unified
px4io/px4-dev image instead of the retired per-toolchain images
(px4-dev-clang, px4-dev-simulation-bionic).
Usage:
./Tools/docker_run.sh make px4_sitl_default
./Tools/docker_run.sh make tests TESTFILTER=ULogMessages
PX4_DOCKER_REPO="px4io/px4-dev:custom" ./Tools/docker_run.sh make px4_fmu-v6x_default
Changes:
- Default to px4io/px4-dev:v1.17.0-beta1, remove conditional image
guessing for clang/tests targets
- Remove stale env passthrough (Travis CI, AWS, Codecov, Coveralls)
- Keep CCACHE_DIR and sanitizer flags (PX4_ASAN/MSAN/TSAN/UBSAN)
- Fix $PWD shadowing by renaming to SCRIPT_DIR
- Use "$@" instead of "$1 $2 $3" for proper argument forwarding
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Add regex-based file exclusion to the clang-tidy runner script.
This allows excluding paths (submodules, vendored code, tests) from
static analysis without modifying .clang-tidy files in each directory.
The -exclude argument accepts a regex pattern that is matched against
file paths from the compilation database. Matching files are skipped.
Example: -exclude="src/lib/foo|src/modules/bar"
This prepares for the clang-tidy v6 to v18 migration where we need
to exclude external code that we consume but don't maintain.
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Remove Gazebo Classic installation branches for Ubuntu 18.04 and 20.04.
The script now only supports Ubuntu 22.04 and 24.04 with Gazebo Harmonic.
Supported Ubuntu LTS versions going forward:
- Ubuntu 24.04 (primary, used in CI and release builds)
- Ubuntu 22.04 (secondary, still supported)
When Ubuntu 26.04 LTS releases we will bump to 26.04/24.04.
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Remove modalai_voxl2 and qurt from CI exclusion lists and add
container overrides to use the private ghcr.io/px4/px4-dev-voxl2
image which contains the Qualcomm Hexagon SDK.
- Add voxl2 build group with x64 runner for cross-compilation
- Add GHCR credentials to workflow for private container pull
- Add packages:read permission to workflow
- Auto-build libfc_sensor.so stub during cmake configure
- Handle missing .px4/.elf gracefully in artifact packaging
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
- Add safe.directory + fetch-depth: 0 for container jobs
- Support workflow_dispatch in metadata-regen and deploy-aws
- Guard PR comments against fork PRs
- Add ccache save to pr-metadata-regen
- Use metadata_sync.sh --generate --sync instead of manual steps
- Fix msg_docs source path in metadata_sync.sh
- Guard set-version against non-release branches
- Clean up build-site needs list
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
Add conditional metadata generation for PRs that modify both docs and
source files. This fixes broken link checker reports when a PR adds a
new module and documents it simultaneously - previously the link checker
would fail because metadata files are only generated on push to main.
Changes:
- Add docs-orchestrator.yml workflow with:
- detect-changes job to check if PR touches source paths
- pr-metadata-regen job that generates metadata and uploads as artifact
- link-check job that downloads metadata artifact when available
- build-site job for VitePress site generation
- deploy-aws and crowdin-upload jobs for push events
- Prettier formatting step before auto-commit on push
- Add Prettier for markdown formatting:
- Add prettier ^3.2.0 as devDependency in docs/package.json
- Add docs/.prettierrc with prose-preserving config
- Remove normalize_whitespace from metadata_sync.sh (Prettier handles
whitespace normalization now)
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
metadata_modules.sh — generate and sync PX4 module reference documentation
Usage:
Tools/ci/metadata_modules.sh [--test-only] [--debug]
Options:
--test-only Run make target and comparison; exit 1 if diffs found, without copying files
--debug Show full make output and debug info for file comparisons
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
metadata_airframe.sh — generate and sync PX4 airframe reference documentation
Usage:
Tools/ci/metadata_airframe.sh [--test-only] [--debug]
Options:
--test-only Run make target and comparison; exit 1 if diffs found, without copying file
--debug Show full make output and debug info for comparison
Signed-off-by: Ramon Roche <mrpollo@gmail.com>