Skip to content

Commit

Permalink
Merge pull request #24 from rlcheng/workflow-2612
Browse files Browse the repository at this point in the history
Workflow 2612
  • Loading branch information
LeStarch authored Nov 1, 2024
2 parents e1abea5 + 363f263 commit c3b53ff
Show file tree
Hide file tree
Showing 4 changed files with 247 additions and 31 deletions.
79 changes: 79 additions & 0 deletions .github/workflows/baremetal_ci_teensy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: baremetal-ci-actions
run-name: ${{ github.actor }} running Baremetal CI actions
on: [push]

env:
run_job_select: "fsw-gds"
build_binary: ${{ github.workspace }}/build-artifacts/teensy41/BaremetalReference/bin/BaremetalReference.hex
gds_args: --comm-adapter uart --uart-device /dev/ttyACM0
dict_path: ${{ github.workspace }}/build-artifacts/teensy41/BaremetalReference/dict/BaremetalReferenceTopologyAppDictionary.xml
test_path: BaremetalReference/test/int/baremetal_ref_integration_test.py
new_build_binary: ${{ github.workspace }}/build-artifacts/teensy41/BaremetalReference/bin/build_binary
new_dict_path: ${{ github.workspace }}/build-artifacts/teensy41/BaremetalReference/dict/dictionary.xml

jobs:

build:
runs-on: ubuntu-latest
outputs:
run_job_select: ${{ env.run_job_select }}
start_cmd: /home/odroid/teensy_loader_cli/teensy_loader_cli --mcu=TEENSY41 -v -s ./build_binary
gds_args: ${{ env.gds_args }}
test_path: ${{ env.test_path }}
steps:
- uses: actions/checkout@v4
- name: "Checkout F' Repository"
uses: actions/checkout@v4
with:
submodules: true
path: ${{ inputs.fprime_location }}
- name: "Fprime Venv and Requirements Install"
run: |
python3 -m venv ./fprime-venv
. ./fprime-venv/bin/activate
pip3 install -r ${{ inputs.fprime_location }}./fprime/requirements.txt
- name: "Platform Specific Requirements Install"
run: |
mkdir -p ~/.local/bin
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR=~/.local/bin sh
cd ~/.local/bin
git clone https://github.com/SterlingPeet/arduino-cli-cmake-wrapper.git
cd arduino-cli-cmake-wrapper
git checkout update/refactor
pip3 install .
export PATH=~/.local/bin:$PATH
cd ${{ github.workspace }}
arduino-cli config init
arduino-cli config add board_manager.additional_urls https://www.pjrc.com/teensy/package_teensy_index.json
arduino-cli core update-index
arduino-cli core install teensy:avr
- name: "Build"
run: |
. ./fprime-venv/bin/activate
fprime-util generate
fprime-util build
- name: "Rename build files"
run: |
mv ${{ env.build_binary }} ${{ env.new_build_binary }}
mv ${{ env.dict_path}} ${{ env.new_dict_path}}
- name: "Upload build binary"
uses: actions/upload-artifact@v4
with:
name: build_binary
path: ${{ env.new_build_binary }}
- name: "Upload dictionary"
uses: actions/upload-artifact@v4
with:
name: dictionary.xml
path: ${{ env.new_dict_path }}
- run: echo "Expose env vars for reusable workflow."

fit:
needs: build
uses: ./.github/workflows/reusable_fit_ci.yml
with:
test_path: ${{ needs.build.outputs.test_path }}
runs_on: self-hosted
run_job_select: ${{ needs.build.outputs.run_job_select }}
start_cmd: ${{ needs.build.outputs.start_cmd }}
gds_args: ${{ needs.build.outputs.gds_args }}
129 changes: 129 additions & 0 deletions .github/workflows/reusable_fit_ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
name: resuable-fit

on:
workflow_call:
inputs:
test_path:
required: true
type: string
runs_on:
required: false
type: string
default: "ubuntu-latest"
run_job_select:
required: false
type: string
default: "non-embedded"
start_cmd:
required: false
type: string
default: "fprime-gds"
gds_args:
required: false
type: string
default: ""

jobs:
# Setup job will run first by creating the virtual environment and then downloading the
# FSW binary and dictionary created in the build job step of the caller workflow to this
# workflow. After that the following run jobs are on a switch, only one will run based
# on run_job_select string. Each run job has a different method of starting FSW, FIT is
# run at the end of each job. If adding a new run job make sure it does not collide with
# an existing job. After one of these jobs is run, the upload FIT artifact job will then
# run.
#
# / run-non-embedded \
# setup --->| run-fsw-gds |---> upload-fit-artifacts
# \ run-gds-fsw /

setup:
runs-on: ${{ inputs.runs_on }}
steps:
- uses: actions/checkout@v4
- name: "Checkout F' Repository"
uses: actions/checkout@v4
with:
submodules: true
path: ${{ inputs.fprime_location }}
- name: "Install and activate Virtual Environment"
run: |
python3 -m venv ./fprime-venv
. ./fprime-venv/bin/activate
pip3 install -U setuptools wheel pip
pip3 install -r ${{ inputs.fprime_location }}./fprime/requirements.txt
- name: "Download FSW Binary"
uses: actions/download-artifact@v4
with:
name: build_binary
- name: "Download Dictionary"
uses: actions/download-artifact@v4
with:
name: dictionary.xml

run-non-embedded:
if: ${{ inputs.run_job_select == 'non-embedded' }}
runs-on: ${{ inputs.runs_on }}
needs: setup
steps:
- name: "Start FSW and GDS"
run: |
. ./fprime-venv/bin/activate
${{ inputs.start_cmd }}
- name: "Run Integration tests"
run: |
. ./fprime-venv/bin/activate
sleep 12
pytest ${{ inputs.test_path }} --dictionary ./dictionary.xml -rP
run-fsw-gds:
if: ${{ inputs.run_job_select == 'fsw-gds' }}
needs: setup
runs-on: ${{ inputs.runs_on }}
steps:
- name: "Start FSW"
run: ${{ inputs.start_cmd }}
- name: "Start GDS"
run: |
. ./fprime-venv/bin/activate
fprime-gds -n --dictionary ./dictionary.xml --gui none ${{ inputs.gds_args }} &
sleep 12
- name: "Run Integration tests"
run: |
. ./fprime-venv/bin/activate
pytest ${{ inputs.test_path }} -rP --dictionary ./dictionary.xml --logs ./
run-gds-fsw:
if: ${{ inputs.run_job_select == 'gds-fsw' }}
needs: setup
runs-on: ${{ inputs.runs_on }}
steps:
- name: "Start GDS"
run: |
. ./fprime-venv/bin/activate
fprime-gds -n --dictionary ./dictionary.xml --gui none ${{ inputs.gds_args }} &
- name: "Start FSW"
run: |
${{ inputs.start_cmd }}
sleep 12
- name: "Run Integration tests"
run: |
. ./fprime-venv/bin/activate
pytest ${{ inputs.test_path }} --dictionary ./dictionary.xml -rP
upload-fit-artifact:
runs-on: ${{ inputs.runs_on }}
if: ${{ always() }} #as long as one of the above jobs run, this job will run
needs: [run-non-embedded, run-fsw-gds, run-gds-fsw]
steps:
- name: "Upload Integration Test Results"
#Navigate into newest directory, which is for test logs.
#Rename test log because it contains date time and time is separated by colons that upload-artifact cannot handle.
#Store full path to test log xlsx in a variable for upload-artifact to use.
run: |
cd "$(ls -td -- */ | head -n 1)"
mv TestLog*.xlsx TestLog.xlsx
echo "TEST_LOG_PATH=$(realpath -s *.xlsx)" >> $GITHUB_ENV
- uses: actions/upload-artifact@v4
with:
name: TestLog
path: ${{ env.TEST_LOG_PATH }}
62 changes: 31 additions & 31 deletions BaremetalReference/test/int/baremetal_ref_integration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ def test_send_command(fprime_test_api):
Tests command send, dispatch, and receipt using a pair of NO_OP commands.
"""
result = fprime_test_api.send_command('cmdDisp.CMD_NO_OP')
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 3)
result = fprime_test_api.assert_event('OpCodeCompleted')
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 5)
result = fprime_test_api.assert_event('OpCodeCompleted', timeout = 5)
time.sleep(3)
result = fprime_test_api.send_and_assert_command("cmdDisp.CMD_NO_OP", max_delay=10.0)
#Note: send_and_assert_command has issues finding both displatched and completed EVRs. It can only find them if you
Expand All @@ -30,8 +30,8 @@ def test_send_command_with_args(fprime_test_api):
Test command send, dispatch, and receipt using a pair of NO_OP_STRING commands.
"""
result = fprime_test_api.send_command('cmdDisp.CMD_NO_OP_STRING', ['hello'])
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 3)
result = fprime_test_api.assert_event('OpCodeCompleted')
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 5)
result = fprime_test_api.assert_event('OpCodeCompleted', timeout = 5)
time.sleep(3)
result = fprime_test_api.send_and_assert_command('cmdDisp.CMD_NO_OP_STRING', ['hola'], max_delay=10.0)

Expand Down Expand Up @@ -65,28 +65,28 @@ def test_event_filter(fprime_test_api):
4. Re-enable activity hi evrs and send BLINKING_ON_OFF back to on, verify evr is no longer filtered.
"""
result = fprime_test_api.send_command('blinker.BLINKING_ON_OFF', ['ON'])
result = fprime_test_api.assert_event('SetBlinkingState', timeout = 3)
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 3)
result = fprime_test_api.assert_event('OpCodeCompleted')
result = fprime_test_api.assert_event('SetBlinkingState', timeout = 5)
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 5)
result = fprime_test_api.assert_event('OpCodeCompleted', timeout = 5)
time.sleep(3)
result = fprime_test_api.send_command('eventLogger.SET_EVENT_FILTER', ['ACTIVITY_HI', 'DISABLED'])
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 3)
result = fprime_test_api.assert_event('OpCodeCompleted')
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 5)
result = fprime_test_api.assert_event('OpCodeCompleted', timeout = 5)
time.sleep(3)
result = fprime_test_api.send_command('blinker.BLINKING_ON_OFF', ['OFF'])
result = fprime_test_api.await_event_count(0, 'SetBlinkingState')
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 3)
result = fprime_test_api.assert_event('OpCodeCompleted')
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 5)
result = fprime_test_api.assert_event('OpCodeCompleted', timeout = 5)
time.sleep(3)
#tear down steps. set EVR back to enable and LED back to on.
result = fprime_test_api.send_command('eventLogger.SET_EVENT_FILTER', ['ACTIVITY_HI', 'ENABLED'])
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 3)
result = fprime_test_api.assert_event('OpCodeCompleted')
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 5)
result = fprime_test_api.assert_event('OpCodeCompleted', timeout = 5)
time.sleep(3)
result = fprime_test_api.send_command('blinker.BLINKING_ON_OFF', ['ON'])
result = fprime_test_api.await_event_count(1, 'SetBlinkingState')
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 3)
result = fprime_test_api.assert_event('OpCodeCompleted')
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 5)
result = fprime_test_api.assert_event('OpCodeCompleted', timeout = 5)

def test_id_filter(fprime_test_api):
"""Test that event can be filtered by ID.
Expand All @@ -99,31 +99,31 @@ def test_id_filter(fprime_test_api):
5. Remove SetBlinkState EVR from the filter list and send BLINKING_ON_OFF back to on.
"""
result = fprime_test_api.send_command('blinker.BLINKING_ON_OFF', ['ON'])
result = fprime_test_api.assert_event('SetBlinkingState', timeout = 3)
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 3)
result = fprime_test_api.assert_event('OpCodeCompleted')
result = fprime_test_api.assert_event('SetBlinkingState', timeout = 5)
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 5)
result = fprime_test_api.assert_event('OpCodeCompleted', timeout = 5)
time.sleep(3)
result = fprime_test_api.send_command('eventLogger.SET_ID_FILTER', ['0x10001', 'ENABLED'])
result = fprime_test_api.assert_event('eventLogger.ID_FILTER_ENABLED', timeout = 3)
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 3)
result = fprime_test_api.assert_event('OpCodeCompleted')
result = fprime_test_api.assert_event('eventLogger.ID_FILTER_ENABLED', timeout = 5)
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 5)
result = fprime_test_api.assert_event('OpCodeCompleted', timeout = 5)
time.sleep(3)
result = fprime_test_api.send_command('blinker.BLINKING_ON_OFF', ['ON'])
result = fprime_test_api.await_event_count(0, 'SetBlinkingState')
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 3)
result = fprime_test_api.assert_event('OpCodeCompleted')
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 5)
result = fprime_test_api.assert_event('OpCodeCompleted', timeout = 5)
time.sleep(3)
result = fprime_test_api.send_command('eventLogger.SET_ID_FILTER', ['0x10001', 'DISABLED'])
result = fprime_test_api.assert_event('eventLogger.ID_FILTER_REMOVED', timeout = 3)
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 3)
result = fprime_test_api.assert_event('OpCodeCompleted')
result = fprime_test_api.assert_event('eventLogger.ID_FILTER_REMOVED', timeout = 5)
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 5)
result = fprime_test_api.assert_event('OpCodeCompleted', timeout = 5)
time.sleep(3)
result = fprime_test_api.send_command('eventLogger.SET_ID_FILTER', ['0x100', 'DISABLED'])
result = fprime_test_api.assert_event('eventLogger.ID_FILTER_NOT_FOUND', timeout = 3)
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 3)
result = fprime_test_api.assert_event('OpCodeError')
result = fprime_test_api.assert_event('eventLogger.ID_FILTER_NOT_FOUND', timeout = 5)
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 5)
result = fprime_test_api.assert_event('OpCodeError', timeout = 5)
time.sleep(3)
result = fprime_test_api.send_command('blinker.BLINKING_ON_OFF', ['ON'])
result = fprime_test_api.await_event_count(1, 'SetBlinkingState')
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 3)
result = fprime_test_api.assert_event('OpCodeCompleted')
result = fprime_test_api.assert_event('OpCodeDispatched', timeout = 5)
result = fprime_test_api.assert_event('OpCodeCompleted', timeout = 5)
8 changes: 8 additions & 0 deletions docs/run-baremetal-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ Note: It has to be the full path to the BaremetalReference.hex file for arduino-

4. While programming the red led will be brighter and then flash. Once done the board will get out of HalfKay bootloader mode (red led off) and run the BaremetalReference application. You should now see an orange flashing led by the button.

### Alternate option for hex file upload
Instead of using arduino-cli, you can also use teensy_loader_cli. This alternative is best if you are running on a headless machine / SBC and using SSH. teensy_loader_cli requires compiling on the host machine but usage is simpler.

1. After building the hex file, simply call:
```
teensy_loader_cli --mcu=TEENSY41 -v -s /full_path/fprime-baremetal-reference/build-artifacts/teensy41/BaremetalReference/bin/BaremetalReference.hex
```

## Using GDS via serial
1. Find the serial port, this varies by your host system but it should show up as a `/dev/tty*` device. On the mac, it's /dev/tty.usbmodem*(9 digit number).
2. Launch GDS:
Expand Down

0 comments on commit c3b53ff

Please sign in to comment.