Commit Graph

619 Commits

Author SHA1 Message Date
Gitea CI 124f1f5cf5 chore(deploy): bump image to a6a73b5f [skip ci] 2026-05-14 18:38:04 +00:00
funman300 a6a73b5f36 fix(ci): add permission and env diagnostics to build step
Android Build / build-apk (push) Failing after 3m47s
Build and Deploy / build-and-push (push) Successful in 36s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 11:33:54 -07:00
Gitea CI b84fe79806 chore(deploy): bump image to 3248f00d [skip ci] 2026-05-14 18:32:22 +00:00
funman300 3248f00d66 fix(ci): deeper SDK verification — find android.jar actual location
Android Build / build-apk (push) Failing after 3m41s
Build and Deploy / build-and-push (push) Successful in 25s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 11:28:17 -07:00
Gitea CI c680a043ae chore(deploy): bump image to d0ab7ed9 [skip ci] 2026-05-14 18:26:23 +00:00
funman300 d0ab7ed97b fix(ci): add SDK verification step to diagnose platforms-not-found
Android Build / build-apk (push) Failing after 3m28s
Build and Deploy / build-and-push (push) Successful in 39s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 11:22:11 -07:00
Gitea CI 1144a96757 chore(deploy): bump image to eba1f66b [skip ci] 2026-05-14 18:18:13 +00:00
funman300 ac6668cee7 fix(ci): apply template-expansion pattern to release workflow
Android Build / build-apk (push) Failing after 2m59s
Build and Deploy / build-and-push (push) Failing after 46s
Mirror the fix from android-build.yml: rename ANDROID_HOME -> ANDROID_SDK
in the env block to avoid the Docker-image-baked ANDROID_HOME overriding
the workflow value in run scripts. Use ${{ env.ANDROID_SDK }} template
expressions throughout, and explicitly export ANDROID_HOME/ANDROID_NDK_HOME
before cargo-apk build so it finds the SDK at the right path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 11:17:58 -07:00
funman300 eba1f66b45 fix(ci): use template-expanded paths in run scripts to bypass Docker ENV
Android Build / build-apk (push) Failing after 3m6s
Build and Deploy / build-and-push (push) Successful in 31s
Replace shell variable $ANDROID_HOME references in run blocks with
${{ env.ANDROID_SDK }} template expressions. Gitea runner v1 may not
override Docker-image-baked ENV vars via docker exec; template expansion
happens at workflow compilation time, so the literal path is hardcoded
into the script before the shell runs it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 11:14:34 -07:00
Gitea CI 90959728b1 chore(deploy): bump image to 8b30f877 [skip ci] 2026-05-14 18:11:34 +00:00
funman300 8b30f8778b fix(ci): use fresh /opt/android-sdk path to avoid container ENV conflict
Android Build / build-apk (push) Failing after 3m9s
Build and Deploy / build-and-push (push) Successful in 50s
Remove SDK detection logic and install directly to /opt/android-sdk,
matching the release workflow. The container Docker image has ANDROID_HOME
baked in at /usr/local/lib/android/sdk; installing there with sudo while
cargo-apk resolves ANDROID_HOME from the image ENV created a divergence.
Using a controlled path we own eliminates that class of conflict entirely.
Add SDK cache shared with the release workflow (same key prefix v2-).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 11:07:46 -07:00
Gitea CI d6a7924f14 chore(deploy): bump image to 4db43fb3 [skip ci] 2026-05-14 18:02:16 +00:00
funman300 4db43fb3fb fix(ci): replace ANDROID_SDK_ROOT with ANDROID_HOME in release workflow
Android Build / build-apk (push) Failing after 3m49s
Build and Deploy / build-and-push (push) Successful in 54s
ANDROID_SDK_ROOT was never set; zipalign and apksigner were resolving
to empty paths and would fail. All three occurrences replaced with
ANDROID_HOME which is defined in the workflow env block.

Also adds sudo to the cache-miss SDK install (mkdir/mv/sdkmanager) to
match the debug workflow pattern — /opt/android-sdk requires root on
a fresh runner.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 10:56:42 -07:00
funman300 01d6b27e61 fix(ci): detect existing container SDK before installing, set ANDROID_HOME via GITHUB_ENV
Android Build / build-apk (push) Failing after 3m50s
Build and Deploy / build-and-push (push) Failing after 33s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 10:53:14 -07:00
funman300 3cffbc2c51 feat(engine): embed classic theme into binary like dark theme
Classic SVGs and manifest are now compiled in via include_bytes!(),
making the theme available on all platforms (desktop, Android) without
requiring filesystem assets. Removes the now-redundant Dockerfile COPY
of solitaire_engine/assets/themes/classic.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 10:53:14 -07:00
Gitea CI 2ef25934ac chore(deploy): bump image to bb670d6c [skip ci] 2026-05-14 17:51:40 +00:00
funman300 bb670d6cc6 fix(ci): drop ANDROID_SDK_ROOT, pass --sdk_root to sdkmanager explicitly
Android Build / build-apk (push) Failing after 3m19s
Build and Deploy / build-and-push (push) Successful in 30s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 10:47:52 -07:00
Gitea CI 76911c57c9 chore(deploy): bump image to 8391235a [skip ci] 2026-05-14 17:45:46 +00:00
funman300 8391235a1a fix(ci): check android.jar existence in platform dir
Android Build / build-apk (push) Failing after 3m25s
Build and Deploy / build-and-push (push) Successful in 30s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 10:41:57 -07:00
funman300 2f3a6b9586 fix(ci): dump env at build time to diagnose ANDROID_HOME visibility
Android Build / build-apk (push) Failing after 3m23s
Build and Deploy / build-and-push (push) Failing after 40s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 10:37:37 -07:00
Gitea CI 4d20b70809 chore(deploy): bump image to bfadcf0e [skip ci] 2026-05-14 17:32:04 +00:00
funman300 bfadcf0e0d fix(ci): add SDK layout debug step to diagnose platforms-not-found error
Android Build / build-apk (push) Failing after 3m19s
Build and Deploy / build-and-push (push) Successful in 42s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 10:28:10 -07:00
Gitea CI 356dbebe57 chore(deploy): bump image to c90c7831 [skip ci] 2026-05-14 17:28:04 +00:00
funman300 c90c783177 fix(ci): set ANDROID_HOME/NDK_HOME in workflow env block instead of GITHUB_ENV
Android Build / build-apk (push) Failing after 3m23s
Build and Deploy / build-and-push (push) Successful in 40s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 10:23:58 -07:00
Gitea CI bbf4b2c14a chore(deploy): bump image to 1f46785b [skip ci] 2026-05-14 17:19:04 +00:00
funman300 62be72e918 fix(ci): bust SDK cache key to force fresh SDK install after prior broken cache
Android Build / build-apk (push) Failing after 3m16s
Build and Deploy / build-and-push (push) Failing after 39s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 10:18:57 -07:00
funman300 1f46785b31 fix(ci): add apt-get update before package install to fix exit code 100
Android Build / build-apk (push) Failing after 3m50s
Build and Deploy / build-and-push (push) Successful in 39s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 10:14:32 -07:00
Gitea CI 2e5d82f83c chore(deploy): bump image to 396ba6bc [skip ci] 2026-05-14 17:12:21 +00:00
funman300 396ba6bc97 fix(ci): always install Java regardless of SDK cache hit; harden release creation
Android Build / build-apk (push) Failing after 13s
Build and Deploy / build-and-push (push) Successful in 38s
Android Release / build-release-apk (push) Failing after 11s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v0.24.0
2026-05-14 10:11:42 -07:00
Gitea CI 88298206bb chore(deploy): bump image to 0f650311 [skip ci] 2026-05-14 17:11:05 +00:00
funman300 0f65031114 ci: add Android release workflow — sign and publish APK on version tag
Android Build / build-apk (push) Failing after 11s
Build and Deploy / build-and-push (push) Successful in 23s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 10:10:27 -07:00
funman300 c91ce9436e fix(deploy): copy classic theme assets into Docker runtime image
Build and Deploy / build-and-push (push) Failing after 27s
solitaire_engine/assets/themes/classic/ was absent from the container
because only the workspace-root assets/ directory was copied. The
AssetServer serves themes/classic/ from that same root, so the classic
theme manifested as a missing-asset load failure at runtime.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 23:00:43 -07:00
Gitea CI ace96b4a47 chore(deploy): bump image to ea079af9 [skip ci] 2026-05-14 05:58:01 +00:00
funman300 ea079af9e1 ci: add Android APK build workflow
Android Build / build-apk (push) Failing after 59s
Build and Deploy / build-and-push (push) Successful in 26s
Triggers on every master push that touches app/engine/asset code
(ignores deploy/, argocd/, solitaire_server/, *.md).

Three-layer cache strategy:
  1. Android SDK + NDK keyed by NDK + build-tools versions (~2 GB, stable)
  2. cargo-apk binary keyed by OS + toolchain (avoids recompiling the tool)
  3. Cargo registry + build artifacts keyed by Cargo.lock + SHA

Outputs a debug APK as a workflow artifact retained for 30 days.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 22:56:34 -07:00
Gitea CI c66d81c73a chore(deploy): bump image to 20b7a617 [skip ci] 2026-05-14 05:53:08 +00:00
funman300 20b7a617e0 feat(engine): rename themes — Classic is default, Dark replaces Default
Build and Deploy / build-and-push (push) Successful in 33s
- Rename assets/themes/default/ → assets/themes/dark/; update theme.ron
  id/name to "dark"/"Dark"
- Rename all DEFAULT_THEME_* constants → DARK_THEME_* and
  default_theme_svg_bytes / populate_embedded_default_theme → dark_*
- Add bundled_theme_url() helper for URL resolution without needing the
  registry (used by Startup systems where ordering isn't guaranteed)
- Registry now lists Classic first (new player default), Dark second
- settings.rs default_theme_id() returns "classic" so fresh installs
  start on the white card theme

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 22:52:44 -07:00
funman300 7a0d57b2b1 feat(engine): add Classic card theme
White/cream card faces with traditional red (hearts/diamonds) and black
(clubs/spades) colours, plus a navy diamond-pattern card back. Shipped
as a bundled AssetServer theme alongside the existing Default theme.

Registry updated to include the Classic entry; registry tests updated
to reflect the new BUNDLED_COUNT of 2.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 22:52:44 -07:00
Gitea CI 93ec4a7478 chore(deploy): bump image to 72dfd741 [skip ci] 2026-05-14 05:34:53 +00:00
funman300 72dfd741c4 fix(web): add Matomo tracking snippet to all pages
Build and Deploy / build-and-push (push) Successful in 4m10s
Only game.html had the snippet; the other five pages were missing it,
causing the Matomo installation verification check to fail.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 22:30:08 -07:00
funman300 3837a10b15 fix(deploy): use matomo.php for liveness/readiness probes
/index.php returns 302 after tables are created (installer redirect),
which fails k8s HTTP probes. /matomo.php is the tracker endpoint and
always returns 200 regardless of installation state. Also add
timeoutSeconds: 5 since PHP startup can exceed the 1s default.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 22:03:07 -07:00
funman300 574115cb71 fix(deploy): switch matomo to official image 5.10.0
bitnami/matomo was removed from Docker Hub (0 tags). Switch to the
official matomo:5.10.0 image; update port 8080→80, volume path to
/var/www/html, and env var names to match the official image schema.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 21:52:00 -07:00
Gitea CI 1707553790 chore(deploy): bump image to 6905f26b [skip ci] 2026-05-14 04:37:19 +00:00
funman300 6905f26b56 security: remove secrets from git, gitignore k8s secret files
Build and Deploy / build-and-push (push) Successful in 35s
Secrets committed in prior commits (matomo-secret.yaml,
secret-analytics-auth.yaml) have been scrubbed from history via
filter-branch — rotate those credentials immediately.

Going forward:
- deploy/*-secret.yaml is gitignored; apply manually with kubectl
- deploy/matomo-secret.yaml.example shows the required shape
- ArgoCD ignoreDifferences on matomo-secret prevents it pruning a
  manually-applied secret
- Remove matomo-secret.yaml from kustomization.yaml so ArgoCD never
  manages it again

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 21:36:46 -07:00
funman300 1b7c4d92aa fix(web): auto-complete now works with cards remaining in waste
check_auto_complete no longer requires the waste pile to be empty —
only the stock must be exhausted and all tableau cards face-up.
next_auto_complete_move checks the waste top card before scanning
tableau, and auto_complete_step falls back to draw() when no direct
foundation move is available so the waste drains automatically.

Fixes the end-game state where the player could see a clear win but
the auto-complete interval never fired because the waste was non-empty.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 21:30:46 -07:00
Gitea CI d685224ce6 chore(deploy): bump image to 3e006a1e [skip ci] 2026-05-14 04:14:55 +00:00
funman300 539779d78b feat(analytics): replace custom pipeline with Matomo
Removes the hand-rolled analytics endpoint and SQLite event table in favour
of Matomo — a self-hosted, full-featured analytics platform.

k8s:
- Deploy MariaDB 11 + Bitnami Matomo 5 in the solitaire namespace
- Route analytics.aleshym.co ingress to the Matomo service
- Remove Datasette sidecar and its BasicAuth middleware/secret
- Remove the analytics port from the solitaire-server Service

Rust:
- Replace AnalyticsClient (custom HTTP endpoint) with MatomoClient (Matomo
  HTTP Tracking API bulk endpoint); maps game events to Matomo categories
- Add matomo_url + matomo_site_id fields to Settings (serde default → None/1)
- Privacy toggle in Settings now activates when matomo_url is set (not tied
  to SyncBackend::SolitaireServer)
- Remove POST /api/analytics route from solitaire_server

Web:
- Add Matomo JS tracking snippet to game.html (/play page)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 21:10:15 -07:00
funman300 f6506c57e5 feat(deploy): Datasette analytics sidecar + analytics.aleshym.co ingress
Adds a Datasette container alongside the existing server in the same pod so
it can read the SQLite PVC without a second ReadWriteOnce mount. Protected
by a Traefik BasicAuth middleware at analytics.aleshym.co.

Also fixes the ArgoCD repoURL to point to the migrated Gitea hostname
(git.aleshym.co) instead of the old bare IP.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 20:17:20 -07:00
Gitea CI b88f3df119 chore(deploy): bump image to 3cec200a [skip ci] 2026-05-14 03:10:52 +00:00
funman300 0dcb783e94 feat(analytics): opt-in usage analytics with server ingest and settings toggle
- Server: POST /api/analytics endpoint with per-IP rate limit (5/min),
  batch validation (≤50 events, event_type regex, UUID dedup, clock check),
  INSERT OR IGNORE for idempotency, and migration 004_analytics.sql
- Client (solitaire_data): AnalyticsClient with in-memory Mutex buffer,
  UUID session_id per launch, async flush via background task
- Engine: AnalyticsPlugin records game_won, game_forfeit, game_start,
  achievement_unlocked; flushes immediately on game-end, every 60 s otherwise
- Settings UI: Privacy section with ON/OFF toggle, hidden in local-only mode
- Default: analytics_enabled = false (explicit opt-in required)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 20:06:34 -07:00
Gitea CI ea17f94b6c chore(deploy): bump image to 09fcd209 [skip ci] 2026-05-14 02:43:38 +00:00