CI/CD Integration
You can integrate the Testbox into your CI/CD setup. To do this, you need a computer that is connected to the Internet and to which the test box is connected. At the moment we are using a setup with a Raspberry PI 5. We provide an Image on Docker Hub for the Raspberry Pi 5 which has installed all neccessary libraries which are needed to run a test. In the following chapters, you will find step-by-step instructions for various CI/CD tools.
Github
You can find an example for an automated test with our testbox in our example project on Github: Tasterplatine. The description below will explain all steps for this example.
Setup Runner
First you have to install the action-runner on your PC. Open your Repository in your browser.
Click on Settings –> Actions –> Runners
Click on the top right Button New self-hostet runner.
Choose your operating system and Architecture and run all displayed commands on your PC.
With the given commands you start the runner manually. If you want to start your runner automatically on each boot, run:
On Linux:
sudo ./svc.sh installsudo ./svc.sh start
On Windows:
.\svc install.\svc start
If your setup runs correctly - your runner should be displayed in green with the state “Idle” on the Action-runner page on Github. For example:
Now your setup is ready to run automated tests!
In the next step you have to define your workflow.
Create Workflow
The easiest way to create a new Workflow is to open your repository on github in the webbrowser, klick on Actions and use the link set up a workflow yourself.
Copy & Paste the following configuration:
name: Build and Test
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Build STM32CubeIde project
uses: xanderhendriks/action-build-stm32cubeide@v11.0
with:
project-path: '.'
project-target: 'Testplatine'
env:
ENV_VERSION_MAJOR: 1
ENV_VERSION_MINOR: 0
ENV_VERSION_BUGFIX: 0
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-artifact
path: Debug/Testplatine.bin
remote-test:
needs: build
runs-on: [self-hosted, linux]
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: build-artifact
path: ./firmware
- name: Run Test
env:
test-project-folder: "Tests"
test-project-file: "project.etp"
run: |
docker pull emintes/testplattform:arm64
docker run --rm --name test-container --device=/dev --privileged \
-v "${{ github.workspace }}:/workspace/repo" \
-e TEST_PROJECT_FOLDER="${{ env.test-project-folder }}" \
-e TEST_PROJECT_FILE="${{ env.test-project-file }}" \
-e EXTRA_COMMANDS="${{ env.extra-commands }}" \
emintes/testplattform:arm64
- name: Upload Testreport artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: Testreport
path: Tests/Reports/Testreport.html
Description:
This workflow contains of two jobs: build and remote-test.
The build job runs on github hostet runner and consits of three steps:
Checkout code: to checkout your repository
Build STM32CubeIde project: compiles your code. In our example its code, written in STM32Cube IDE. So we are using the
xanderhendriks/action-build-stm32cubeideaction for compiling the code. This step must be adapted to your development environment.Upload build artifacts: This uploads the firmware-binary as an artifact.
The remote-test job runs on the self-hostet runner and consits of the following steps:
Checkout code: to checkout your repository
Download artifact: to download the previously built firmware-artifact.
Run Test: here the test gets executed in a docker container. For detailed description of all parameteres, see documentation on docker-hub
Upload Testreport artifact: when the test is finished, we upload the testreport as an artifact to github.
After a successfully run of this workflow, we get this result:
In the middle you see that the build job has passed successfully and the remote-test too.
On the bottom area you can now download the Testreport and the firmware-file of this run.
Azure DevOps
Setup Agent
Create an Agent Pool in Azure DevOps
Go to your project in Azure DevOps.
Click the gear icon (Project settings) in the top-right corner.
Select
Agent poolson the left.Click
Add pool→ give it a name (e.g., SelfHostedPool).Optional: Grant access permission to all pipelines aktivieren, damit der Pool ohne Extra-Rechte nutzbar ist.
Register a Self-Hosted Agent
Select your newly created agent pool.
Click on
New agent.Choose the operating system of the target machine (Windows, Linux, Mac).
Azure DevOps will show exact commands to download and register the agent.
When running
./config.sh(Linux) orconfig.cmd(Windows), you will be prompted for:Server URL: https://dev.azure.com/<org-name>
Authentication type: PAT (Personal Access Token)
Agent pool: Name of your pool (SelfHostedPool)
Agent name: Any name, e.g., build01
Create a Personal Access Token (PAT)
In Azure DevOps, click your profile picture in the top-right →
Personal access tokens.Click
New Token:Scope: at least Agent Pools (read, manage)
Organisation: select your organization.
Expiration date: set appropriately (not too short if you want it to run continuously)
Enter this token when prompted in config.sh or config.cmd.
Start Agent
run
./run.shon linux or.\run.cmdon Windows.
Autostart Agent
To start your agent automatically on each boot, run:
On Linux:
sudo ./svc.sh installsudo ./svc.sh start
On Windows:
.\svc install.\svc start
Create Pipeline
Go to your Azure DevOps project. In the left-hand menu, click Pipelines.
Then click on New pipeline (usually top-right).
Choose the repository containing your code.
You may need to authorize Azure DevOps if using GitHub or another external repo.
Configure your Pipeline
Use Starter pipeline - this will create a minimal YAML template to start with.
Here is an example for the Tasterplatine example project:
trigger:
- master
jobs:
- job: Build
displayName: 'build'
pool:
vmImage: 'ubuntu-latest' # Microsoft hostet Agent
container:
image: 'xanderhendriks/stm32cubeide:15.1'
steps:
- checkout: self
displayName: 'Checkout code'
- script: |
echo "Start Build for Testplatine..."
echo $(Build.SourcesDirectory)
cd $(Build.SourcesDirectory)
stm32cubeide --launcher.suppressErrors -nosplash -application org.eclipse.cdt.managedbuilder.core.headlessbuild -data /tmp/stm-workspace -importAll $(Build.SourcesDirectory)
headless-build.sh -data /tmp/stm-workspace -build "Testplatine/Debug"
displayName: 'Build STM32CubeIde project'
- script: ls $(Build.SourcesDirectory) -R
displayName: List files
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: '$(Build.SourcesDirectory)/Debug/Testplatine.bin'
artifactName: 'DebugBinary'
publishLocation: 'Container'
displayName: 'Upload build artifacts'
- job: remote_test
displayName: 'remote test'
dependsOn: Build # wait until build is finished
pool:
name: SelfHostedPool
steps:
- checkout: self
displayName: 'Checkout code'
- task: DownloadBuildArtifacts@0
inputs:
buildType: 'current'
downloadType: 'single'
artifactName: 'DebugBinary'
downloadPath: '$(Build.SourcesDirectory)/firmware' # Target folder
displayName: 'Download build artifact'
- script: |
docker pull emintes/testplattform:arm64
docker run --rm --name test-container --device=/dev --privileged \
-v "$(Build.SourcesDirectory):/workspace/repo" \
-e TEST_PROJECT_FOLDER="$test_project_folder" \
-e TEST_PROJECT_FILE="${{ env.test_project_file }}" \
-e EXTRA_COMMANDS="$extra_commands" \
emintes/testplattform:arm64
displayName: 'Run Test'
env:
test_project_folder: "Tests"
test_project_file: "project.etp"
extra_commands: ""
- task: PublishBuildArtifacts@1
condition: always()
inputs:
pathToPublish: 'Tests/Reports/Testreport.html'
artifactName: 'Testreport'
publishLocation: 'Container'
displayName: 'Upload Testreport artifact'
The Result of this Pipeline looks like this:
By clicking on the 2 published link you will see the artifacts of this run: