Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release-fast.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
reddb_version:
description: "Pinned RedDB release tag to smoke-package with"
required: true
default: "v1.11.0"
default: "v1.13.1"

permissions:
contents: read
Expand Down
13 changes: 8 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ concurrency:

env:
# RedDB sidecar pinned for reproducible builds — bump when adopting a newer reddb.
# v1.13.0-rc.12: persists collection contracts (declared_model) in the single-file
# artifact, so KV collections survive a server restart (reddb fix a8139467). v1.11.0
# lost the model on reopen → "model mismatch: expected kv, got table" on every project
# reopen. Bump to v1.13.0 once reddb publishes that tag's release binaries.
REDDB_VERSION: v1.13.0-rc.12
# v1.13.1: first stable to publish the fully *static* (musl) `red-linux-<arch>-static`
# assets, which fetch-reddb.mjs now prefers. The dynamic `red-linux-x86_64` links the
# build host's glibc and fails to start on older distros ("GLIBC_2.39 not found") → the
# reddb sidecar crash-loops and the app hangs on a black/loading screen. The static build
# runs on any glibc. v1.13.x also persists collection contracts (declared_model) so KV
# collections survive a server restart (reddb fix a8139467); v1.11.0 lost the model on
# reopen → "model mismatch: expected kv, got table".
REDDB_VERSION: v1.13.1
# Run AppImage tooling (linuxdeploy) without FUSE, which CI runners lack.
APPIMAGE_EXTRACT_AND_RUN: "1"
# linuxdeploy's strip pass chokes on some shared objects under the no-FUSE extract path
Expand Down
27 changes: 20 additions & 7 deletions scripts/check-reddb-release-assets.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@
// The desktop app cannot be packaged for Linux/Windows unless the pinned RedDB
// release exposes the prebuilt `red-<os>-<arch>` assets that fetch-reddb.mjs
// downloads. Check that up front so release jobs fail before runner setup,
// dependency install, and Tauri packaging work.
// dependency install, and Tauri packaging work. Mirrors fetch-reddb.mjs's
// candidate logic: linux x86_64/aarch64 prefer the static (musl) `-static` asset
// and fall back to the glibc one, so the preflight passes iff the fetch will.
//
// REDDB_VERSION=v1.11.0 node scripts/check-reddb-release-assets.mjs \
// x86_64-unknown-linux-gnu x86_64-pc-windows-msvc
import { env, exit } from "node:process";

const REPO = "reddb-io/reddb";

function assetName(triple) {
// Candidate asset names for this triple in preference order (see fetch-reddb.mjs).
function assetCandidates(triple) {
const [arch] = triple.split("-");
const os = triple.includes("linux")
? "linux"
Expand All @@ -23,7 +26,10 @@ function assetName(triple) {
: null;
if (!os) throw new Error(`unsupported target triple: ${triple}`);
const ext = os === "windows" ? ".exe" : "";
return `red-${os}-${arch}${ext}`;
const glibc = `red-${os}-${arch}${ext}`;
const preferStatic =
os === "linux" && (arch === "x86_64" || arch === "aarch64");
return preferStatic ? [`red-${os}-${arch}-static`, glibc] : [glibc];
}

async function ghJson(path) {
Expand Down Expand Up @@ -52,7 +58,6 @@ if (targets.length === 0) {
exit(2);
}

const required = targets.map(assetName);
const tag = env.REDDB_VERSION;

let release;
Expand All @@ -69,19 +74,27 @@ try {
}

const available = new Set((release.assets ?? []).map((asset) => asset.name));
const missing = required.filter((name) => !available.has(name));
// Each target is satisfied if ANY of its candidates is published; record the one
// fetch-reddb.mjs would actually download (the first available, static-preferred).
const resolved = targets.map((triple) => {
const names = assetCandidates(triple);
return { triple, names, chosen: names.find((n) => available.has(n)) ?? null };
});
const missing = resolved.filter((r) => r.chosen === null);

if (missing.length > 0) {
console.error(
`RedDB ${release.tag_name} is missing required release assets:`
);
for (const name of missing) console.error(` - ${name}`);
for (const { triple, names } of missing) {
console.error(` - ${triple} (need one of: ${names.join(", ")})`);
}
console.error("");
console.error("Available assets:");
for (const name of [...available].sort()) console.error(` - ${name}`);
exit(1);
}

console.log(
`RedDB ${release.tag_name} has required assets: ${required.join(", ")}`
`RedDB ${release.tag_name} has required assets: ${resolved.map((r) => r.chosen).join(", ")}`
);
39 changes: 34 additions & 5 deletions scripts/fetch-reddb.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ function hostTriple() {
return `${a}-unknown-linux-gnu`;
}

function assetName(triple) {
// Candidate asset names for this triple, in preference order. Linux x86_64/aarch64 ship a
// fully *static* (musl) `red` as `<asset>-static`; prefer it. The dynamic `red-linux-<arch>`
// links the build host's glibc, so it fails to start on any host with an older glibc
// ("GLIBC_2.xx not found") — which black-screens the desktop app (the reddb sidecar
// crash-loops, the UI waits on it forever). The static build runs on any glibc. Fall back to
// the glibc asset for older reddb releases that predate the static one. Mirrors install.sh.
function assetCandidates(triple) {
const [arch] = triple.split("-");
const os = triple.includes("linux")
? "linux"
Expand All @@ -52,7 +58,11 @@ function assetName(triple) {
: null;
if (!os) throw new Error(`Unsupported target triple: ${triple}`);
const ext = os === "windows" ? ".exe" : "";
return { name: `red-${os}-${arch}${ext}`, ext, os };
const glibc = `red-${os}-${arch}${ext}`;
// The static variant is published only for the linux x86_64 / aarch64 sidecars.
const preferStatic = os === "linux" && (arch === "x86_64" || arch === "aarch64");
const names = preferStatic ? [`red-${os}-${arch}-static`, glibc] : [glibc];
return { names, ext, os };
}

async function ghJson(url) {
Expand All @@ -74,7 +84,7 @@ async function download(url) {
}

const triple = hostTriple();
const { name, ext, os } = assetName(triple);
const { names, ext, os } = assetCandidates(triple);

const tag =
process.env.REDDB_VERSION ||
Expand All @@ -83,8 +93,27 @@ const tag =
if (!tag) throw new Error("could not determine a reddb release tag");

const base = `https://github.com/${REPO}/releases/download/${tag}`;
console.log(`Fetching RedDB ${name} from ${REPO}@${tag} …`);
const bin = await download(`${base}/${name}`);

// Download the first candidate that exists. Fall back to the next ONLY on a 404 (asset not
// published in this release) — a real network/auth error still propagates instead of being
// masked by a fallback that would also fail.
let name, bin;
for (let i = 0; i < names.length; i++) {
const candidate = names[i];
console.log(`Fetching RedDB ${candidate} from ${REPO}@${tag} …`);
try {
bin = await download(`${base}/${candidate}`);
name = candidate;
break;
} catch (e) {
const last = i === names.length - 1;
if (String(e).includes("→ 404") && !last) {
console.log(` (${candidate} not published in ${tag} — trying ${names[i + 1]})`);
continue;
}
throw e;
}
}

// Verify the published .sha256 sidecar when present (best-effort). Pull the hash out by
// regex so we don't care about the format: `<hash> file` (sha256sum), `SHA256(file)= <hash>`
Expand Down