Commit Graph
20 Commits
Author SHA1 Message Date
randy 0080ac6170 Deploy to brick-host instead of cube-host
CI / check (push) Successful in 19s
CI / deploy (push) Failing after 5m1s
cube.local and brick.local swapped IPs and brick is now the deploy
target — rename the native runner label everywhere it's referenced.
2026-09-12 01:15:09 +02:00
randy 2c3dd4534e Add P4N_SESSION_COOKIE for p4n2gpx, since login alone can't work headless
CI / check (push) Successful in 40s
CI / deploy (push) Successful in 13s
Traced the plugin's "Login failed" error directly against
park4night.com: correct credentials still get rejected because the
login form is behind invisible reCAPTCHA, which only a real browser
ever satisfies. p4n2gpx.rb (outside this repo) now checks
P4N_SESSION_COOKIE first and uses it as-is, skipping the login POST
entirely — the cookie comes from an already-authenticated browser,
copied out by hand and refreshed when it expires. Wired the env var
through docker-compose.yaml and the deploy workflow's "Write .env"
step the same way as P4N_USER/P4N_PASSWORD.
2026-09-09 18:07:03 +02:00
randy 92cc0c87ed Wire up p4n2gpx as a private plugin
CI / check (push) Successful in 47s
CI / deploy (push) Successful in 1m53s
data/plugins/p4n2gpx/ (outside git, see .gitignore) now holds a
plugin.json + run.rb wrapper around ../p4n2gpx/ruby/p4n2gpx.rb, so it
runs through the same --south/--west/--north/--east-in,
GeoJSON-on-stdout-out contract as the built-in overpass-pois plugin.
run.rb converts the requested bbox to the center+radius p4n2gpx.rb
itself expects, then reuses lib/maptool/gpx.rb to turn its .gpx output
into GeoJSON.

p4n2gpx.rb needs faraday-cookie_jar, which wasn't in the Gemfile yet
(faraday itself already was, transitively via oauth2) — added and
locked. Also wires P4N_USER/P4N_PASSWORD through docker-compose.yaml
and the deploy workflow's "Write .env" step, the same optional-secret
pattern as LIVETRACK_WEBHOOK_SECRET, since the container has no
browser for p4n2gpx.rb's Chrome-cookie auth fallback.
2026-09-09 17:38:53 +02:00
randy 76e3239d54 Tidy the deploy checkout into build/, symlink docker-compose.yaml up
CI / check (push) Successful in 44s
CI / deploy (push) Canceled after 40s
Sources now sync into /srv/podman/maptool/build/ (wiped and fully
replaced every deploy, nothing in it needs preserving) instead of
directly into /srv/podman/maptool/ itself, where data/ and .env also
live — the old sync step had to specifically skip data/ by name to
avoid wiping it; this way there's nothing to skip.

docker-compose.yaml is symlinked (ln -sf, relative target) from
/srv/podman/maptool/ up to build/ — both for a human to still find it
at the top, and because that symlink's own location, not build/, is
what compose resolves ./data and .env's directory against. No changes
to docker-compose.yaml or the podman-compose@.service systemd unit's
WorkingDirectory needed.

Verified against a full local dry run of the new sync step (copy into
a fake build/, symlink up, confirm pre-existing data/ survives) and
`docker-compose config` against the real docker-compose.yaml through
that symlink — both volume mounts (./data, the kiwix ZIM path)
resolved to the sibling data/ directory as intended, not build/data.
2026-09-09 14:13:42 +02:00
randy 5c9516d038 Check the deployed revision, not just any 200, in the health poll
CI / check (push) Successful in 53s
CI / deploy (push) Successful in 13s
/api/health now reports REVISION alongside status, and the CI wait
step checks for this deploy's own short SHA specifically - a stray
old container that never got torn down (or a build that silently
kept serving stale code) would still 200 on a plain health check but
now won't match.
2026-09-08 21:19:03 +02:00
randy 4982f04258 Verify the deploy actually came up, not just that it was launched
systemctl restart (Type=simple, no readiness protocol) returns as
soon as podman compose up --build forks, before the build or the
container start have actually finished - a build failure or crash
loop would still show as a green deploy job. Poll /api/health for up
to 5 minutes (comfortably above the ~3.5min worst-case cold rebuild)
and fail the job if it never answers.
2026-09-08 21:16:41 +02:00
randy a908cd7abc Fix the real cause of slow podman deploys: add --build, drop podman rmi
CI / check (push) Successful in 44s
CI / deploy (push) Successful in 3s
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.
2026-09-08 21:12:54 +02:00
randy 049d54e44e Use the short maptool:latest image name in the deploy job
CI / check (push) Successful in 43s
CI / deploy (push) Successful in 4s
docker.io/library/maptool:latest and maptool:latest resolve to the
same local image (verified on cube.local) - the docker.io/library
prefix is just podman's normalization of the unqualified name, not an
actual registry reference. Short form matches what docker-compose.yaml
itself uses and avoids implying a Docker Hub push/pull that never
happens.
2026-09-08 20:38:14 +02:00
randy e4764c64e4 Drive maptool's deploy through the podman-compose@ systemd service
The service's own ExecStart deliberately runs a plain podman compose
up (no --build) since ExecStartPre already tears down the previous
containers/networks/volumes on every start — but that leaves the
built image alone, so the deploy job now removes it directly first
(what forces a fresh build) and drives start/stop through systemctl
rather than calling podman/docker compose by hand. Also switches
/srv/docker/maptool to /srv/podman/maptool per the symlink now in
place, and updates deployment.adoc to match.
2026-09-08 20:33:03 +02:00
randy 61ba86c6e6 Add a GNSS simulator for dev without gpsd running
bin/gnss_simulator.rb speaks gpsd's own JSON wire protocol directly
on its default port -- GpsdClient connects to it exactly as it would
to real gpsd, no app changes needed, and no gpsd install/daemon
required either (unlike the existing fake-NMEA-source approach in
docs/development.adoc, which still needs gpsd itself in front of it).
Drives a loop around a center point at a driving-ish pace rather than
sitting still, since a fixed position isn't much of a "GNSS position"
to look at.

Verified end to end: started it, pointed a dev server at it, and
confirmed /api/gnss/position reports a moving fix across two polls.
2026-09-08 00:28:34 +02:00
randy 37bc14f3ba Show the deployed commit as a hover tooltip on the topbar brand
CI / check (push) Successful in 47s
CI / deploy (push) Successful in 27s
ASSET_VERSION only proves *a* deploy happened recently, not *which*
commit -- not enough to answer "did my push actually deploy, or am I
looking at a stale browser cache" (today's actual answer: neither --
deploy was current, a GeoJSON cache predating a code change was just
never invalidated, since it only checks the source .gpx's mtime).

The CI deploy job now writes REVISION (short SHA) before dropping
.git; app.rb reads it at boot, falling back to "dev" locally/in CI's
own check job where the file never exists.
2026-09-07 23:54:24 +02:00
randy cd4eef342b Add a persisted test suite
CI / check (push) Successful in 1m56s
CI / deploy (push) Successful in 2m56s
`bundle exec rake test` (minitest, a default gem but pinned in
Gemfile for reproducibility) now covers what ad-hoc scripts kept
re-verifying by hand during development: Gpx/Fit/TrackStats parsing,
GpxStore/LiveTrackStore file/TTL logic, LiveTrackClient's payload
parsing, and app.rb's routes end to end via Rack::MockRequest.

MAPTOOL_DATA_DIR (new, app.rb) lets the suite point GPX_STORE/
LIVETRACK_STORE at a throwaway directory instead of real data/ —
without it every run would leave uploaded test files behind. Each
lib file's old `if __FILE__ == $0` self-check is now redundant with
real tests covering the same ground, so removed rather than kept as
a second copy of the same assertions. Wired into ci.yml so it isn't
just a local convenience.
2026-09-07 12:46:35 +02:00
randy f9ddf860ea Add Garmin LiveTrack session tracking
CI / check (push) Successful in 6m49s
CI / deploy (push) Successful in 23s
A Gmail-watching Apps Script (documented in docs/deployment.adoc) posts
the session ID from each LiveTrack email to a new webhook, which stores
it in data/livetrack.json; a new sidebar panel lists what's been
received.
2026-09-06 21:05:35 +02:00
randy 60170efda2 Rename deploy runner label to cube-host
CI / check (push) Successful in 6m26s
CI / deploy (push) Successful in 22s
2026-08-28 20:38:16 +02:00
randy e13d1a1e97 Require Gitea login to write GPX data; IPv6-capable bind
CI / check (push) Successful in 6m28s
CI / deploy (push) Successful in 13s
Upload/delete/move/create-folder now require logging in via Gitea
OAuth2 (only MAPTOOL_ALLOWED_GITEA_USER is granted write access);
reading stays public. Deploy secrets (session secret, OAuth2 client
credentials, allowed user) are written to .env from Gitea Actions
repo secrets on every deploy instead of living on the server by hand.

Also switch the container's bind address to "[::]" (dual-stack) so
the app is reachable over IPv6, not just IPv4.
2026-08-27 18:02:37 +02:00
randy ae67cc72c7 Move deploy job to a dedicated native runner
CI / check (push) Successful in 5m43s
CI / deploy (push) Successful in 2m46s
The Docker-based runner's own container is too minimal for host-mode
jobs (no rsync, docker CLI, or Node.js) and has no reliable path to
the host filesystem or systemctl otherwise. Register a separate,
native runner (label deploy:host) just for deployment, and point the
deploy job at it.
2026-08-27 16:12:33 +02:00
randy 71e638b459 Fix CI: host-mode runner has no Node.js for actions/checkout
CI / check (push) Successful in 7m3s
CI / deploy (push) Failing after 1s
Host-mode jobs run directly in the runner container instead of a
spawned per-job container, so JS actions like actions/checkout@v4
have no Node.js runtime to execute with. Replace it with a plain git
fetch/checkout in the deploy job.
2026-08-27 15:39:47 +02:00
randy 3a79c3d6c1 Add Docker deployment via Gitea Actions host-mode runner
CI / check (push) Successful in 5m47s
CI / deploy (push) Failing after 1s
Containerize the app (Dockerfile, docker-compose.yaml) and add a CI
deploy job that syncs the checkout to /srv/docker/maptool and runs
docker compose directly, using the runner's new "host" execution
label to reach the host's Docker daemon and filesystem.
2026-08-27 14:54:21 +02:00
randy f186a3e8ef Fix CI: ruby/setup-ruby doesn't recognize "file" as a version keyword
CI / check (push) Successful in 5m47s
Omitting ruby-version entirely triggers its actual auto-detection from
.ruby-version — "file" was a mistaken guess and failed with "Unknown
engine file".
2026-08-27 14:06:31 +02:00
randy 7f2ad57d1a Add a Gitea Actions CI workflow
CI / check (push) Failing after 1m30s
Ruby syntax check, a require_relative "app" smoke load, and JS syntax
check on every push/PR. No test suite exists yet, so these are cheap
syntax/load checks rather than behavioral tests.
2026-08-27 14:03:37 +02:00