-
Notifications
You must be signed in to change notification settings - Fork 2
Firmware-CI testing #245
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
Open
AtomicFS
wants to merge
3
commits into
main
Choose a base branch
from
feat/add-fwci-testing
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Firmware-CI testing #245
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| ## Can be changed depending on the FWCI tester device used | ||
| {%- set RPI_HOSTNAME = "fwci-dutctl-tester" %} | ||
| {%- set RPI_FQDN = RPI_HOSTNAME ~ ".sec.9e.network" %} | ||
| ## Do not change values below, unless you know what you are doing | ||
| {%- set PKG_NAME = "dutctl" %} | ||
| {%- set DUTCTL_CONFIG_FILE = "/etc/dutctl.yaml" %} | ||
| {%- set SYSTEMD_FILE = "dutagent.service" %} | ||
| {%- set DUTAGENT_PORT = "2024" %} | ||
| {%- set DUTCTL_ARGS = '"-s", "' ~ RPI_HOSTNAME ~ ':' ~ DUTAGENT_PORT ~ '"' %} | ||
| {%- set DUTCTL_ARGS_STR = '-s ' ~ RPI_HOSTNAME ~ ':' ~ DUTAGENT_PORT %} | ||
| ## Values below should not change | ||
| {%- set GPIO_PIN_TEST_OLIMEX = "21" %} | ||
| {%- set FAKE_SERIAL_INPUT = "/home/oscar/ttyS1" %} | ||
| {%- set FAKE_SERIAL_OUTPUT = "/home/oscar/ttyS2" %} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| transport_oscar: &transport_oscar | ||
| proto: ssh | ||
| options: | ||
| host: "[[attributes.Host]]" | ||
| user: oscar | ||
| identity_file: "/root/.ssh/fwci" | ||
| # TODO: The ssh keys (identity_file) are hard-coded in the FWCI docker at the moment | ||
|
|
||
| transport_root: &transport_root | ||
| proto: ssh | ||
| options: | ||
| host: "[[attributes.Host]]" | ||
| user: root | ||
| identity_file: "/root/.ssh/fwci" | ||
| # TODO: The ssh keys (identity_file) are hard-coded in the FWCI docker at the moment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| post-stage: | ||
| # =========================================== | ||
| # Delete the files copied over for the test | ||
| # =========================================== | ||
| - cmd: shell | ||
| name: Stop remotelab-server systemd service | ||
| transport: *transport_root | ||
| parameters: | ||
| command: "systemctl stop {{ defaults.SYSTEMD_FILE }} || true" | ||
|
|
||
| - cmd: shell | ||
| name: Uninstall the package | ||
| transport: *transport_root | ||
| parameters: | ||
| command: "apt remove --assume-yes {{ defaults.PKG_NAME }} || true" | ||
|
|
||
| - cmd: shell | ||
| name: Delete testing configuration file | ||
| transport: *transport_root | ||
| parameters: | ||
| command: "rm {{ defaults.DUTCTL_CONFIG_FILE }} || true" | ||
|
|
||
| - cmd: shell | ||
| name: Delete package | ||
| transport: *transport_root | ||
| parameters: | ||
| command: "rm {{ defaults.PKG_NAME }}.deb || true" | ||
|
|
||
| - cmd: shell | ||
| name: Shutdown fake serial | ||
| transport: *transport_oscar | ||
| parameters: | ||
| command: "pkill socat || true" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| pre-stage: | ||
| # Fix permissions | ||
| - cmd: cmd | ||
| name: chmod dutctl | ||
| transport: | ||
| proto: local | ||
| parameters: | ||
| executable: chmod | ||
| args: ["755", "[[input.DUTCTL]]"] | ||
|
|
||
| # ======================== | ||
| # Copy files over to RPI | ||
| # ======================== | ||
| - cmd: copy | ||
| name: Copy over {{ defaults.PKG_NAME }} debian package | ||
| transport: *transport_root | ||
| parameters: | ||
| source: "[[input.REMOTE_PKG]]" | ||
| destination: "{{ defaults.PKG_NAME }}.deb" | ||
|
|
||
| - cmd: cmd | ||
| name: Install {{ defaults.PKG_NAME }} package | ||
| transport: *transport_root | ||
| parameters: | ||
| executable: dpkg | ||
| args: ["-i", "{{ defaults.PKG_NAME }}.deb"] | ||
|
|
||
| - cmd: copy | ||
| name: Copy over test config file | ||
| transport: *transport_root | ||
| parameters: | ||
| source: "[[input.CONFIG]]" | ||
| destination: {{ defaults.DUTCTL_CONFIG_FILE }} | ||
|
|
||
| - cmd: cmd | ||
| name: chmod config file | ||
| transport: *transport_root | ||
| parameters: | ||
| executable: chmod | ||
| args: ["644", {{ defaults.DUTCTL_CONFIG_FILE }}] | ||
|
|
||
| # ============== | ||
| # Start server | ||
| # ============== | ||
| - cmd: cmd | ||
| name: Reload systemctl daemon | ||
| transport: *transport_root | ||
| parameters: | ||
| executable: systemctl | ||
| args: ["daemon-reload"] | ||
|
|
||
| - cmd: cmd | ||
| name: Start systemd service | ||
| transport: *transport_root | ||
| parameters: | ||
| executable: systemctl | ||
| args: ["start", {{ defaults.SYSTEMD_FILE }}] | ||
|
|
||
| - cmd: shell | ||
| name: Status systemd service | ||
| transport: *transport_root | ||
| parameters: | ||
| command: "systemctl status --no-pager {{ defaults.SYSTEMD_FILE }}" | ||
| expect: | ||
| - regex: "Active: active \\(running\\)" | ||
|
|
||
| # ========================== | ||
| # Test dutctl help command | ||
| # ========================== | ||
| - cmd: cmd | ||
| name: dutctl help | ||
| transport: | ||
| proto: local | ||
| parameters: | ||
| executable: "[[input.DUTCTL]]" | ||
| args: ["--help"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| # FirmwareCI configuration for dutctl testing | ||
|
|
||
| This directory contains FirmwareCI configurations and tests. | ||
|
|
||
| For detailed information on FirmwareCI, please refer to the [official documentation](https://docs.firmware-ci.com/). | ||
|
|
||
|
|
||
| ## Requirements | ||
|
|
||
| - Parametric and re-usable testing | ||
| - Easy to expand | ||
| - Reliable | ||
| - Can be used in CI/CD to verify each pull request | ||
|
|
||
|
|
||
| ## Design decisions | ||
|
|
||
| ### Jinja templating | ||
| We want to test multiple features (flashing, power control, serial, etc). And to keep everything nicely organised we need to have each feature-specific test as it's own test. | ||
|
|
||
| However, the setup and tear-down of the tests is rather complex: | ||
| - copy over the compiled binaries | ||
| - copy over configuration files | ||
| - spin up the server (agent) | ||
| - execute the test | ||
| - shut-down the server | ||
| - delete the copied binaries | ||
| - delete configuration files | ||
|
|
||
| In case of the serial feature, it also means spinning-up "fake" / "dummy" serial that can be used for the testing. | ||
|
|
||
| It would be stupid to copy-paste all this setup into each test file, especially because keeping all of them in sync would be a nightmare. | ||
|
|
||
| For this reason I have decided to use [jinja2 templates](https://jinja.palletsprojects.com/en/stable/api/) to automate this menial and error-prone work. To make it even simpler, I have also included [Taskfile](https://taskfile.dev/docs/guide) which has already all the jobs written there, so to generate all of the templates is as easy as simply calling `task jinja2:templates`. | ||
|
|
||
| Thanks to jinja templating, and how the tests are structured, tests are parametric and easy to expand. | ||
|
|
||
|
|
||
| ### Debian packaging magic | ||
| As you might notice, instead of simply copying over the compiled binaries (`dutctl` / `dutagent` / ...) we use Debian packages. | ||
|
|
||
| The biggest motivator here to do this was to accommodate for setup and tear-down, and the differences between tested versions (future-proofing). This way, we leverage the power of package manager to make sure that the cleanup (uninstalling) of old file is complete and that no files are left behind! This makes sure that the environment is always pristine. | ||
|
|
||
| Another huge advantage is, that with this approach, that run-time dependencies are also handled by package manager. Because of this, the test hardware (Raspberry Pi) has minimal (if any) setup required for use in the FWCI tests. Just install package, test and uninstall! Easy! | ||
|
|
||
|
|
||
| ## Project structure | ||
|
|
||
| The most important files / directories are: | ||
| - `.firmwareci/Taskfile.yml` | ||
| - `.firmwareci/.jinja2_templates/` | ||
| - `.firmwareci/workflows/` | ||
|
|
||
| ### Taskfile | ||
| The `.firmwareci/Taskfile.yml` is there to help and automate some mundane and repetitive jobs. | ||
|
|
||
| Contains task `jinja2:templates` which finds all jinja tempaltes in `.firmwareci/workflows/` and `.firmwareci/duts/` and runs a tempalting engine on them. | ||
|
|
||
| The list of the templates is created dynamically with the shell command: | ||
| ```bash | ||
| find './workflows/' './duts/' -type f -name '*.yaml.j2' | ||
| ``` | ||
|
|
||
| This list is then iterated over in a for-loop, such as that it takes `./duts/dut-rpi-fti-tester/dut.yaml.j2` as input, and produces `./duts/dut-rpi-fti-tester/dut.yaml`. | ||
|
|
||
|
|
||
| ### jinja2_templates | ||
| The `.firmwareci/.jinja2_templates` contains the "common" building-blocks that are shared across templates. The `defaults.j2` and `defaults.yaml` are for storing some basics (they are intentionally separate): | ||
| - `defaults.j2` | ||
| - this is pure jinja2 syntax, and is imported into template with | ||
| ```j2 | ||
| {%- import ".jinja2_templates/defaults.j2" as defaults %} | ||
| ``` | ||
| - import means that the variables will become accessible, and can then be accessed in the template with: | ||
| ```j2 | ||
| {{ defaults.DUTCTL_ARGS }} | ||
| ``` | ||
| - `defaults.yaml` | ||
| - this is pure YAML file to be `include`d into a template with | ||
| ```j2 | ||
| {% include ".jinja2_templates/defaults.yaml" with context %} | ||
| ``` | ||
| - essentially this is to just simply render the content of the file, ignoring any variable assignments or macros within it | ||
| - technically speaking it could be renamed to `defaults.yaml.j2`, but it does not contain any jinja2 code and renaming it would have no effect | ||
| - `pre.yaml.j2` and `post.yaml.j2` | ||
| - for pre-stage and post-stage respectively | ||
| - they are copy-pasted into each test (they are `include`d in tests, meaning that their content will be rendered) | ||
|
|
||
|
|
||
| ### workflows | ||
| The `workflows` directory is where the tests live. | ||
|
|
||
| ### Systemd service | ||
| The `dutagent.service` file is a systemd service file to start a dutagent on dutworker. | ||
|
|
||
| At the moment it is only used for firmware-ci testing. | ||
|
|
||
|
|
||
| ## Adding completely new test | ||
| To add a completely new tests from scratch, create a new `.yaml.j2` file in `.firmwareci/workflows/workflow-rpi-dutctl-tester/`. I would recommend to copy-paste some existing test (for example the `dummy-modules.yaml.j2` is rather simple) and use it as basis. | ||
|
|
||
| Then update the test according to your needs. | ||
|
|
||
| Run `task fwci:jinja2:templates` and it will automatically generate a complete tests. That is it. It is as simple as that. | ||
|
|
||
| Next, I recommend to run `fwci fwci:validate`. | ||
|
|
||
| As the last step, add all new files (even those jinja2 generated) into git commit. This is because FirmwareCI cannot pre-process the tests on it's own, which is why we have to include even the "generated code". |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| --- | ||
| version: "3" | ||
|
|
||
| tasks: | ||
| jinja2:templates: | ||
| desc: Run jinja2 on template files | ||
| cmds: | ||
| - task: jinja2:find-and-process-all-tempaltes | ||
|
|
||
| fwci:validate: | ||
| desc: Validate FWCI files | ||
| cmds: | ||
| - fwci validate | ||
|
|
||
| #================ | ||
| # Internal tasks | ||
| #================ | ||
|
|
||
| jinja2:find-and-process-all-tempaltes: | ||
| desc: Run jinja2 on jinja2 templates | ||
| internal: true | ||
| label: 'jinja2-tests-{{.REPO}}' | ||
| vars: | ||
| WORKFLOWS: | ||
| sh: find './workflows/' './duts/' -type f -name '*.yaml.j2' | ||
| sources: | ||
| - .jinja2_templates/* | ||
| - duts/**/*.yaml.j2 | ||
| - workflows/workflow-*/defaults.j2 | ||
| - workflows/workflow-*/**/*.yaml.j2 | ||
| cmds: | ||
| - for: | ||
| var: WORKFLOWS | ||
| task: jinja2:run-on-file | ||
| vars: | ||
| INPUTFILE: | ||
| sh: echo "{{.ITEM}}" | ||
| OUTPUTFILE: | ||
| sh: echo "{{.ITEM}}" | sed -E 's/\.j2$//g' | ||
|
|
||
| jinja2:run-on-file: | ||
| desc: Run jinja2 on a file | ||
| internal: true | ||
| cmds: | ||
| - pwd | ||
| - echo 'INPUTFILE = {{.INPUTFILE}}' | ||
| - echo 'OUTPUTFILE = {{.OUTPUTFILE}}' | ||
| - j2 --format env -o '{{.OUTPUTFILE}}' '{{.INPUTFILE}}' | ||
| requires: | ||
| vars: ["INPUTFILE", "OUTPUTFILE"] |
|
jenstopp marked this conversation as resolved.
AtomicFS marked this conversation as resolved.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| [Unit] | ||
| Description=dutagent to run on SBC attached to a devices under test | ||
| Documentation=https://github.com/BlindspotSoftware/dutctl | ||
| Wants=network-online.target | ||
| After=network-online.target | ||
| StartLimitInterval=15 | ||
| StartLimitBurst=3 | ||
|
|
||
| [Service] | ||
| Restart=always | ||
| RestartSec=3s | ||
| ExecStart=/usr/bin/dutagent -a 0.0.0.0:2024 -c /etc/dutctl.yaml | ||
|
|
||
| [Install] | ||
| WantedBy=multi-user.target |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
|
AtomicFS marked this conversation as resolved.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| --- | ||
| # Device-under-Test Configuration for RaspberryPi acting as dutctl tester | ||
| {%- import ".jinja2_templates/defaults.j2" as defaults %} | ||
| name: {{ defaults.RPI_HOSTNAME }} | ||
| label: {{ defaults.RPI_HOSTNAME }} | ||
| attributes: | ||
| Host: "{{ defaults.RPI_FQDN }}" |
Empty file.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.