podman-compose@.service was missing the --build flag that docker-compose@.service already has (added on cube.local: /etc/systemd/system/podman-compose@.service), so removing maptool:latest before every restart (my own earlier fix, meant to force a rebuild) also destroyed the build cache along with it - every deploy was redoing apt-get/bundle install from scratch (~3 min measured, vs ~20s before). --build lets a plain systemctl restart rebuild while still reusing unchanged layers, same as docker did, so the ci.yml deploy step collapses back to one line.
112 lines
4.7 KiB
YAML
112 lines
4.7 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
pull_request:
|
|
|
|
jobs:
|
|
check:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
# No ruby-version input: the action auto-detects it from
|
|
# .ruby-version when the input is omitted (not "file", which isn't
|
|
# a recognized value and fails with "Unknown engine file").
|
|
- uses: ruby/setup-ruby@v1
|
|
with:
|
|
bundler-cache: true
|
|
|
|
- name: Ruby syntax check
|
|
run: find app.rb config lib bin -name "*.rb" -print0 | xargs -0 -n1 ruby -c
|
|
|
|
- name: App loads without errors
|
|
run: bundle exec ruby -e 'require_relative "app"'
|
|
|
|
- name: Ruby tests
|
|
run: bundle exec rake test
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "22"
|
|
|
|
- name: JS syntax check
|
|
run: find public/js -name "*.js" -print0 | xargs -0 -n1 node --check
|
|
|
|
# Handled by a separate, native (non-Docker) runner registered with the
|
|
# single "cube-host" label (see docs/deployment.adoc) — it runs directly
|
|
# on the server, so it has podman/git/etc. from the host, no socket/bind
|
|
# mount tricks needed. The Docker-based runner keeps handling `check`.
|
|
deploy:
|
|
needs: check
|
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
runs-on: cube-host
|
|
steps:
|
|
# Not actions/checkout@v4: keeping this plain-git checkout from when
|
|
# the job ran in a Node-less container — no reason to add a Node
|
|
# dependency back in for something this already does.
|
|
- name: Checkout
|
|
run: |
|
|
rm -rf .git * .[!.]* 2>/dev/null
|
|
git init -q
|
|
git remote add origin "${{ gitea.server_url }}/${{ gitea.repository }}.git"
|
|
git -c http.extraHeader="Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
|
|
fetch --depth 1 origin "${{ gitea.sha }}"
|
|
git checkout -q FETCH_HEAD
|
|
|
|
# Read by app.rb at boot and shown (as a hover tooltip on the topbar
|
|
# brand) so it's possible to tell which commit is actually live
|
|
# without digging through `tea actions runs list` — written here,
|
|
# before .git gets dropped below, since that's otherwise the only
|
|
# place the commit is recorded.
|
|
- name: Write REVISION
|
|
run: git rev-parse --short HEAD > REVISION
|
|
|
|
# Clears out everything in the target except data/ (uploaded GPX
|
|
# files, offline.pmtiles) and copies the fresh checkout over, dropping
|
|
# .git afterwards. Dotfiles like .env (deployment secrets) are left
|
|
# alone too — the glob below doesn't match them — and neither is ever
|
|
# part of the git checkout in the first place, since both are
|
|
# gitignored.
|
|
- name: Sync to /srv/podman/maptool
|
|
run: |
|
|
mkdir -p /srv/podman/maptool
|
|
for f in /srv/podman/maptool/*; do
|
|
[ "$(basename "$f")" = "data" ] && continue
|
|
rm -rf "$f"
|
|
done
|
|
cp -a . /srv/podman/maptool/
|
|
rm -rf /srv/podman/maptool/.git
|
|
|
|
# Regenerated on every deploy from repo secrets (Settings -> Actions
|
|
# -> Secrets) rather than created once by hand on the server — see
|
|
# docs/deployment.adoc. Values are masked in the job log by Gitea
|
|
# automatically since they come from `secrets`. Secret names here
|
|
# can't start with "GITEA_"/"GITHUB_" — Gitea reserves those prefixes
|
|
# — hence OAUTH_CLIENT_* rather than GITEA_OAUTH_CLIENT_*; the .env
|
|
# var names on the right of `=` are unaffected, still what app.rb
|
|
# actually reads.
|
|
- name: Write .env
|
|
run: |
|
|
cat > /srv/podman/maptool/.env <<EOF
|
|
SESSION_SECRET=${{ secrets.SESSION_SECRET }}
|
|
GITEA_OAUTH_CLIENT_ID=${{ secrets.OAUTH_CLIENT_ID }}
|
|
GITEA_OAUTH_CLIENT_SECRET=${{ secrets.OAUTH_CLIENT_SECRET }}
|
|
MAPTOOL_ALLOWED_GITEA_USER=${{ secrets.MAPTOOL_ALLOWED_GITEA_USER }}
|
|
LIVETRACK_WEBHOOK_SECRET=${{ secrets.LIVETRACK_WEBHOOK_SECRET }}
|
|
EOF
|
|
chmod 600 /srv/podman/maptool/.env
|
|
|
|
# podman-compose@maptool.service (/etc/systemd/system/podman-compose@.service)
|
|
# owns the container lifecycle — its ExecStartPre already tears down
|
|
# the previous containers/networks/volumes on every start, and its
|
|
# ExecStart runs `podman compose up --build` (mirroring
|
|
# docker-compose@.service's own `--build`), so a plain restart always
|
|
# picks up the code just synced above while still reusing unchanged
|
|
# layers (apt-get/bundle install) as cache — unlike explicitly
|
|
# removing the image first, which would delete that cache along with
|
|
# it. sudo is needed since the unit is root's, not gitea-runner's own
|
|
# (gitea-runner has passwordless sudo for this on cube-host).
|
|
- name: Deploy
|
|
run: sudo systemctl restart podman-compose@maptool.service
|