GitHub CI/CD Architecture
All automation is built on reusable workflows hosted in the central .github repository, which individual repos call into.
1. High-Level Overview
The organization follows a hub-and-spoke model: four reusable workflows live in the central .github repo, and every project repo calls them as needed. A cross-repo dispatch chain ensures the documentation site is rebuilt automatically whenever any repo publishes a release.
2. Central Reusable Workflows
All reusable workflows are defined in ARTTU-Software/.github/.github/workflows/ and are invoked with workflow_call.
| Workflow | Trigger | Purpose | Key Actions Used |
|---|---|---|---|
ceedling-test.yml | workflow_call | Runs Ceedling C unit tests and publishes JUnit results to PRs | ruby/setup-ruby, EnricoMi/publish-unit-test-result-action |
stm32-build.yml | workflow_call | Cross-compiles STM32 firmware with CMake + Ninja, uploads .elf/.bin/.map artifacts | carlosperate/arm-none-eabi-gcc-action, hendrikmuhs/ccache-action |
linter.yml | workflow_call | Runs Clang-Tidy static analysis using the compile database from the build step | cpp-linter/cpp-linter-action (needs stm32-build artifact) |
create-release.yml | workflow_call | Creates a GitHub Release, attaches firmware binaries, triggers a documentation rebuild | softprops/action-gh-release, peter-evans/repository-dispatch |
Reusable Workflow Inputs
3. Firmware CI Pipeline (PR)
All firmware repositories with CI (ECU, CAN-Gateway, Telemetry, Galvanic-Isolator, LVSOC-26) share a byte-for-byte identical ci.yml that runs a three-stage pipeline on every pull request. Charger currently does not have a CI pipeline.
NOTE
The linter job depends on (needs:) the build job because it downloads compile_commands.json from the build artifacts. The Ceedling tests run in parallel with the build.
4. Firmware Release Pipeline
When a version tag (v*) is pushed to any firmware repo, the release pipeline builds the firmware and publishes a GitHub Release. For repos with a build step (ECU, CAN-Gateway, Telemetry, Galvanic-Isolator, LVSOC-26), firmware binaries are attached. Charger publishes a release without build artifacts.
5. Library Repo Pipelines
The common and utilities repos follow simpler patterns since they are shared libraries that don't produce standalone firmware binaries.
common
utilities
This repo only runs release and labeler workflows — no CI or unit tests.
6. Application Repo Pipelines
Backend
Documentation
The documentation site has a unique three-trigger deploy:
7. Universal PR Labeler
Every repository in the organization has an identical labeler.yml workflow that auto-labels pull requests based on changed file types. The labeling rules are centrally defined in ARTTU-Software/.github/.github/labeler.yml.
| Label | File Patterns |
|---|---|
C/C++ | *.c, *.cpp, *.h, *.hpp |
TypeScript | *.ts, *.tsx |
Python | *.py |
Arduino | *.ino, *.pde |
Driver | Drivers/**/* |
CI/CD | .github/**/* |
documentation | docs/**/*, *.md |
Build System | CMakeLists.txt, *.cmake |
8. Who Calls What
This table shows every repo and exactly which central reusable workflows it invokes:
9. Repo Coverage Summary
| Repository | CI (PR) | Unit Tests | Release | Deploy | Labeler |
|---|---|---|---|---|---|
| ECU | ✅ build + lint | ✅ Ceedling | ✅ with firmware | — | ✅ |
| CAN-Gateway | ✅ build + lint | ✅ Ceedling | ✅ with firmware | — | ✅ |
| Telemetry | ✅ build + lint | ✅ Ceedling | ✅ with firmware | — | ✅ |
| Galvanic-Isolator | ✅ build + lint | ✅ Ceedling | ✅ with firmware | — | ✅ |
| LVSOC-26 | ✅ build + lint | ✅ Ceedling | ✅ with firmware | — | ✅ |
| Charger | — | — | ✅ no artifact | — | ✅ |
| common | — | ✅ Ceedling | ✅ no artifact | — | ✅ |
| utilities | — | — | ✅ no artifact | — | ✅ |
| Backend | — | — | ✅ | ✅ SSH | ✅ |
| documentation | — | — | — | ✅ SSH | ✅ |
| Partners-Database-App | — | — | — | — | — |
