diff --git a/.github/workflows/sde-update.yml b/.github/workflows/sde-update.yml index 7e6fe7f..3cb0a8a 100644 --- a/.github/workflows/sde-update.yml +++ b/.github/workflows/sde-update.yml @@ -116,6 +116,38 @@ jobs: set -euo pipefail gh release download "$NEW_TAG" -R EX-CT/EXFA-Data --pattern 'dataset-*.json.gz' -D _data echo "EXFA_DATASET=$(ls $PWD/_data/dataset-*.json.gz | head -1)" >> "$GITHUB_ENV" + - name: Refresh embedded price snapshot (its sde_build stamp should match this build) + # EXFA-Data's sde.yml produces a snapshot on this SDE right after the dataset release, so the newest + # prices-* tag normally carries the same sde_build. If it doesn't (snapshot failed / not published + # yet) embed it anyway โ€” freshest prices beat a stale file; the engine just warns at runtime. + run: | + set -euo pipefail + B=${NEW_TAG#sde-}; B=${B%%-*} + PTAG=$(gh release list -R EX-CT/EXFA-Data --json tagName --jq '[.[] | select(.tagName | startswith("prices-"))][0].tagName') + echo "price snapshot release: ${PTAG:-}" + [ -z "$PTAG" ] && { echo "::warning::no prices-* release in EXFA-Data โ€” keeping the current embedded snapshot"; exit 0; } + gh release download "$PTAG" -R EX-CT/EXFA-Data -D _prices -p 'prices-*.json.gz' + python3 - "$(ls _prices/prices-*.json.gz | head -1)" "$B" <<'EOF' + import gzip, json, re, sys, pathlib + f, want_build = sys.argv[1], int(sys.argv[2]) + s = json.loads(gzip.decompress(pathlib.Path(f).read_bytes())) + sid, mtime, chash, ntypes = s["snapshot_id"], s["market_time"], s["content_hash"], s["type_count"] + data = pathlib.Path("crates/exfa-core/data") + for old in data.glob("prices-*.json.gz"): + old.unlink() + dest = data / f"prices-{sid}.json.gz" + dest.write_bytes(pathlib.Path(f).read_bytes()) + p = pathlib.Path("crates/exfa-core/src/price.rs"); t = p.read_text(encoding="utf-8") + t = re.sub(r'include_bytes!\("\.\./data/prices-[^"]+"\)', f'include_bytes!("../data/{dest.name}")', t) + t = re.sub(r'EMBEDDED_ID: &str = "[^"]+"', f'EMBEDDED_ID: &str = "{sid}"', t) + t = re.sub(r'EMBEDDED_TIME: &str = "[^"]+"', f'EMBEDDED_TIME: &str = "{mtime}"', t) + t = re.sub(r'EMBEDDED_HASH: &str = "[^"]+"', f'EMBEDDED_HASH: &str = "{chash}"', t) + t = re.sub(r'EMBEDDED_TYPES: usize = \d+', f'EMBEDDED_TYPES: usize = {ntypes}', t) + p.write_text(t, encoding="utf-8") + print(f"embedded snapshot -> {sid} ({ntypes} types, sde_build {s.get('sde_build')}, market_time {mtime})") + if s.get("sde_build") != want_build: + print(f"::warning::snapshot sde_build {s.get('sde_build')} != dataset build {want_build} โ€” embedded anyway (freshest available)") + EOF - name: sde.lock + version bump + rebuild id: b env: @@ -156,7 +188,7 @@ jobs: set -euo pipefail git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add sde.lock bench.lock Cargo.toml Cargo.lock ci/round1.sha256 ci/round1-base.sha256 + git add sde.lock bench.lock Cargo.toml Cargo.lock ci/round1.sha256 ci/round1-base.sha256 crates/exfa-core/data crates/exfa-core/src/price.rs crates/exfa-core/tests/batch_prices.rs git commit -m "Update SDE to $NEW_TAG" git push origin main git tag "$TAG_OUT" diff --git a/ci/round1.sha256 b/ci/round1.sha256 index 34d4c8e..cd0fff3 100644 --- a/ci/round1.sha256 +++ b/ci/round1.sha256 @@ -1 +1 @@ -ac3016579fb59487ca8548fe5bab4b25055e9db6fd56f493e3cae7b6b24fe8b5 +de9e5d28a2a7b81d26ba0daf05b1519b0364aa94a90dcd6086b75d451b754916 diff --git a/crates/exfa-core/data/prices-jita44-20261003T070857Z.json.gz b/crates/exfa-core/data/prices-jita44-20261003T070857Z.json.gz deleted file mode 100644 index 1841bd3..0000000 Binary files a/crates/exfa-core/data/prices-jita44-20261003T070857Z.json.gz and /dev/null differ diff --git a/crates/exfa-core/data/prices-jita44-20261008T063509Z.json.gz b/crates/exfa-core/data/prices-jita44-20261008T063509Z.json.gz new file mode 100644 index 0000000..ca1ae8a Binary files /dev/null and b/crates/exfa-core/data/prices-jita44-20261008T063509Z.json.gz differ diff --git a/crates/exfa-core/src/price.rs b/crates/exfa-core/src/price.rs index 8f44f82..5a8a9a2 100644 --- a/crates/exfa-core/src/price.rs +++ b/crates/exfa-core/src/price.rs @@ -33,11 +33,12 @@ pub struct Market { static MARKET: RwLock>> = RwLock::new(None); /// Embedded release snapshot (docs/22 ยง3.1): eve-market-prices `prices-jita44-20261003T070857Z`. -pub const EMBEDDED_SNAPSHOT: &[u8] = include_bytes!("../data/prices-jita44-20261003T070857Z.json.gz"); +pub const EMBEDDED_SNAPSHOT: &[u8] = include_bytes!("../data/prices-jita44-20261008T063509Z.json.gz"); /// Identity of the embedded snapshot, for provenance without parsing it (checked by a test against the bytes). -pub const EMBEDDED_ID: &str = "jita44-20261003T070857Z"; -pub const EMBEDDED_TIME: &str = "2026-10-03T07:08:57Z"; -pub const EMBEDDED_HASH: &str = "sha256:279683ddd539f0577589d9f88759627244cf2b7c7488755fcf409ffa007a7f3b"; +pub const EMBEDDED_ID: &str = "jita44-20261008T063509Z"; +pub const EMBEDDED_TIME: &str = "2026-10-08T06:35:09Z"; +pub const EMBEDDED_HASH: &str = "sha256:4476764c07843738b8937cf5a41fc8df36f0c3daf6f22a4e1fbd13817e990a7e"; +pub const EMBEDDED_TYPES: usize = 9076; static EMBEDDED: std::sync::OnceLock>> = std::sync::OnceLock::new(); pub fn embedded() -> Option> { diff --git a/crates/exfa-core/tests/batch_prices.rs b/crates/exfa-core/tests/batch_prices.rs index a9893f5..19f37a4 100644 --- a/crates/exfa-core/tests/batch_prices.rs +++ b/crates/exfa-core/tests/batch_prices.rs @@ -186,7 +186,7 @@ fn embedded_snapshot_identity_and_jcs() { assert_eq!(m.time.as_deref(), Some(exfa_core::price::EMBEDDED_TIME)); assert_eq!(m.hash.as_deref(), Some(exfa_core::price::EMBEDDED_HASH)); // every entry passes the d22/README rule invariants (half-even cents, clamp, 12-digit band_max, p0 > 0) - assert_eq!(m.isk.len(), 9178); + assert_eq!(m.isk.len(), exfa_core::price::EMBEDDED_TYPES); use exfa_core::price::entry_violation as ev; assert!(ev(4.2, 4.0, 4.2, Some(0.05), true).is_none()); assert!(ev(4.21, 4.0, 4.2, Some(0.05), true).is_some()); // above band_max: not clamped