Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/irnas zephyr template migration #14

Merged
merged 2 commits into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ on:
push:
branches:
- "main"
workflow_dispatch:

env:
GIT_CREDENTIALS: ${{ secrets.GIT_CREDENTIALS }}

jobs:
build:
runs-on: ubuntu-20.04
runs-on: self-hosted
defaults:
run:
shell: bash
Expand Down Expand Up @@ -57,6 +58,7 @@ jobs:
git config --global credential.helper '!f() { printf "%s\n" "username=runner" "password=$GIT_CREDENTIALS"; };f'

- name: Install and cache apt packages
if: contains(runner.name, 'Github Action')
uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: gcc-multilib
Expand All @@ -65,6 +67,7 @@ jobs:
version: 1.0

- name: Retrieve cache
if: contains(runner.name, 'Github Action')
uses: actions/cache@v3
env:
cache-name: cache-modules
Expand Down Expand Up @@ -125,3 +128,9 @@ jobs:
with:
name: artefacts
path: project/artefacts/*

- name: Post-build clean
# Only for self hosted runners
# Makes sure east init does not fail in the project setup
if: ${{ always() && !contains(runner.name, 'Github Action') }}
run: rm -rf ${{ github.workspace }}/.west
13 changes: 11 additions & 2 deletions .github/workflows/codechecker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ env:

jobs:
codechecker:
runs-on: ubuntu-20.04
runs-on: self-hosted
defaults:
run:
shell: bash
Expand Down Expand Up @@ -57,20 +57,22 @@ jobs:
# This is needed due to the later east update (west update) command that
# could be cloning from the private repos. The provided token in
# GIT_CREDENTIALS needs to be a fine-grained token, with access to all
# repositores, with "Read-only" access level to the Content repository
# repositories, with "Read-only" access level to the Content repository
# permissions.
- name: Set Git credentials
run: |
git config --global credential.helper '!f() { printf "%s\n" "username=runner" "password=$GIT_CREDENTIALS"; };f'

- name: Add LLVM repositories
if: contains(runner.name, 'Github Action')
run: |
# If updating llvm version do not forget to update distro name
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc
sudo add-apt-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-16 main"
sudo apt-get update

- name: Install and cache apt packages
if: contains(runner.name, 'Github Action')
uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: clang-16 clang-tidy-16 cppcheck gcc-multilib
Expand All @@ -79,6 +81,7 @@ jobs:
version: 3.0

- name: Retrieve cache
if: contains(runner.name, 'Github Action')
uses: actions/cache@v3
env:
cache-name: cache-modules
Expand Down Expand Up @@ -146,3 +149,9 @@ jobs:
with:
name: codechecker-diffs
path: project/codechecker-diffs/*

- name: Post-build clean
# Only for self hosted runners
# Makes sure east init does not fail in the project setup
if: ${{ always() && !contains(runner.name, 'Github Action') }}
run: rm -rf ${{ github.workspace }}/.west
1 change: 0 additions & 1 deletion .github/workflows/publish-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ on:
jobs:
publish-new-release:
runs-on: ubuntu-20.04
# runs-on: self-hosted

steps:
- name: Start
Expand Down
34 changes: 27 additions & 7 deletions .github/workflows/twister.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ on:
pull_request:
types: [opened, reopened, synchronize]

workflow_dispatch:

env:
GIT_CREDENTIALS: ${{ secrets.GIT_CREDENTIALS }}

jobs:
twister-build:
name: "Run Unit Tests"
# This version is a must, twister otherwise fails (some Python library
# depends on a specific version of libffi that is not present in the
# toolchain provided by nordic's toolchain manager).
runs-on: ubuntu-20.04
runs-on: self-hosted
defaults:
run:
shell: bash
Expand All @@ -38,6 +37,7 @@ jobs:
git config --global credential.helper '!f() { printf "%s\n" "username=runner" "password=$GIT_CREDENTIALS"; };f'

- name: Install and cache apt packages
if: contains(runner.name, 'Github Action')
uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: gcc-multilib lcov
Expand All @@ -46,6 +46,7 @@ jobs:
version: 2.0

- name: Retrieve cache
if: contains(runner.name, 'Github Action')
uses: actions/cache@v3
env:
cache-name: cache-modules
Expand Down Expand Up @@ -115,11 +116,24 @@ jobs:
path: |
project/twister-out/coverage.info

- name: Post-build clean
# Only for self hosted runners
# Makes sure east init does not fail in the project setup
if: ${{ always() && !contains(runner.name, 'Github Action') }}
run: rm -rf ${{ github.workspace }}/.west

twister-test-results:
name: "Publish Unit Tests Results"
# WARNING: This step is incompatible with self-hosted runners as it uses the 'publish-unit-test-result' action.
# This would require us to run docker-in-docker in the self-hosted runner.

runs-on: ubuntu-22.04
permissions:
contents: read
issues: read
checks: write
needs: twister-build
if: always()
runs-on: ubuntu-20.04

steps:
- name: Download Artefacts
Expand All @@ -137,8 +151,14 @@ jobs:

coverage-report:
name: "Publish Coverage Report"
# NOTE: This action is not compatible with "workflow_dispatch" event, so
# it's not possible to run it manually.
runs-on: self-hosted
permissions:
issues: write
pull-requests: write
needs: twister-build
runs-on: ubuntu-20.04
if: ${{ github.event_name == 'push' || github.event_name == 'pull_request' }}

steps:
- name: Download Artefacts
Expand All @@ -150,4 +170,4 @@ jobs:
- name: Publish Coverage Report
uses: romeovs/lcov-reporter-action@4cf015aa4afa87b78238301f1e3dc140ea0e1ec6
with:
lcov-file: ./coverage-report/coverage.info
lcov-file: ./coverage-report/coverage.info
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ of CI workflows for release automation.
charge for this** to do it for you.
- [ ] Create a new project on the CodeChecker server. You can also **contact
person in charge** to do it for you.
- [ ] (Optional) Include the `twister-rpi.yaml` GitHub Actions workflow for the on-target testing. Copy it from the `irnas-workflows-software/workflow-templates/rpi-twister-hil/.github/twister-rpi.yaml`. See the [README.md](scripts/rpi-jlink-server/README.md) for more information on the requirements and setup.
- [ ] As a final step delete this checklist and commit changes.

[repository naming scheme]:
Expand Down
5 changes: 5 additions & 0 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ pre-package:
test:
east twister -T tests --coverage -p native_posix

# Used to run twister on remote RPi with attached nRF52840DK
# The {RPI_IP} variable must be set in the environment using Github Secrets
test-remote:
east twister -T tests -p nrf52840dk_nrf52840 --device-testing --device-serial-pty="scripts/rpi-jlink-server/twister_pty.py --host ${RPI_IP} --port 7777" --west-runner=jlink --west-flash="--tool-opt=ip ${RPI_IP}:7778"

test-report-ci:
junit2html twister-out/twister.xml twister-out/twister-report.html

Expand Down
33 changes: 33 additions & 0 deletions scripts/rpi-jlink-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Raspberry Pi J-Link Server

This directory contains two scripts that are used to run tests on a remote Raspberry Pi, which is connected to a J-Link debugger:

- The `request_resource.sh` script, which should be used inside a GitHub Action Workflow before and after running tests on the device.
- The `twister_pty.py` script, which is used with the `west/east twister` command. This script receives and prints the outputs generated by the device.

## Remote Raspberry Pi

Documentation on how to set up the Raspberry Pi and a detailed explanation of the functionality can be found [here](https://github.com/IRNAS/irnas-runners-software/blob/main/rpi-jlink-server/README.md).

## GitHub Actions Workflow

The scripts mentioned are used by the `twister-rpi.yaml` GitHub Actions Workflow.
The workflow is not included in this repository, as it is opt-in. To include it, you must copy the `twister-rpi.yaml` from the [linked repository](https://github.com/IRNAS/irnas-workflows-software/blob/main/workflow-templates/rpi-twister-hil/.github/twister-rpi.yaml) into `.github/workflows` folder inside your repository and add the following GitHub secrets:

- RPI_IP - IP address of the Raspberry Pi running the JLinkRemoteServer.

The IP can be the local IP address of the Raspberry Pi, if the GitHub Action runner is running on the same network. Or it has to be the VPN IP address of the Raspberry Pi, if the GitHub Action runner is running on a different network.

The following make command has been added to the projects `makefile`:

```bash
test-remote:
east twister -T tests -p nrf52840dk_nrf52840 --device-testing --device-serial-pty="scripts/twister_pty.py --host ${RPI_IP} --port 7777" --west-runner=jlink --west-flash="--tool-opt=ip ${RPI_IP}:7778"
```

The command is used to run twister tests on the remote device. The `--device-serial-pty` and `--west-flash` options are used to connect to the remote device. The `twister_pty.py` script is used to print the output of the device to the GitHub Actions log. The `--west-runner` and `--west-flash` options are used to flash the device with the firmware and run the tests.

**IMPORTANT: The `testcase.yaml` has been modified as well to include the `- CONFIG_NULL_POINTER_EXCEPTION_DETECTION_NONE=y` `extra_configs` option.**

This flag fixes the tests taking a minute longer, due to a timeout. [This related issue](https://github.com/zephyrproject-rtos/zephyr/issues/39216) describes the problem.

40 changes: 40 additions & 0 deletions scripts/rpi-jlink-server/request_resource.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/bash
# This scripts send a HTTP POST request to the specified URL and checks if the response code is 200.
# The URL endpoint is a server running on the Raspberry Pi that is connected to the J-Link debugger.
# The script is called from the ``

# Check if the required arguments are provided
if [ "$#" -ne 3 ]; then
echo "Usage: $0 <timeout_seconds> <interval_seconds> <request_url>"
exit 1
fi

timeout="$1"
interval="$2"
request_url="$3"
start_time=$(date +%s) # Converts the date into unix timestamp

echo $start_time

while true; do
# Send a POST request to the request_url and capture the HTTP response code
response_code=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$request_url")

# Check if the response code is 200
if [ "$response_code" -eq 200 ]; then
echo "Request to $request_url succeeded with status code 200."
exit 0
fi

current_time=$(date +%s)
elapsed_time=$((current_time - start_time))

# Check if the timeout is reached
if [ "$elapsed_time" -ge "$timeout" ]; then
echo "Timeout reached. Request to $request_url failed with status code $response_code."
exit 1
fi

echo "Request to $request_url failed with status code $response_code. Retrying in $interval seconds..."
sleep "$interval"
done
36 changes: 36 additions & 0 deletions scripts/rpi-jlink-server/twister_pty.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env python3
# A script used by twister to run the pseudoterminal
# The script opens a telnet connection to the specified IP and PORT and prints the output to the terminal

import argparse
import telnetlib

parser = argparse.ArgumentParser(description="Read telnet output")
parser.add_argument("--host", help="Host to connect to")
parser.add_argument("--port", help="Port to connect to")
args = parser.parse_args()

HOST = args.host
PORT = args.port

def read_telnet_output():

try:
with telnetlib.Telnet(HOST, PORT) as tn:
while True:
line = tn.read_until(b'PROJECT EXECUTION SUCCESSFUL')
print(line.decode("utf-8"))
if b'PROJECT EXECUTION SUCCESSFUL'in line:
print(f"Tests finished running. Exiting!")
return 0

except Exception as e:
print(f"An exception occurred when reading telnet output: {e}")


# Run the event loop and call the function to start reading the telnet output
if __name__ == "__main__":
if not HOST or not PORT:
print("Please specify a host and port")
exit()
read_telnet_output()
3 changes: 2 additions & 1 deletion tests/sample_test/testcase.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
tests:
tests.sample_test:
# Set of platforms that this test case can be run on.
platform_allow: native_posix nrf52dk_nrf52832
platform_allow: native_posix nrf52dk_nrf52832 nrf52840dk_nrf52840
harness: ztest
# Only build the test, do not run it
# build_only: True
extra_configs:
# Disable fancy test, otherwise stdout parsing does not work.
- CONFIG_FANCY_ZTEST=n
- CONFIG_NULL_POINTER_EXCEPTION_DETECTION_NONE=y
Loading