chore: rename app from Solitaire Quest to Ferrous Solitaire
Build and Deploy / build-and-push (push) Successful in 4m40s

Updates all in-tree references:
- Android package: com.solitairequest.app → com.ferrousapp.solitaire
- APK name: solitaire-quest → ferrous-solitaire
- Data dir: solitaire_quest → ferrous_solitaire (across all 6 data modules + engine)
- Keyring service: solitaire_quest_server → ferrous_solitaire_server
- Android Keystore key: solitaire_quest_token_key → ferrous_solitaire_token_key
- Gitea repo: Rusty_Solitare → Ferrous-Solitaire (also fixes "Solitare" typo)
- Renamed pkg/solitaire-quest* → pkg/ferrous-solitaire*
- Updated ArgoCD, docker-compose, CI workflow, build script, all docs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-05-14 19:23:49 -07:00
parent d105fee319
commit d761a150d7
31 changed files with 109 additions and 109 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ use std::path::{Path, PathBuf};
pub use solitaire_sync::AchievementRecord;
const APP_DIR_NAME: &str = "solitaire_quest";
const APP_DIR_NAME: &str = "ferrous_solitaire";
const FILE_NAME: &str = "achievements.json";
/// Platform-specific default path for `achievements.json`.
+1 -1
View File
@@ -19,7 +19,7 @@ use std::path::PathBuf;
use crate::auth_tokens::TokenError;
const KEY_ALIAS: &str = "solitaire_quest_token_key";
const KEY_ALIAS: &str = "ferrous_solitaire_token_key";
#[derive(Serialize, Deserialize)]
struct TokenBlob {
+2 -2
View File
@@ -1,6 +1,6 @@
//! Secure storage for JWT access and refresh tokens using the OS keychain.
//!
//! Tokens are stored under service name `"solitaire_quest_server"` with entry
//! Tokens are stored under service name `"ferrous_solitaire_server"` with entry
//! keys `"{username}_access"` and `"{username}_refresh"`.
//!
//! On Linux this requires a running secret service (GNOME Keyring / KWallet).
@@ -46,7 +46,7 @@ pub enum TokenError {
/// Service name used to namespace all keychain entries for this application.
#[cfg(not(target_os = "android"))]
const SERVICE: &str = "solitaire_quest_server";
const SERVICE: &str = "ferrous_solitaire_server";
/// Map a `keyring_core::Error` to the appropriate `TokenError`.
#[cfg(not(target_os = "android"))]
+7 -7
View File
@@ -3,7 +3,7 @@
//! The rest of `solitaire_data` (settings, stats, achievements,
//! replays, progress, game state) and the engine's user-themes
//! discovery all need a base path under which to nest
//! `solitaire_quest/<file>`. On desktop the right answer is
//! `ferrous_solitaire/<file>`. On desktop the right answer is
//! `dirs::data_dir()` (which resolves to platform-appropriate
//! locations: `~/.local/share` on Linux, `~/Library/Application
//! Support` on macOS, `%APPDATA%` on Windows). On Android the
@@ -12,9 +12,9 @@
//!
//! [`data_dir`] is a thin shim that returns the right base path
//! per target. Callers continue to append
//! `solitaire_quest/<file>` themselves, so the on-disk layout is
//! `ferrous_solitaire/<file>` themselves, so the on-disk layout is
//! identical across platforms (the per-app Android sandbox makes
//! the extra `solitaire_quest/` segment harmless, and a `tar`
//! the extra `ferrous_solitaire/` segment harmless, and a `tar`
//! export from one platform deserialises cleanly on another).
//!
//! # Why hardcode on Android?
@@ -24,7 +24,7 @@
//! `AndroidApp` context through Bevy's startup hooks and a
//! per-call JNI bridge — meaningfully more code than the
//! sandbox-guaranteed `/data/data/<package>/files` path. The
//! package name `com.solitairequest.app` is fixed at compile
//! package name `com.ferrousapp.solitaire` is fixed at compile
//! time in `solitaire_app/Cargo.toml`'s
//! `[package.metadata.android]` block, so a hardcoded path is
//! safe until that ever changes (at which point this constant
@@ -40,14 +40,14 @@ use std::path::PathBuf;
/// constant and the Cargo metadata together if the package id
/// ever changes.
#[cfg(target_os = "android")]
const ANDROID_APP_FILES_DIR: &str = "/data/data/com.solitairequest.app/files";
const ANDROID_APP_FILES_DIR: &str = "/data/data/com.ferrousapp.solitaire/files";
/// Returns the per-user data directory for the current target,
/// or `None` if the platform doesn't expose one (rare; usually
/// indicates a broken `$HOME` or `$XDG_*` configuration on a
/// minimal Linux container).
///
/// Callers append `solitaire_quest/<file>` themselves. See the
/// Callers append `ferrous_solitaire/<file>` themselves. See the
/// module-level doc comment for the per-platform behaviour and
/// why Android uses a hardcoded path.
pub fn data_dir() -> Option<PathBuf> {
@@ -87,6 +87,6 @@ mod tests {
#[test]
fn data_dir_returns_sandbox_path_on_android() {
let dir = data_dir().expect("android must report a data dir");
assert_eq!(dir, PathBuf::from("/data/data/com.solitairequest.app/files"));
assert_eq!(dir, PathBuf::from("/data/data/com.ferrousapp.solitaire/files"));
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ use chrono::{Datelike, NaiveDate};
pub use solitaire_sync::progress::level_for_xp;
pub use solitaire_sync::PlayerProgress;
const APP_DIR_NAME: &str = "solitaire_quest";
const APP_DIR_NAME: &str = "ferrous_solitaire";
const FILE_NAME: &str = "progress.json";
/// Deterministic seed derived from a date, identical for all players globally.
+3 -3
View File
@@ -1,7 +1,7 @@
//! Win-game replay recording + storage.
//!
//! When a player wins, the engine freezes the in-memory recording into a
//! [`Replay`] and persists it to `<data_dir>/solitaire_quest/latest_replay.json`
//! [`Replay`] and persists it to `<data_dir>/ferrous_solitaire/latest_replay.json`
//! via [`save_latest_replay_to`]. The Stats screen offers a "Watch replay"
//! action that loads it via [`load_latest_replay_from`] so the player can
//! revisit (or, in a future build, watch the engine re-execute) the path
@@ -29,7 +29,7 @@ use serde::{Deserialize, Serialize};
use solitaire_core::game_state::{DrawMode, GameMode};
use solitaire_core::pile::PileType;
const APP_DIR_NAME: &str = "solitaire_quest";
const APP_DIR_NAME: &str = "ferrous_solitaire";
const LATEST_REPLAY_FILE_NAME: &str = "latest_replay.json";
const REPLAY_HISTORY_FILE_NAME: &str = "replays.json";
@@ -221,7 +221,7 @@ impl Replay {
/// Rolling history of the player's most recent winning replays.
///
/// Stored as a single JSON file at
/// `<data_dir>/solitaire_quest/replays.json` (see
/// `<data_dir>/ferrous_solitaire/replays.json` (see
/// [`replay_history_path`]). Capped at [`REPLAY_HISTORY_CAP`] entries —
/// when [`append_replay_to_history`] pushes past the cap, the oldest
/// entry is dropped so the file never grows unbounded.
+1 -1
View File
@@ -11,7 +11,7 @@ use std::path::{Path, PathBuf};
use serde::{Deserialize, Serialize};
use solitaire_core::game_state::{DifficultyLevel, DrawMode};
const APP_DIR_NAME: &str = "solitaire_quest";
const APP_DIR_NAME: &str = "ferrous_solitaire";
const SETTINGS_FILE_NAME: &str = "settings.json";
/// Animation playback speed for card transitions.
+1 -1
View File
@@ -13,7 +13,7 @@ use solitaire_core::game_state::{GameState, GAME_STATE_SCHEMA_VERSION};
use crate::stats::StatsSnapshot;
const APP_DIR_NAME: &str = "solitaire_quest";
const APP_DIR_NAME: &str = "ferrous_solitaire";
const STATS_FILE_NAME: &str = "stats.json";
const GAME_STATE_FILE_NAME: &str = "game_state.json";
const TIME_ATTACK_SESSION_FILE_NAME: &str = "time_attack_session.json";