|
| 1 | +# FirmwareCI configuration for dutctl testing |
| 2 | + |
| 3 | +This directory contains FirmwareCI configurations and tests. |
| 4 | + |
| 5 | +For detailed information on FirmwareCI, please refer to the [official documentation](https://docs.firmware-ci.com/). |
| 6 | + |
| 7 | + |
| 8 | +## Requirements |
| 9 | + |
| 10 | +- Parametric and re-usable testing |
| 11 | +- Easy to expand |
| 12 | +- Reliable |
| 13 | +- Can be used in CI/CD to verify each pull request |
| 14 | + |
| 15 | + |
| 16 | +## Design decisions |
| 17 | + |
| 18 | +### Jinja templating |
| 19 | +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. |
| 20 | + |
| 21 | +However, the setup and tear-down of the tests is rather complex: |
| 22 | +- copy over the compiled binaries |
| 23 | +- copy over configuration files |
| 24 | +- spin up the server (agent) |
| 25 | +- execute the test |
| 26 | +- shut-down the server |
| 27 | +- delete the copied binaries |
| 28 | +- delete configuration files |
| 29 | + |
| 30 | +In case of the serial feature, it also means spinning-up "fake" / "dummy" serial that can be used for the testing. |
| 31 | + |
| 32 | +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. |
| 33 | + |
| 34 | +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`. |
| 35 | + |
| 36 | +Thanks to jinja templating, and how the tests are structured, tests are parametric and easy to expand. |
| 37 | + |
| 38 | + |
| 39 | +### Debian packaging magic |
| 40 | +As you might notice, instead of simply copying over the compiled binaries (`dutctl` / `dutagent` / ...) we use Debian packages. |
| 41 | + |
| 42 | +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. |
| 43 | + |
| 44 | +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! |
| 45 | + |
| 46 | + |
| 47 | +## Project structure |
| 48 | + |
| 49 | +The most important files / directories are: |
| 50 | +- `.firmwareci/Taskfile.yml` |
| 51 | +- `.firmwareci/.jinja2_templates/` |
| 52 | +- `.firmwareci/workflows/` |
| 53 | + |
| 54 | +### Taskfile |
| 55 | +The `.firmwareci/Taskfile.yml` is there to help and automate some mundane and repetitive jobs. |
| 56 | + |
| 57 | +Contains task `jinja2:templates` which finds all jinja tempaltes in `.firmwareci/workflows/` and `.firmwareci/duts/` and runs a tempalting engine on them. |
| 58 | + |
| 59 | +The list of the templates is created dynamically with the shell command: |
| 60 | +```bash |
| 61 | +find './workflows/' './duts/' -type f -name '*.yaml.j2' |
| 62 | +``` |
| 63 | + |
| 64 | +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`. |
| 65 | + |
| 66 | + |
| 67 | +### jinja2_templates |
| 68 | +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): |
| 69 | +- `defaults.j2` |
| 70 | + - this is pure jinja2 syntax, and is imported into template with |
| 71 | + ```j2 |
| 72 | + {%- import ".jinja2_templates/defaults.j2" as defaults %} |
| 73 | + ``` |
| 74 | + - import means that the variables will become accessible, and can then be accessed in the template with: |
| 75 | + ```j2 |
| 76 | + {{ defaults.DUTCTL_ARGS }} |
| 77 | + ``` |
| 78 | +- `defaults.yaml` |
| 79 | + - this is pure YAML file to be `include`d into a template with |
| 80 | + ```j2 |
| 81 | + {% include ".jinja2_templates/defaults.yaml" with context %} |
| 82 | + ``` |
| 83 | + - essentially this is to just simply render the content of the file, ignoring any variable assignments or macros within it |
| 84 | + - 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 |
| 85 | +- `pre.yaml.j2` and `post.yaml.j2` |
| 86 | + - for pre-stage and post-stage respectively |
| 87 | + - they are copy-pasted into each test (they are `include`d in tests, meaning that their content will be rendered) |
| 88 | +
|
| 89 | +
|
| 90 | +### workflows |
| 91 | +The `workflows` directory is where the tests live. |
| 92 | +
|
| 93 | +### Systemd service |
| 94 | +The `dutagent.service` file is a systemd service file to start a dutagent on dutworker. |
| 95 | +
|
| 96 | +At the moment it is only used for firmware-ci testing. |
| 97 | +
|
| 98 | +
|
| 99 | +## Adding completely new test |
| 100 | +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. |
| 101 | +
|
| 102 | +Then update the test according to your needs. |
| 103 | +
|
| 104 | +Run `task fwci:jinja2:templates` and it will automatically generate a complete tests. That is it. It is as simple as that. |
| 105 | +
|
| 106 | +Next, I recommend to run `fwci fwci:validate`. |
| 107 | +
|
| 108 | +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". |
0 commit comments