Skip to content
Closed
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
48 changes: 47 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ on:
- "tests/**"
- "scripts/**"
- "app/**"
- "desktop/**"
- "gui/**"
- "assets/**"
- ".gitattributes"
Expand Down Expand Up @@ -215,6 +216,7 @@ jobs:
- 'tests/**'
- 'scripts/**'
- 'app/**'
- 'desktop/**'
- 'gui/**'
- 'assets/**'
- '.gitattributes'
Expand Down Expand Up @@ -1175,14 +1177,55 @@ jobs:
- name: Build macOS menu bar app
run: bun run build:macos

desktop-shell:
name: desktop shell
needs: [changes, gates]
if: github.event_name != 'pull_request' || needs.changes.outputs.ci == 'true'
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: false

- name: Install Tauri Linux dependencies
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf

- name: Setup Rust
uses: dtolnay/rust-toolchain@02cb101ec7c40f2c49e1d9714d64511d8e1b74de # master
with:
toolchain: stable
components: rustfmt, clippy

- name: Prepare desktop check resources
run: |
set -euo pipefail
triple="$(rustc -vV | sed -n 's/^host: //p')"
mkdir -p desktop/src-tauri/binaries desktop/src-tauri/resources/gui/dist
: > "desktop/src-tauri/binaries/ocx-${triple}"
chmod +x "desktop/src-tauri/binaries/ocx-${triple}"
: > desktop/src-tauri/resources/gui/dist/.keep

- name: Check Rust formatting
run: cargo fmt --manifest-path desktop/src-tauri/Cargo.toml --check

- name: Run Rust clippy
run: cargo clippy --manifest-path desktop/src-tauri/Cargo.toml --all-targets -- -D warnings

- name: Run Rust tests
run: cargo test --manifest-path desktop/src-tauri/Cargo.toml

ci:
name: ci
if: always()
# Every producer, including the ones that only feed other jobs. `needs` holds
# direct dependencies only, so a failing `select-windows-runner` would
# otherwise reach this gate as nothing at all while its dependents report
# `skipped`, which is the shape the step below is written to catch.
needs: [changes, select-windows-runner, test, storage-policy, api-usage, gates, platform-macos, macos-control, platform-windows, keyring-smoke, docker-smoke, docs-site-build, structure-gate, npm-global-smoke, macos-app]
needs: [changes, select-windows-runner, test, storage-policy, api-usage, gates, platform-macos, macos-control, platform-windows, keyring-smoke, docker-smoke, docs-site-build, structure-gate, npm-global-smoke, macos-app, desktop-shell]
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
Expand Down Expand Up @@ -1249,12 +1292,15 @@ jobs:
GATED_JOBS="$GATED_JOBS platform-macos keyring-smoke docker-smoke npm-global-smoke"
GATED_JOBS="$GATED_JOBS macos-control platform-windows docs-site-build"
GATED_JOBS="$GATED_JOBS structure-gate macos-app"
GATED_JOBS="$GATED_JOBS desktop-shell"

expected_for() {
case "$1" in
changes|select-windows-runner) echo requested ;;
test|storage-policy|api-usage|gates|platform-macos|keyring-smoke|docker-smoke|macos-app)
echo "$scoped" ;;
desktop-shell)
echo "$scoped" ;;
npm-global-smoke) echo "$packaging" ;;
docs-site-build) echo "$docs" ;;
structure-gate) echo "$structure" ;;
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,7 @@ go/
native/**/target/
dist/macos/
dist/release/
desktop/src-tauri/binaries/
desktop/src-tauri/resources/
desktop/src-tauri/gen/
desktop/src-tauri/target/
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Bun-native TypeScript with no separate server compile step.
gone, and on a new `src/` area nobody claimed.
- `scripts/` — release and maintenance tooling; `scripts/release.ts` is the
release authority.
- `desktop/` — Tauri v2 desktop shell, bootstrap UI, and compiled proxy sidecar preparation.
- `devlog/` — planning and investigation notes, tracked in this repository. See
"The `devlog` directory" below for what may and may not go there.

Expand Down
17 changes: 17 additions & 0 deletions desktop/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# OpenCodex desktop shell

The Tauri shell attaches to the local OpenCodex proxy and keeps the dashboard
in the proxy's loopback origin. During development:

```sh
bun run prepare-sidecar
bun run dev
```

The sidecar is generated from the repository's standalone binary build and is
not checked into git.

The CI desktop-shell job performs Rust-only checks. It creates an empty
platform-named sidecar stub and a placeholder dashboard resource directory
solely for Tauri's external-binary and resource validation; it does not build
or run the standalone binary.
12 changes: 12 additions & 0 deletions desktop/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "@opencodex/desktop",
"private": true,
"scripts": {
"dev": "tauri dev",
"build": "tauri build",
"prepare-sidecar": "bun scripts/prepare-sidecar.ts"
},
"devDependencies": {
"@tauri-apps/cli": "2.5.0"
}
}
59 changes: 59 additions & 0 deletions desktop/scripts/prepare-sidecar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { copyFileSync, cpSync, existsSync, mkdirSync } from "node:fs";
import { join, resolve } from "node:path";

const targetByTriple: Record<string, string> = {
"aarch64-apple-darwin": "bun-darwin-arm64",
"x86_64-apple-darwin": "bun-darwin-x64",
"x86_64-pc-windows-msvc": "bun-windows-x64",
"x86_64-unknown-linux-gnu": "bun-linux-x64",
"aarch64-unknown-linux-gnu": "bun-linux-arm64",
};

function argument(name: string): string | undefined {
const index = Bun.argv.indexOf(name);
return index < 0 ? undefined : Bun.argv[index + 1];
}

function hostTriple(): string | undefined {
const result = Bun.spawnSync(["rustc", "-vV"], { stdout: "pipe", stderr: "ignore" });
if (result.exitCode !== 0) return undefined;
const host = result.stdout.toString().match(/^host:\s*(\S+)$/m)?.[1];
return host;
}

const repoRoot = resolve(import.meta.dir, "../..");
const triple =
argument("--target") ??
process.env.TARGET ??
process.env.RUST_TARGET ??
Bun.env.RUST_TARGET ??
hostTriple();
if (!triple || !targetByTriple[triple]) {
throw new Error(
`Unsupported Rust target ${triple ?? "(host unavailable)"}; pass --target ${Object.keys(targetByTriple).join("|")}`,
);
}

const target = targetByTriple[triple];
const source = join(repoRoot, "dist", "standalone", target);
const executable = join(source, target.startsWith("bun-windows-") ? "ocx.exe" : "ocx");
if (!existsSync(executable)) {
const result = Bun.spawnSync([
process.execPath,
"run",
"build:standalone",
"--target",
target,
], { cwd: repoRoot, stdout: "inherit", stderr: "inherit" });
Comment on lines +40 to +47

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Build the GUI before preparing the sidecar

On a clean checkout, gui/dist is ignored and absent, but this path invokes build:standalone, whose first prerequisite check rejects the build unless gui/dist/index.html already exists; the later cpSync has the same unstated dependency. Consequently the documented bun run prepare-sidecar workflow fails before producing a sidecar unless the user happened to run bun run build:gui separately. Have this preparation command build the GUI first or fail with and document the required prerequisite.

Useful? React with 👍 / 👎.

if (result.exitCode !== 0) process.exit(result.exitCode);
}

const desktopRoot = resolve(import.meta.dir, "..");
const binaries = join(desktopRoot, "src-tauri", "binaries");
const resources = join(desktopRoot, "src-tauri", "resources", "gui", "dist");
mkdirSync(binaries, { recursive: true });
mkdirSync(resources, { recursive: true });
const destination = join(binaries, `ocx-${triple}${target.startsWith("bun-windows-") ? ".exe" : ""}`);
copyFileSync(executable, destination);
cpSync(join(repoRoot, "gui", "dist"), resources, { recursive: true });
console.log(`Prepared ${destination}`);
Loading
Loading