Skip to content

Commit e19b536

Browse files
committed
fix(release): restore packaged sidecar for Linux
1 parent a9877e3 commit e19b536

7 files changed

Lines changed: 150 additions & 12 deletions

File tree

.github/workflows/release.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ jobs:
7979
- name: Build sidecar artifacts
8080
run: bash ./scripts/build-sidecar.sh
8181

82+
- name: Smoke test sidecar
83+
run: node ./scripts/smoke-test-sidecar.mjs
84+
8285
- name: Build desktop
8386
run: |
8487
set -euo pipefail

apps/desktop/src-tauri/tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://schema.tauri.app/config/2",
33
"productName": "OpenLinear",
4-
"version": "0.1.35",
4+
"version": "0.1.36",
55
"identifier": "com.openlinear.app",
66
"build": {
77
"beforeDevCommand": "PORT=3000 pnpm --filter @openlinear/desktop-ui dev",

packages/openlinear/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "openlinear",
3-
"version": "0.1.35",
3+
"version": "0.1.36",
44
"description": "OpenLinear launcher, installer, and validation utilities",
55
"license": "MIT",
66
"repository": {

packaging/aur/openlinear-bin/.SRCINFO

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
pkgbase = openlinear-bin
22
pkgdesc = AI-powered project management that actually writes the code — desktop app
3-
pkgver = 0.1.35
3+
pkgver = 0.1.36
44
pkgrel = 1
55
url = https://github.com/kaizen403/openlinear
66
arch = x86_64
@@ -14,9 +14,9 @@ pkgbase = openlinear-bin
1414
conflicts = openlinear
1515
options = !strip
1616
options = !debug
17-
source = openlinear-0.1.35-x86_64.AppImage::https://github.com/kaizen403/openlinear/releases/download/v0.1.35/openlinear-0.1.35-x86_64.AppImage
17+
source = openlinear-0.1.36-x86_64.AppImage::https://github.com/kaizen403/openlinear/releases/download/v0.1.36/openlinear-0.1.36-x86_64.AppImage
1818
source = openlinear.desktop
19-
source = openlinear.png::https://raw.githubusercontent.com/kaizen403/openlinear/v0.1.35/apps/desktop/src-tauri/icons/icon.png
19+
source = openlinear.png::https://raw.githubusercontent.com/kaizen403/openlinear/v0.1.36/apps/desktop/src-tauri/icons/icon.png
2020
sha256sums = SKIP
2121
sha256sums = SKIP
2222
sha256sums = SKIP

packaging/aur/openlinear-bin/PKGBUILD

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Maintainer: kaizen403 <kaizen403@proton.me>
22
pkgname=openlinear-bin
3-
pkgver=0.1.35
3+
pkgver=0.1.36
44
pkgrel=1
55
pkgdesc="AI-powered project management that actually writes the code — desktop app"
66
arch=('x86_64')

scripts/build-sidecar.sh

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
55
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
66
SIDECAR_DIR="$ROOT_DIR/apps/sidecar"
77
BINARIES_DIR="$ROOT_DIR/apps/desktop/src-tauri/binaries"
8+
PRISMA_CLIENT="$ROOT_DIR/packages/db/generated/prisma/client"
89
SKIP_OPENCODE_DOWNLOAD="${OPENLINEAR_SKIP_OPENCODE_DOWNLOAD:-0}"
910

1011
OS="$(uname -s)"
@@ -18,31 +19,50 @@ pnpm --filter @openlinear/db db:generate
1819
echo "==> Building TypeScript..."
1920
pnpm --filter @openlinear/sidecar build
2021

21-
echo "==> Bundling with esbuild (ESM -> CJS)..."
22+
echo "==> Bundling sidecar entrypoint..."
2223
cd "$SIDECAR_DIR"
2324
npx esbuild src/index.ts \
2425
--bundle \
2526
--platform=node \
2627
--target=node18 \
27-
--outfile=dist/sidecar-entry.cjs \
28+
--outfile=dist/bundle.cjs \
2829
--format=cjs \
2930
'--define:import.meta.dirname=""'
3031

32+
echo "==> Copying Prisma runtime assets..."
33+
if [ -f "$PRISMA_CLIENT/schema.prisma" ]; then
34+
cp "$PRISMA_CLIENT/schema.prisma" dist/
35+
echo " - schema.prisma"
36+
fi
37+
38+
for f in \
39+
"query_compiler_fast_bg.wasm" \
40+
"query_compiler_fast_bg.wasm-base64.js" \
41+
"index.js" \
42+
"runtime/client.js"; do
43+
src="$PRISMA_CLIENT/$f"
44+
if [ -f "$src" ]; then
45+
mkdir -p "dist/$(dirname "$f")"
46+
cp "$src" "dist/$f"
47+
echo " - $f"
48+
fi
49+
done
50+
3151
case "$OS" in
3252
Darwin)
3353
echo "==> Building macOS binary with pkg..."
3454
if [ "$ARCH" = "arm64" ]; then
35-
npx @yao-pkg/pkg dist/sidecar-entry.cjs --target node18-macos-arm64 --output dist/sidecar-macos-arm64
55+
npx @yao-pkg/pkg dist/bundle.cjs --target node18-macos-arm64 --output dist/sidecar-macos-arm64
3656
else
37-
npx @yao-pkg/pkg dist/sidecar-entry.cjs --target node18-macos-x64 --output dist/sidecar-macos-x64
57+
npx @yao-pkg/pkg dist/bundle.cjs --target node18-macos-x64 --output dist/sidecar-macos-x64
3858
fi
3959
;;
4060
Linux)
4161
echo "==> Building Linux binary with pkg..."
4262
if [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then
43-
npx @yao-pkg/pkg dist/sidecar-entry.cjs --target node18-linux-arm64 --output dist/sidecar-linux-arm64
63+
npx @yao-pkg/pkg dist/bundle.cjs --target node18-linux-arm64 --output dist/sidecar-linux-arm64
4464
elif [ "$ARCH" = "x86_64" ]; then
45-
npx @yao-pkg/pkg dist/sidecar-entry.cjs --target node18-linux-x64 --output dist/sidecar-linux-x64
65+
npx @yao-pkg/pkg dist/bundle.cjs --target node18-linux-x64 --output dist/sidecar-linux-x64
4666
else
4767
echo "==> Unsupported Linux architecture: $ARCH"
4868
exit 1

scripts/smoke-test-sidecar.mjs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#!/usr/bin/env node
2+
3+
import { spawn } from "node:child_process";
4+
import { constants as fsConstants } from "node:fs";
5+
import { access } from "node:fs/promises";
6+
import path from "node:path";
7+
import process from "node:process";
8+
import { fileURLToPath } from "node:url";
9+
10+
const ROOT_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
11+
12+
function resolveBinaryPath() {
13+
if (process.platform === "linux") {
14+
if (process.arch === "x64") {
15+
return path.join(
16+
ROOT_DIR,
17+
"apps/desktop/src-tauri/binaries/openlinear-sidecar-x86_64-unknown-linux-gnu",
18+
);
19+
}
20+
21+
if (process.arch === "arm64") {
22+
return path.join(
23+
ROOT_DIR,
24+
"apps/desktop/src-tauri/binaries/openlinear-sidecar-aarch64-unknown-linux-gnu",
25+
);
26+
}
27+
}
28+
29+
if (process.platform === "darwin") {
30+
if (process.arch === "x64") {
31+
return path.join(
32+
ROOT_DIR,
33+
"apps/desktop/src-tauri/binaries/openlinear-sidecar-x86_64-apple-darwin",
34+
);
35+
}
36+
37+
if (process.arch === "arm64") {
38+
return path.join(
39+
ROOT_DIR,
40+
"apps/desktop/src-tauri/binaries/openlinear-sidecar-aarch64-apple-darwin",
41+
);
42+
}
43+
}
44+
45+
throw new Error(`Unsupported smoke test platform: ${process.platform}/${process.arch}`);
46+
}
47+
48+
function wait(ms) {
49+
return new Promise((resolve) => setTimeout(resolve, ms));
50+
}
51+
52+
async function main() {
53+
const binaryPath = resolveBinaryPath();
54+
await access(binaryPath, fsConstants.X_OK);
55+
56+
const child = spawn(binaryPath, [], {
57+
cwd: ROOT_DIR,
58+
env: { ...process.env },
59+
stdio: ["ignore", "pipe", "pipe"],
60+
});
61+
62+
let output = "";
63+
let ready = false;
64+
let exitCode = null;
65+
let spawnError = null;
66+
67+
const appendOutput = (chunk) => {
68+
const text = chunk.toString();
69+
output += text;
70+
process.stdout.write(text);
71+
72+
if (output.includes("Server running on http://localhost:3001")) {
73+
ready = true;
74+
}
75+
};
76+
77+
child.stdout.on("data", appendOutput);
78+
child.stderr.on("data", appendOutput);
79+
80+
child.on("exit", (code) => {
81+
exitCode = code;
82+
});
83+
84+
child.on("error", (error) => {
85+
spawnError = error;
86+
});
87+
88+
const deadline = Date.now() + 15000;
89+
while (!ready && exitCode === null && !spawnError && Date.now() < deadline) {
90+
await wait(200);
91+
}
92+
93+
if (!ready) {
94+
if (exitCode === null) {
95+
child.kill("SIGTERM");
96+
await wait(500);
97+
}
98+
99+
if (spawnError) {
100+
throw spawnError;
101+
}
102+
103+
throw new Error(
104+
`Sidecar smoke test failed before readiness. Exit code: ${exitCode ?? "still running"}\n${output}`,
105+
);
106+
}
107+
108+
child.kill("SIGTERM");
109+
await wait(1000);
110+
}
111+
112+
main().catch((error) => {
113+
console.error(error.message || String(error));
114+
process.exit(1);
115+
});

0 commit comments

Comments
 (0)