Skip to content

Portable builds#17

Merged
jrpear merged 15 commits into
mainfrom
portable-builds
Jul 7, 2026
Merged

Portable builds#17
jrpear merged 15 commits into
mainfrom
portable-builds

Conversation

@nateinaction

@nateinaction nateinaction commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

This PR should make it simpler to build the software in the repo.

Just run make build

  • No need to have python modules installed globally or even have python installed at all.
  • pre-commit hooks now work no matter your local shell... yay!

This PR also includes CI to verify that the Make commands work and the software builds.

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@nateinaction, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 22 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2c29cf7c-ebc2-45f1-ba67-b91f4f50c9d4

📥 Commits

Reviewing files that changed from the base of the PR and between 48a02a2 and 94914ed.

📒 Files selected for processing (6)
  • .github/actions/setup/action.yml
  • .github/workflows/ci.yaml
  • AGENTS.md
  • docs/additional-resources/wsl-notes.md
  • docs/main-content/build-flash-run.md
  • makelib/zephyr.mk
📝 Walkthrough

Walkthrough

Introduces a uv-based Python toolchain management system via new makelib/build-tools.mk and makelib/zephyr.mk modules, a new west uv command (lib/west-commands/uv.py), and a rewritten Makefile with venv-driven targets and BFT/flash/debug workflows. Adds a GitHub Actions CI workflow and pre-commit configuration, removes the old git hook, and applies widespread whitespace, typo, and formatting fixes across source and documentation files.

Changes

Build System, Toolchain, CI, and Cleanup

Layer / File(s) Summary
west uv command
lib/west-commands/uv.py, west-commands.yml, west.yml
Adds a new west uv command that collects and installs Zephyr Python requirements via uv pip, with venv validation and module filtering; registers it in the west manifest.
makelib modules
makelib/build-tools.mk, makelib/zephyr.mk
Introduces build-tools.mk for uv binary download/install and UV_RUN definition, and zephyr.mk for Zephyr workspace init, SDK version detection, SDK install, export, and Python dep orchestration targets.
Makefile rewrite
Makefile, .gitignore
Exports VIRTUAL_ENV/UV_BIN, adds help/fmt/fprime-venv/generate/build targets, rewrites gds via UV_RUN, replaces BFT execution with setsid+GDS PID trapping+pytest, and defines flash1/flash2/gdb/attach targets using probe-rs.
CI workflow and pre-commit
.github/workflows/ci.yaml, .pre-commit-config.yaml, .github/actions/setup/action.yml
Adds ci workflow with fmt and build jobs; adds pre-commit config with clang-format, ruff, codespell, and standard hooks; removes old githooks/pre-commit script.
README, AGENTS.md, fprime-gds.yml
README.md, AGENTS.md, fprime-gds.yml
Updates README setup/flashing instructions to use make build; updates AGENTS.md with CI/build-system and uv-based env guidance; fixes fprime-gds.yml dictionary path YAML tag.
Whitespace, typo, and formatting fixes
.gdbinit, CMakeLists.txt, CMakePresets.json, FprimeZephyrReference/..., docs/..., settings.ini, test/...
Applies clang-format/ruff/whitespace cleanup to FPP configs, HPP, CMake, and test files; fixes typos and broken links across documentation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 Hoppity-hop, the Makefile grew,
With uv and venvs all shiny and new!
West commands installed with a curl and a ping,
CI now checks every formatting thing.
Typos corrected, the docs gleam bright—
This bunny approves, it all looks right! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and clearly reflects the PR’s focus on portable build tooling.
Description check ✅ Passed The description matches the changeset by describing simpler builds, portable hooks, and CI verification.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@nateinaction
nateinaction marked this pull request as ready for review June 30, 2026 03:40
@nateinaction
nateinaction requested a review from jrpear June 30, 2026 03:53

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/additional-resources/wsl-notes.md (1)

17-26: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix broken step numbering: step 4 is missing.

The list jumps from step 3 (line 17) to step 5 (line 26). Either renumber step 5 to 4, or add the missing step (typically usbipd attach --busid <BUSID> after bind).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/additional-resources/wsl-notes.md` around lines 17 - 26, The numbered
list in the WSL notes skips a step between the USBIPD bind commands and the WSL
visibility check. Update the sequence in the markdown list by either renumbering
the current “5. On WSL confirm visibility of USB device” entry to the next
correct number, or insert the missing step after the bind commands in the same
section (the step should align with the USBIPD workflow), so the numbering is
continuous in docs/additional-resources/wsl-notes.md.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yaml:
- Around line 24-26: The CI Build step currently exercises only the serial make
path, so update the job to run the build target under parallel execution instead
of plain make build. Adjust the Build step in the workflow to use make --jobs=2
build so the same prerequisite scheduling behavior that can expose dependency
races is covered by CI.
- Around line 1-32: The CI workflow uses mutable action tags and lacks explicit
token scoping; update the workflow in ci.yaml by adding a top-level permissions
block for the jobs, pin the actions/checkout and actions/upload-artifact
references in the fmt and build jobs to full commit SHAs, and set
persist-credentials to false on each actions/checkout step if git authentication
is not required. Use the existing fmt and build job steps to locate the two
checkout usages and the upload-artifact step.

In `@docs/main-content/build-flash-run.md`:
- Around line 33-37: In the note within the build-flash-run documentation,
update the operating system name from “MacOS” to “macOS” to match Apple’s
official capitalization. Locate the text in the note near the serial device
example and replace the incorrect casing only, without changing the surrounding
command or link text.

In `@Makefile`:
- Around line 59-67: The artifact-consuming helper targets are missing an
explicit dependency on the build step, so they can run before the generated
files exist on a clean tree. Update the Make graph so gds, gdb*, and attach*
depend on build the same way flash* already does, and keep the existing helper
prerequisites like check-no-gds and fprime-venv intact. Use the target names gds
and the related gdb/attach rules to locate and adjust their dependency lists.
- Around line 38-49: The Makefile is missing the documented generate-force
recovery entry point, so contributors hitting a corrupted cache will fail on
make generate-force. Add a thin alias target named generate-force that routes to
the existing generate behavior (or otherwise preserves the documented recovery
path), and keep the related generate, generate-if-needed, and build targets
consistent with the new entry point.

In `@makelib/build-tools.mk`:
- Line 22: UV_RUN currently only sets up the virtual environment, so the build
still falls back to a globally installed uv when UV_BIN is unset in the uv
command path. Update UV_RUN in build-tools.mk to also export the managed uv
binary path from the local fprime-venv, matching the fallback logic in uv.py and
ensuring zephyr.mk invokes the bundled uv consistently on clean machines.
- Around line 19-20: The installer step in the `$(UV)` target hides failures
because piping `curl` directly into `sh` can succeed even when the download
breaks; update the `$(UV)` rule to avoid the pipeline by saving the installer
script to a temporary file first and then executing it. Use the existing
`$(UV)`, `$(UV_DIR)`, and `UV_VERSION` recipe in `build-tools.mk` as the place
to make this change, keeping the same install behavior while making download
errors surface properly.

In `@makelib/zephyr.mk`:
- Around line 33-34: The clean-zephyr-workspace target currently only
deinitializes the Zephyr submodule, so the west-managed checkouts are not
removed. Update the clean-zephyr-workspace recipe in zephyr.mk to explicitly
remove the lib/zephyr-workspace/{bootloader,modules,tools} directories instead
of relying on git submodule deinit --all -f, and keep the target focused on
fully cleaning the workspace state.
- Around line 10-13: Delay SDK_VERSION evaluation in zephyr.mk so it is expanded
only after zephyr-workspace has populated ZEPHYR_PATH. Update the SDK_VERSION
assignment to use recursive expansion instead of immediate expansion, and keep
the existing ZEPHYR_SDK_PATH fallback tied to SDK_VERSION so it resolves
correctly on a fresh checkout.

---

Outside diff comments:
In `@docs/additional-resources/wsl-notes.md`:
- Around line 17-26: The numbered list in the WSL notes skips a step between the
USBIPD bind commands and the WSL visibility check. Update the sequence in the
markdown list by either renumbering the current “5. On WSL confirm visibility of
USB device” entry to the next correct number, or insert the missing step after
the bind commands in the same section (the step should align with the USBIPD
workflow), so the numbering is continuous in
docs/additional-resources/wsl-notes.md.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c020ad1f-35d7-414a-94ce-5b4470ad0012

📥 Commits

Reviewing files that changed from the base of the PR and between 58b16e5 and 48a02a2.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (41)
  • .agents/skills/confirm-crash-and-gather-logs/SKILL.md
  • .clang-format
  • .gdbinit
  • .github/actions/setup/action.yml
  • .github/workflows/ci.yaml
  • .gitignore
  • .pre-commit-config.yaml
  • .west/config
  • AGENTS.md
  • CMakeLists.txt
  • CMakePresets.json
  • FprimeZephyrReference/Components/ByteComBridge/docs/sdd.md
  • FprimeZephyrReference/Components/FatalHandler/FatalHandler.hpp
  • FprimeZephyrReference/ReferenceDeployment/CMakeLists.txt
  • FprimeZephyrReference/ReferenceDeployment/README.md
  • FprimeZephyrReference/ReferenceDeployment/test/int/int_config.json
  • FprimeZephyrReference/ReferenceDeployment/test/int/test_reboot_machine.py
  • FprimeZephyrReference/project/config/CdhCoreConfig.fpp
  • FprimeZephyrReference/project/config/CdhCoreTlmConfig.fpp
  • FprimeZephyrReference/project/config/ComCcsdsConfig.fpp
  • Makefile
  • README.md
  • docs/additional-resources/board-list.md
  • docs/additional-resources/specifying-board-configuration.md
  • docs/additional-resources/troubleshooting.md
  • docs/additional-resources/wsl-notes.md
  • docs/main-content/build-flash-run.md
  • docs/main-content/initial-setup.md
  • docs/uploading/stm32/Arduino-STM32CubeProgrammer-Arm-Issue.md
  • docs/uploading/stm32/stm32.md
  • docs/uploading/teensy.md
  • fprime-gds.yml
  • githooks/pre-commit
  • lib/west-commands/uv.py
  • makelib/build-tools.mk
  • makelib/zephyr.mk
  • settings.ini
  • test/conftest.py
  • test/two-board/main_test.py
  • west-commands.yml
  • west.yml
💤 Files with no reviewable changes (6)
  • .west/config
  • githooks/pre-commit
  • .clang-format
  • test/two-board/main_test.py
  • .gdbinit
  • .agents/skills/confirm-crash-and-gather-logs/SKILL.md

Comment thread .github/workflows/ci.yaml
Comment thread .github/workflows/ci.yaml
Comment thread docs/main-content/build-flash-run.md Outdated
Comment thread Makefile
Comment thread Makefile
Comment thread makelib/build-tools.mk
Comment thread makelib/build-tools.mk
Comment thread makelib/zephyr.mk
Comment thread makelib/zephyr.mk Outdated

@jrpear jrpear left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a big improvement to the approachability of the project, thanks Nate!

I left some comments and suggestions if you want to take a look when you've got a chance.

Comment thread makelib/build-tools.mk
.PHONY: uv
uv: $(UV) ## Download uv
$(UV): $(TOOLS_DIR)
@test -s $(UV) || { mkdir -p $(UV_DIR); curl -LsSf https://astral.sh/uv/$(UV_VERSION)/install.sh | UV_UNMANAGED_INSTALL=$(UV_DIR) sh > /dev/null; }

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a leery about running a shell script downloaded from the internet. It's from astral.sh so I'm not worried about malware, but these scripts can sometimes do very annoying things like create nodes in your home directory, modify your rc files, etc. And they can be changed at any point. Can we download an executable directly or maybe install via a tool that will just put the executable where we want like cargo? We already require cargo in order to install a particular probe-rs version for the attach and gdb targets.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the concern. We are configuring the install script to do exactly that. It will download the binary for your distribution into the UV_DIR which will be ./build/uv-someversion/{uv|uvx}. Try it out!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK wonderful.

If the recipe was just downloading the release from e.g. https://github.com/astral-sh/uv/releases/download/0.11.26/uv-x86_64-unknown-linux-gnu.tar.gz and extracting uv I think it would be a bit clearer that that's all that's going on. What do you think?

Comment thread makelib/build-tools.mk
$(UV): $(TOOLS_DIR)
@test -s $(UV) || { mkdir -p $(UV_DIR); curl -LsSf https://astral.sh/uv/$(UV_VERSION)/install.sh | UV_UNMANAGED_INSTALL=$(UV_DIR) sh > /dev/null; }

UV_RUN ?= VIRTUAL_ENV=$(shell pwd)/fprime-venv PATH=$(shell pwd)/fprime-venv/bin:$$PATH

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is UV_RUN a good name for this? There doesn't seem to be anything uv-related going on here unless I am missing something.

Comment thread makelib/zephyr.mk
Comment thread makelib/zephyr.mk

.PHONY: zephyr-config
zephyr-config: fprime-venv ## Configure west
@test -f .west/config || { \

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we just call the target .west/config and skip this check?

Comment thread makelib/zephyr.mk
.PHONY: zephyr-export
zephyr-export: zephyr-workspace ## Export Zephyr environment variables
@test -d $(CMAKE_PACKAGES)/Zephyr/ || \
test -d $(CMAKE_PACKAGES)/ZephyrUnittest/ || \

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing here, couldn't we have two targets named each of these files and the recipe be just west zephyr-export?

Comment thread Makefile
.PHONY: generate-if-needed
BUILD_DIR ?= $(shell pwd)/build-fprime-automatic-zephyr
generate-if-needed: submodules fprime-venv zephyr
@test -d $(BUILD_DIR) || $(UV_RUN) fprime-util generate --force

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing here, seems silly to test dir existence in a recipe then run if it's not there, that's what Make is for, I think we should just name the target the thing that's being made.

Comment thread Makefile
probe-rs attach --probe $(PROBE_USB_ID):$(ACTIVE_PROBE) build-artifacts/zephyr.elf

include makelib/build-tools.mk
include makelib/zephyr.mk

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we put these up with the other include?

Comment thread Makefile
Comment thread AGENTS.md
modules, so they must depend on `zephyr-workspace`, not just `fprime-venv`.

When adding a build step that consumes files produced by another step, add the
corresponding `make` prerequisite rather than assuming run order.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need all this explicit guidance about how the Makefile works in AGENTS.md? I have found coding agents to be pretty good at figuring this stuff out on the fly when necessary, so if we can keep AGENTS.md shorter for the sake of each of our own "context windows" then let's do it. But if you've had an agent getting tripped up writing Make rules I don't have a problem with this.

Comment thread AGENTS.md
When adding a build step that consumes files produced by another step, add the
corresponding `make` prerequisite rather than assuming run order.

The west manifest is defined in `west.yml` and `west.yml` specifies which Zephyr modules to download. When modifying the build system or Zephyr dependencies, keep `west.yml` in sync with `proves-core-reference` as a reference implementation.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little dubious about this instruction. proves-core-reference is not necessarily visible to an agent in the repo. And just because a change in west.yml is suitable for proves-core-reference doesn't mean it's suitable for ground-radio-controller.

@jrpear
jrpear self-requested a review July 7, 2026 00:24

@jrpear jrpear left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going to merge and move the comments to an issue in the interest of keeping PR from rotting.

@jrpear
jrpear merged commit e018bf4 into main Jul 7, 2026
3 checks passed
This was referenced Jul 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants