Service Template
An opinionated Go service scaffold with GitHub Actions CI/CD, multi-environment Docker builds, and first-class homelab Caddy integration baked in. Clone and rename to start a production-ready Go service.


service-template is the scaffold every new homelab service in this portfolio is cloned from: GitHub Actions CI/CD, multi-arch Docker builds, and the Caddy/Ansible conventions homelab-automation expects are already wired up before a single line of business logic exists. Its GitHub Actions workflow is the literal template homelab-automation's repository_dispatch deploy pipeline is built around — build, push to GHCR, then fire a dispatch event the homelab automation listens for and rolls out via Ansible. The template also models a theoretical dev/prod split: a service cloned from it can deploy to both a `prod` and a `dev` branch-tracked environment side by side (see its two live links), demonstrating how a future feature branch could get its own short-lived deployment without touching the production service, even though today every actual service in the homelab deploys straight from `main`.
Architecture
graph TD Push["git push
(main / dev/* / *dev*)"] --> Test["go test + SonarQube"] Test --> Build["docker build & push
(GHCR)"] Build -->|tag: latest or dev| Deploy["deploy job
computes tag + environment"] Deploy -->|repository_dispatch| Homelab["MrCodeEU/homelab-automation"] Homelab -->|Ansible rollout| Prod["production env"] Homelab -->|Ansible rollout| Staging["staging/dev env"]
Under the hood
The deploy job doesn't push anything itself — it just decides which tag/environment apply and fires a repository_dispatch at the homelab-automation repo, which owns the actual rollout.
deploy:
runs-on: ubuntu-latest
needs: build-and-push
if: |
github.event_name != 'pull_request' &&
(github.ref == 'refs/heads/main' || contains(github.ref, 'dev'))
steps:
- name: Determine deployment tag
id: deploy-tag
run: |
if [ "${{ github.ref }}" == "refs/heads/main" ]; then
echo "tag=latest" >> $GITHUB_OUTPUT
echo "environment=production" >> $GITHUB_OUTPUT
else
echo "tag=dev" >> $GITHUB_OUTPUT
echo "environment=staging" >> $GITHUB_OUTPUT
fi
- name: Trigger homelab deployment
run: |
curl -X POST \
-H "Authorization: token ${{ secrets.DISPATCH_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/MrCodeEU/homelab-automation/dispatches \
-d "{\"event_type\": \"service-update\", \"client_payload\": {\"service\": \"${{ github.event.repository.name }}\", \"tag\": \"${{ steps.deploy-tag.outputs.tag }}\", \"environment\": \"${{ steps.deploy-tag.outputs.environment }}\"}}"