2025-06-12 - Dev Log
Gitea Actions CI/CD Pipeline for Skyweave
- Date: 2025-05-14
- Summary: This session focused on establishing a full Continuous Integration (CI) and Continuous Deployment (CD) pipeline for the
skyweaveLua-based API project. We successfully configured a Gitea Actions runner, built a multi-stage CI workflow for linting and unit testing, and troubleshooted numerous environment and configuration issues to achieve a stable, passing build. - Potential Tags:
#skyweave,#gitea-actions,#ci-cd,#lua,#openwrt,#embedded-devops - Potential Links:
[[RVLink System Exploitation]],[[Skyweave Lua Framework]],[[Gitea Runner Configuration]]
Key Topics & Discussion Points
Initial CI/CD Goal: Automated Deployment
- Objective: The initial request was to create a Gitea Action to automatically deploy the
skyweaveapplication to the MV2400 roof unit on agit push. - Initial Plan:
- Create a
.gitea/workflows/deploy.ymlfile. - Use Gitea Secrets to store SSH credentials (
MV2400_HOST,MV2400_USER, etc.). - Use an action like
appleboy/ssh-actiontoscpfiles and restart the service.
- Create a
Gitea Runner Setup & Troubleshooting
- Requirement: A Gitea Runner (
act_runner) is required to execute the workflow jobs. - Initial Runner Issue: The user encountered a
-bash: ./act_runner: Text file busyerror.- Diagnosis: This error typically means the process is already running.
- Troubleshooting:
lsofandpscommands proved the process was not running, pointing to a more subtle issue.
- Second Runner Issue: After re-downloading the binary, a new error appeared:
fatal error: mallocgc called without a P or outside bootstrapping.- Diagnosis: This is a classic Go runtime error indicating a CPU architecture mismatch (e.g., running an
amd64binary on anaarch64machine). - Resolution: The user needed to download the correct binary for their machine’s architecture, found by running
uname -m.
- Diagnosis: This is a classic Go runtime error indicating a CPU architecture mismatch (e.g., running an
- Final Runner Approach: Docker
- Decision: The user opted to use the official
gitea/act_runner:latestDocker image for a cleaner setup. - Initial Docker Error:
Error: daemon Docker Engine socket not found. - Diagnosis: The runner container, which needs to spawn other containers for CI jobs, could not access the host’s Docker daemon.
- Resolution: The host’s Docker socket was mounted into the runner container by adding the
-v /var/run/docker.sock:/var/run/docker.sockflag to thedocker runcommand.
- Decision: The user opted to use the official
CI Stage 1: Lua Linting with luacheck
- Objective: Automatically scan all Lua code for syntax errors and style violations.
- Initial
ci.ymlError: The first attempt failed because theactions/checkout@v4step requires a Node.js runtime, which was not present in the minimalalpine:latestcontainer.- Resolution: Switched the job’s container to
node:lts-alpineand installed Lua tools inside it.
- Resolution: Switched the job’s container to
luacheckConfiguration (.luacheckrc):- Challenge 1:
luacheckflagged built-inbustedfunctions (describe,it,assert) as undefined variables in the test files. - Initial Attempt: A separate
.luacheckrcin thespec/directory was proposed, but this hierarchical approach did not work in the CI environment. - Final, Correct Solution: The user discovered the correct syntax for the root
.luacheckrcfile to define per-file globals:
- Challenge 1:
files['spec/'] = {
read_globals = { 'describe', 'it', 'assert', ... }
}
Challenge 2: The linter was failing the build due to benign warnings (e.g., “line is too long”, “unused variable”).
- Resolution: The user discovered that the warning codes in the
.luacheckrcignoretable must be numeric strings (e.g.,"111") not alphanumeric ("W111").
CI Stage 2: Unit Testing with busted
- Objective: Run unit tests to verify the logic of individual Lua modules.
- Test Target: We created a sample test file,
spec/utils_spec.lua, to test theparse_query_stringfunction inskyweave/utils.lua. - Initial
bustedError: The test failed with amodule 'json' not founderror.- Diagnosis: The test environment did not know the location of the
json.lualibrary, which resides in thelib/directory. The application relies on a specific deployment path (/usr/lib/lua/) that doesn’t exist in the CI container. - Resolution: A pre-test step was added to the CI workflow to copy the library into the path searched by the test runner:
cp lib/json.lua skyweave/.
- Diagnosis: The test environment did not know the location of the
Advanced Testing: Integration Test Simulation
- User Question: The user correctly pointed out that running application code would fail in a generic container because it relies on OpenWrt-specific binaries like
iwinfoanduci. - Proposed Solution: A high-fidelity simulation using a custom Docker image.
- Base Image: Use an x86 build of OpenWrt/LEDE to provide a similar filesystem and base utilities.
- Mocking: Create mock scripts (fake
iwinfo,uci, etc.) that live in a separate directory (/usr/bin_mock) and prepend this directory to the container’s$PATH. These scripts would return predictable, static output for the application to parse during tests. - CI Job: A new
integration-testjob would build this Docker image, run a web server with the CGI script, and then usecurlor a Python script to make real HTTP calls to the running service to verify end-to-end functionality against the mocked data.
Decisions Made
- The Gitea Runner will be run via the official Docker image for ease of management.
- The CI pipeline will consist of two main jobs:
lint-all-codeandunit-test-lua. - A single, unified
.luacheckrcfile will be used, leveraging thefiles['spec/']syntax to apply specific rules to test files. - Specific, non-critical
luacheckwarnings will be ignored via the.luacheckrcfile to prevent CI failures on stylistic issues. - A pre-test step will be included in the CI workflow to copy necessary libraries (
json.lua) into the test environment’s path.
Action Items
- Expand Unit Test Coverage: Write more
bustedtests for other functions inutils.luaand for the business logic in theskyweave/handlers/modules. - (Future) Implement Integration Testing: When ready, create the
test/Dockerfileand the mock scripts to build the high-fidelity simulation environment. - (Future) Add Integration Test Job: Add the
integration-testjob to the.gitea/workflows/test.ymlfile to automate the end-to-end testing process.
Key Takeaways & Conclusions
- CI for Embedded is Nuanced: Testing applications for bespoke embedded environments requires simulating those environments, often through custom Docker images and mock executables.
- Configuration is Key: The majority of troubleshooting involved finding the correct syntax and structure for configuration files (
.luacheckrc) and CI workflows (.yml), and understanding the specific requirements of the tools (luacheck,busted,act_runner). - Iterative Problem Solving: The final, successful pipeline was achieved through a collaborative, iterative process of proposing a solution, analyzing the failure log, and refining the approach.
- Success! A fully functional, two-stage CI pipeline is now operational, automatically linting and unit-testing the
skyweaveproject.