systemd as a CI system
I make fairly extensive use of systemd for scripting tasks which I need to run repeatedly and possibly on schedule (or based on other triggers), and recording a log of the output. At work and among friends, people use Jenkins for the same purpose. This gave me a stupid idea - can I turn systemd into Jenkins, and use it to build Git codebases?
Disclaimer: This is purely a bit of “what if?” fun, not serious advice
The basic idea is quite simple
- Write a timer to pull a git repo
- If a new change is found, trigger a oneshot service to build the project
Writing this for each project would get quite repetitive, so I’d like to generify it as follows
- The timer will be parameterised with the git URL, so I can do
systemctl enable systemd-ci-poll@$REPO
- The builder service will expect an executable at
$REPO/.systemd-ci/build
Assumptions
Since this is just a proof of concept, I make the followingg assumptions
- Every project has a name marching
[a-Z0-9]+
, to saves character escaping headaches - Every project is already cloned in the workspace dir, and we’re only building the branch that’s been checked out
- I’m not including any sort of artefact archiving or workspace cleaning. That could be implemented if needed, but for this PoC I’ll take the laissez-faire approach of leaving that to the build script
- We can always fast-forward. No force pushes!
System setup
I deployed a fresh Ubuntu 20.04 LTS Linux container on Proxmox and made the following changes
- Installed
git
- Add a
systemd-ci
user and group with the normal minimal permissions expected of a service user - Create the workspace dir
/var/lib/systemd-ci
with ownersystemd-ci:systemd-ci
and mode770
The builder service
This service is quite simple - just run an executable
/etc/systemd/system/systemd-ci-build@.service
We can test this in isolation, by just creating
/var/lib/systemd-ci/test/.systemd-ci/build
(mode: +x
)
Then execute systemctl start systemd-ci-build@test
(remembering to do a daemon-reload
first). Logs can be found with journalctl -u systemd-ci-build@test
The trigger service
So for the timer, we need to repeatedly pull the repository, and take note of when it changes. In accordance with assumption 4, let’s be really hacky and just grep Fast-forward
in the git output
/etc/systemd/system/systemd-ci-poll@.service
And here we run into a problem. OnSuccess
was added in systemd 249, but this version of Ubuntu has 245. Luckily, bash has a negation operator, so I can use OnFailure
and ExecStart=/bin/bash -c "! git...
The polling timer
/etc/systemd/system/systemd-ci-poll@.timer
As far as I understand you need to enable systemd-ci-poll@.timer
at least once, in addition to systemd-ci-poll@$REPO.timer
. Well, I guess that provides an easy way to turn the whole thing off if needed
Project creation script
systemd-ci-init
(mode +x
)
Conclusion
Yes, you can do it, no, you probably shouldn’t. The main problem is that you pollute the logs with “failed” polls, but I imagine this can be fixed if one is determined enough, but not on version 245