Jenkins for firmware builds (MCUXpresso + MPLAB X)

A general-purpose Jenkins controller plus two toolchain-specific build agents, connected over SSH inside a private Docker network:

  • jenkins-controller - lean controller, no toolchains, numExecutors: 0 so it only orchestrates. Configured entirely via controller/casc/jenkins.yaml (JCasC) - security realm, the SSH credential, and both agent node definitions are declared there.
  • mcuxpresso-agent - Ubuntu + NXP's Arm GNU Toolchain/CMake/Ninja, fetched headlessly via MCUXpressoInstallerCLI (see agents/mcuxpresso/Dockerfile and installers/mcuxpresso/README.md for how that actually works - it's not a plain apt package). Jenkins label: mcuxpresso arm-gcc.
  • mplabx-agent - Ubuntu + MPLAB X IDE + XC8/XC16/XC32 compilers. Jenkins label: mplabx.

Point pipelines at a toolchain with agent { label 'mcuxpresso' } or agent { label 'mplabx' }.

MCUXpresso SDKs

SDKs are stored outside the agent container and mounted read-only from the Docker host:

host:      /home/brent/jenkins-docker/sdks
container: /opt/mcux-sdks

Keep each SDK in a versioned directory so pipelines can select one explicitly, for example:

/home/brent/jenkins-docker/sdks/EVK-MIMXRT1020/25.06.00-8a1cd039

Set SdkRootDirPath in a pipeline when it needs a path other than its project default. The parent directory is mounted read-only, so adding or replacing an SDK is an explicit host-side operation rather than a build side effect. The sdks/ directory is ignored by Git so initializing and pushing this infrastructure directory does not upload the vendor SDK contents.

Why separate images

Each vendor toolchain is large, versioned independently, and installed from a manually-downloaded, license-gated installer. Keeping them out of the controller means the controller stays small/disposable, and you can rebuild/upgrade one toolchain without touching the other or restarting Jenkins itself.

One-time setup

  1. Get the vendor installers (both require a free account/login to download, so this step can't be automated in the Dockerfile - though the actual component installs that follow don't need any further login):

    • MCUXpresso Installer (*.deb.bin) -> installers/mcuxpresso/ (see the README there)
    • MPLAB X + XC8/XC16/XC32 .sh installers -> installers/mplabx/ (see the README there)
  2. Generate the SSH keypair and admin password:

    ./scripts/setup-secrets.sh
    

    This writes secrets/agent_ssh_key (+ .pub) and secrets/jenkins_admin_password.txt. Note the printed password - you'll need it to log in. Nothing in secrets/ is committed to git.

  3. Build and start everything:

    docker compose build
    docker compose up -d
    
  4. Visit http://localhost:8080 and log in as admin with the password from step 2. Under Manage Jenkins > Nodes, confirm mcuxpresso-agent and mplabx-agent come online (they connect automatically via the SSH launcher defined in JCasC - no manual node setup needed).

Things to verify before relying on this in production

  • Silent-install flags: the MPLAB X/XC installer commands in agents/mplabx/Dockerfile use --mode unattended --unattendedmodeui none, the standard flags for InstallBuilder-based installers, but Microchip hasn't guaranteed this across every release. Run the installer with --help locally against the exact version you downloaded before trusting the build.
  • Install paths: the PATH set in that same Dockerfile assumes /opt/microchip/...; Microchip has changed default install directories across MPLAB X major versions, so confirm it matches what your installer actually chose (check the build logs, or add -D INSTALL_DIR=... to pin it explicitly).
  • MCUXpresso component versions: the Dockerfile bakes in whatever mcux-cli install -c armToolchain cmake ninja resolves to as "current" at build time (verified working: Arm GNU Toolchain 14.2.1, CMake 3.30.0, Ninja 1.13.2). mcux-cli install --help lists older versions too (e.g. Arm GNU Toolchain 13.2.1) but a quick test showed -c armToolchain:13.2.1-style pinning is rejected as an invalid choice - I didn't find the right syntax for requesting a non-default version, so for now you get whatever's newest. Worth checking NXP's own docs if you need a pinned version for reproducibility.
  • Licensing: XC8/XC16/XC32 free-tier compilers work out of the box; Standard/Pro tiers need a license file or floating license server, which isn't configured here.
  • Host key verification: the controller's SSH launcher uses nonVerifyingKeyVerificationStrategy, fine for an isolated local Docker network but worth tightening (knownHosts strategy) if you deploy this beyond your machine.

Adding more toolchains later

Add a new directory under agents/<name>/Dockerfile, a matching installers/<name>/, a service in docker-compose.yml, and a permanent node block in controller/casc/jenkins.yaml with a distinct label - same pattern as the two agents here.

Description
No description provided
Readme 39 KiB
Languages
Dockerfile 91.1%
Shell 8.9%