Skip to main content

bud_runner

bud_runner is the command-line execution agent for Bud TMP. It runs trusted Python test suites, emits CI-friendly reports, uploads results to Bud, and can operate as a long-lived registered runner daemon.

Creator: Amine El Omari

bud_runner is designed for machines you manage, including dedicated lab hosts and self-hosted CI runners.

What it does

  • Runs test case lists from local automation or CI.
  • Produces JUnit XML, JSON, or text output.
  • Creates and updates Bud test runs.
  • Uploads test results and artifacts to Bud.
  • Runs work the backend has queued for a test station.
  • Registers persistent runner identities.
  • Runs a heartbeat and local control daemon.
  • Spools failed result uploads for later retry.

Compatibility

bud_runner Intended budtestlibrary pairing Notes
1.0.3 1.0.3 Backend-queued runs, --artifact uploads, optional addr on FlashEvent
1.0.2 1.0.2 Multipart artifact uploads and formatting fixes
1.0.1 1.0.1 Timeout fixes and PyPI release structure

Installation

python -m pip install bud-runner budtestlibrary

Requirements:

  • Python 3.9 or later;
  • budtestlibrary;
  • a Bud backend for registration, test-run creation, or result upload.

The package can execute tests and generate local reports without Bloom. Bloom is not a direct dependency of bud_runner.

Trusted-code execution model

bud_runner imports and executes Python test code from the selected local workspace. Only run test modules you trust. Test code can access files, the network, subprocesses, and any credentials available to the runner account.

Each discovered test class runs in a separate spawned operating-system process. Per-test and global suite timeouts limit hangs, but process isolation is not a security sandbox.

The daemon control socket binds to 127.0.0.1 by default. Do not expose it to an untrusted network. Non-loopback binding requires an external protection layer.

Quick start

Run tests locally

python -m bud_runner run-tests \
  --test-case-list <Module.ClassName> \
  --output report_junit.xml \
  --no-upload

Run and upload results

python -m bud_runner run-tests \
  --test-case-list <Module.ClassName> \
  --backend-url "https://<your-bud-instance-url>" \
  --username "ci-user@example.com" \
  --password "<bud-password>" \
  --upload

If an upload returns 401 Unauthorized and credentials were supplied, bud_runner logs in again through the Bud authentication API, refreshes the cached user token, and retries once.

Upload artifacts with the results

--artifact (-A) takes a file path or glob and is repeatable. Matching files are uploaded alongside the results, so logs, captures, and reports stay attached to the run:

python -m bud_runner run-tests \
  --test-case-list <Module.ClassName> \
  --artifact "logs/*.log" \
  --artifact capture.png \
  --upload

A file that fails to upload is reported but does not fail the run.

Run work queued by Bud

claim-run asks the backend for this station's next queued run and executes it through the same path as any other run. With --interval 0 (the default) it claims once and exits, which suits a cron entry or a one-shot CI job; a non-zero interval polls continuously:

python -m bud_runner claim-run \
  --backend-url "https://<your-bud-instance-url>" \
  --username "station-01@example.com" \
  --workspace ./tests \
  --interval 30 \
  --artifact "logs/*.log"

--workspace points at the directory holding this station's test modules and defaults to the current directory. --test-timeout and --suite-timeout cap a single test and the full suite, at 300 and 1800 seconds respectively.

Create a Bud test run

python -m bud_runner add-test-run \
  --test-case-list <Module.ClassName> \
  --test-suite-name "Nightly Automated Tests" \
  --url-test-software https://github.com/org/tests.git \
  --ref-test-software main \
  --sw-under-test https://github.com/org/product.git \
  --ref-sw-under-test release-2026.07

Register a runner

Each station enrols with its own key. A Bud administrator mints it under Test Stations → Enrolment keys; it is shown once, and pins to the first station that registers with it. There is no shared secret across benches.

The administrator also names the station when minting the key, and that name wins: if it differs from the --username passed here, registration returns the name Bud assigned and the runner stores that one. A later rename in Bud is picked up on the next heartbeat.

export RUNNER_API_KEY="<enrolment-key-minted-in-bud>"
export BUD_BACKEND_URL="https://<your-bud-instance-url>"

python -m bud_runner register \
  --username "lab-station-01" \
  --socket-port 53035

Runner identity, tokens, and daemon state are stored under ~/.bud/. Keep that directory private to the runner account and never commit it.

Start the daemon

python -m bud_runner daemon \
  --username "lab-station-01" \
  --location "Hardware Lab" \
  --bind-host 127.0.0.1

Run the daemon under a service manager such as systemd, launchd, or a Windows service wrapper.

Configuration

Environment variables:

export BUD_BACKEND_URL="https://<your-bud-instance-url>"
export BUD_TOKEN="<user-token>"
export BUD_RUNNER_ACCOUNT="lab-station-01"
export BUD_RUNNER_TOKEN="<runner-token>"
export RUNNER_API_KEY="<enrolment-key-minted-in-bud>"

Project-level, non-secret context can be stored in app.properties:

budBackend=https://<your-bud-instance-url>
budRunnerAccount=lab-station-01

Do not put passwords, user tokens, runner tokens, or enrolment keys in app.properties.

Main commands

Command Purpose
run-tests Execute tests, generate reports, and optionally upload results
claim-run Run work the backend has queued for this test station
list-tests Resolve and list discovered tests without executing them
add-test-run Create a Bud test run
register Register or re-register a runner identity
daemon Run heartbeat and local control services
status Show local configuration, versions, and Bud health
version Print the installed package version

Run python -m bud_runner <command> --help for complete options.

CI example

name: Run tests

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: self-hosted
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: python -m pip install bud-runner budtestlibrary
      - name: Execute tests
        env:
          BUD_BACKEND_URL: ${{ secrets.BUD_BACKEND_URL }}
          BUD_TOKEN: ${{ secrets.BUD_TOKEN }}
        run: |
          python -m bud_runner run-tests \
            --test-case-list <Module.ClassName> \
            --ref-test-software ${{ github.sha }} \
            --output report_junit.xml
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: test-results
          path: report_junit.xml

Licence

bud_runner is permanent free and open-source software licensed under the GNU Affero General Public License v3.0 only (AGPL-3.0-only).

No paid EmbedLabs licence is required to use bud_runner, including for commercial use, provided the AGPL terms are followed. Accepted community contributions remain publicly available under AGPL-3.0-only and will not become proprietary-only.

Bud and Bloom are separate source-available applications. Commercial licensing, deployment, integration, and support offered through sales@embedlabs.de applies to those applications and services—not to the bud_runner package licence.

Technical, security, and contribution questions: dev@embedlabs.net.

Copyright (C) 2026 Mohamed Amine El Omari Alaoui, operating under the name EmbedLabs.

Metadata

Release files for bud-runner 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for bud-runner 1.1.0
File Size Uploaded
bud_runner-1.1.0.tar.gz 45.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for bud-runner 1.1.0
File Interpreter ABI Platform
bud_runner-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 89.7 kB

Release files / bud_runner-1.1.0.tar.gz

Download URL bud_runner-1.1.0.tar.gz
Size 45.1 kB
Tags Source
SHA-256 checksum
How to use checksums
9165a7a9d88c49029c0cba704e35995a3f6c7ae227601d0be2d15b490d63b4c3
BLAKE2b-256 checksum
How to use checksums
5fb9275be8d70e9249347f8ad34b3b26fbc8438e54fd64d19b95d4197390cd03
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

Release files / bud_runner-1.1.0-py3-none-any.whl

Download URL bud_runner-1.1.0-py3-none-any.whl
Size 44.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
80ee663578d05b631a494a52e30af8741c766a6194f9350598fc11f662a70080
BLAKE2b-256 checksum
How to use checksums
38d7517de9086288daf81009ef48dc20ac9be6677048ca9e5a72d8d18c927520
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page