Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 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
75 changes: 75 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ permissions:
jobs:
publish:
runs-on: blacksmith-4vcpu-ubuntu-2404
if: github.repository == 'sst/opencode'
steps:
- uses: actions/checkout@v3
with:
Expand Down Expand Up @@ -79,3 +80,77 @@ jobs:
GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }}
AUR_KEY: ${{ secrets.AUR_KEY }}
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}

publish-tauri:
strategy:
matrix:
settings:
- host: macos-latest
target: x86_64-apple-darwin
- host: macos-latest
target: aarch64-apple-darwin
- host: windows-latest
target: x86_64-pc-windows-msvc
- host: ubuntu-24.04
target: x86_64-unknown-linux-gnu
runs-on: ${{ matrix.settings.host }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0

- run: git fetch --force --tags

- uses: ./.github/actions/setup-bun

- name: install dependencies (ubuntu only)
if: startsWith(matrix.settings.host, 'ubuntu')
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf

- name: install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.settings.target }}

- uses: Swatinem/rust-cache@v2
with:
workspaces: packages/tauri/src-tauri
shared-key: ${{ matrix.settings.target }}

- name: Prepare
run: |
cd packages/tauri
bun ./scripts/prepare.ts
env:
OPENCODE_BUMP: ${{ inputs.bump }}
OPENCODE_VERSION: ${{ inputs.version }}
OPENCODE_CHANNEL: latest
NPM_CONFIG_TOKEN: ${{ secrets.NPM_TOKEN }}
GITHUB_TOKEN: ${{ secrets.SST_GITHUB_TOKEN }}
AUR_KEY: ${{ secrets.AUR_KEY }}
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
RUST_TARGET: ${{ matrix.settings.target }}
GH_TOKEN: ${{ github.token }}

# Fixes AppImage build issues, can be removed when https://github.com/tauri-apps/tauri/pull/12491 is released
- run: cargo install tauri-cli --git https://github.com/tauri-apps/tauri --branch feat/truly-portable-appimage
if: startsWith(matrix.settings.host, 'ubuntu')

- name: Build and upload artifacts
uses: tauri-apps/tauri-action@390cbe447412ced1303d35abe75287949e43437a
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAURI_BUNDLER_NEW_APPIMAGE_FORMAT: true
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
with:
projectPath: packages/tauri
uploadWorkflowArtifacts: true
tauriScript: ${{ (startsWith(matrix.settings.host, 'ubuntu') && 'cargo tauri') || '' }}
args: --target ${{ matrix.settings.target }}
updaterJsonPreferNsis: true
releaseDraft: true
tagName: ${{ inputs.version }}
releaseName: ${{ inputs.version }}
Comment on lines +153 to +155
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

These should all be replaced by just providing releaseId, which will likely need to be derived from the publish job

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ refs
Session.vim
opencode.json
a.out
target
225 changes: 215 additions & 10 deletions bun.lock

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions packages/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
"version": "1.0.132",
"description": "",
"type": "module",
"exports": {
".": "./src/index.tsx",
"./vite": "./vite.js"
},
"scripts": {
"typecheck": "tsgo --noEmit",
"start": "vite",
Expand Down
5 changes: 3 additions & 2 deletions packages/desktop/src/pages/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default function Layout(props: ParentProps) {

return (
<div class="relative h-screen flex flex-col">
<header class="h-12 shrink-0 bg-background-base border-b border-border-weak-base">
<header class="h-12 shrink-0 bg-background-base border-b border-border-weak-base" data-tauri-drag-region>
<A
href="/"
classList={{
Expand All @@ -33,6 +33,7 @@ export default function Layout(props: ParentProps) {
"border-r border-border-weak-base": true,
}}
style={{ width: layout.sidebar.opened() ? `${layout.sidebar.width()}px` : undefined }}
data-tauri-drag-region
>
<Mark class="shrink-0" />
</A>
Expand Down Expand Up @@ -109,7 +110,7 @@ export default function Layout(props: ParentProps) {
>
<Tooltip placement="right" value={session.title}>
<div
class="w-full px-2 py-1 rounded-md
class="w-full px-2 py-1 rounded-md
group-data-[active=true]/session:bg-surface-raised-base-hover
group-hover/session:bg-surface-raised-base-hover
group-focus/session:bg-surface-raised-base-hover"
Expand Down
14 changes: 2 additions & 12 deletions packages/desktop/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
import { defineConfig } from "vite"
import solidPlugin from "vite-plugin-solid"
import tailwindcss from "@tailwindcss/vite"
import path from "path"
import desktopPlugin from "./vite"

export default defineConfig({
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
plugins: [tailwindcss(), solidPlugin()] as any,
plugins: [desktopPlugin] as any,
server: {
host: "0.0.0.0",
allowedHosts: true,
Expand All @@ -18,7 +11,4 @@ export default defineConfig({
build: {
target: "esnext",
},
worker: {
format: "es",
},
})
26 changes: 26 additions & 0 deletions packages/desktop/vite.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import solidPlugin from "vite-plugin-solid"
import tailwindcss from "@tailwindcss/vite"
import { fileURLToPath } from "url"

/**
* @type {import("vite").PluginOption}
*/
export default [
{
name: "opencode-desktop:config",
config() {
return {
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
},
worker: {
format: "es",
},
}
},
},
tailwindcss(),
solidPlugin(),
]
51 changes: 22 additions & 29 deletions packages/tauri/index.html
Original file line number Diff line number Diff line change
@@ -1,35 +1,28 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="/src/styles.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tauri App</title>
<script type="module" src="/src/main.ts" defer></script>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>OpenCode</title>
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="manifest" href="/site.webmanifest" />
<meta name="theme-color" content="#F8F7F7" />
<meta name="theme-color" content="#131010" media="(prefers-color-scheme: dark)" />
<meta property="og:image" content="/social-share.png" />
<meta property="twitter:image" content="/social-share.png" />
</head>

<body>
<main class="container">
<h1>Welcome to Tauri</h1>

<div class="row">
<a href="https://vite.dev" target="_blank">
<img src="/src/assets/vite.svg" class="logo vite" alt="Vite logo" />
</a>
<a href="https://tauri.app" target="_blank">
<img src="/src/assets/tauri.svg" class="logo tauri" alt="Tauri logo" />
</a>
<a href="https://www.typescriptlang.org/docs" target="_blank">
<img src="/src/assets/typescript.svg" class="logo typescript" alt="typescript logo" />
</a>
</div>
<p>Click on the Tauri logo to learn more about the framework</p>

<form class="row" id="greet-form">
<input id="greet-input" placeholder="Enter a name..." />
<button type="submit">Greet</button>
</form>
<p id="greet-msg"></p>
</main>
<body class="antialiased overscroll-none select-none text-12-regular">
<script>
;(function () {
const savedTheme = localStorage.getItem("theme") || "oc-1"
document.documentElement.setAttribute("data-theme", savedTheme)
})()
</script>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script src="/src/index.ts" type="module"></script>
</body>
</html>
14 changes: 11 additions & 3 deletions packages/tauri/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,26 @@
"version": "1.0.132",
"type": "module",
"scripts": {
"predev": "bun ./scripts/predev.ts",
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"tauri": "tauri"
},
"dependencies": {
"@opencode-ai/desktop": "workspace:*",
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-opener": "^2"
"@tauri-apps/plugin-dialog": "~2",
"@tauri-apps/plugin-opener": "^2",
"@tauri-apps/plugin-shell": "~2",
"@tauri-apps/plugin-updater": "~2",
"solid-js": "catalog:"
},
"devDependencies": {
"@actions/artifact": "4.0.0",
"@tauri-apps/cli": "^2",
"vite": "^6.0.3",
"typescript": "~5.6.2"
"@types/bun": "catalog:",
"typescript": "~5.6.2",
"vite": "catalog:"
}
}
12 changes: 12 additions & 0 deletions packages/tauri/scripts/copy-bundles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { $ } from "bun"
import * as path from "node:path"

import { RUST_TARGET } from "./utils"

if (!RUST_TARGET) throw new Error("RUST_TARGET not defined")

const BUNDLE_DIR = `src-tauri/target/${RUST_TARGET}/release/bundle`
const BUNDLES_OUT_DIR = path.join(process.cwd(), `src-tauri/target/bundles`)

await $`mkdir -p ${BUNDLES_OUT_DIR}`
await $`cp -r ${BUNDLE_DIR}/*/OpenCode* ${BUNDLES_OUT_DIR}`
17 changes: 17 additions & 0 deletions packages/tauri/scripts/predev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as fs from "node:fs/promises"
import { $ } from "bun"

import { copyBinaryToSidecarFolder, getCurrentSidecar } from "./utils"

const RUST_TARGET = Bun.env.TAURI_ENV_TARGET_TRIPLE

const sidecarConfig = getCurrentSidecar(RUST_TARGET)

const binaryPath = `../opencode/dist/${sidecarConfig.ocBinary}/bin/opencode`

if (!(await fs.exists(binaryPath))) {
console.log("opencode binary not found, building...")
await $`cd ../opencode && bun run build --single`
}

await copyBinaryToSidecarFolder(binaryPath, RUST_TARGET)
20 changes: 20 additions & 0 deletions packages/tauri/scripts/prepare.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env bun

import { $ } from "bun"

import { copyBinaryToSidecarFolder, getCurrentSidecar } from "./utils"

const sidecarConfig = getCurrentSidecar()

const dir = "src-tauri/target/opencode-binaries"

await $`mkdir -p ${dir}`
await $`gh release download --pattern ${sidecarConfig.ocBinary}.${sidecarConfig.assetExt} --repo sst/opencode --skip-existing --dir ${dir}`

if (sidecarConfig.assetExt === "tar.gz") {
await $`tar -xvzf ${dir}/${sidecarConfig.ocBinary}.${sidecarConfig.assetExt} -C ${dir}`
} else {
await $`unzip -o ${dir}/${sidecarConfig.ocBinary}.${sidecarConfig.assetExt} -d ${dir}`
}

await copyBinaryToSidecarFolder(`${dir}/opencode${process.platform === "win32" ? ".exe" : ""}`)
43 changes: 43 additions & 0 deletions packages/tauri/scripts/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { $ } from "bun"

export const SIDECAR_BINARIES: Array<{ rustTarget: string; ocBinary: string; assetExt: string }> = [
{
rustTarget: "aarch64-apple-darwin",
ocBinary: "opencode-darwin-arm64",
assetExt: "zip",
},
{
rustTarget: "x86_64-apple-darwin",
ocBinary: "opencode-darwin-x64",
assetExt: "zip",
},
{
rustTarget: "x86_64-pc-windows-msvc",
ocBinary: "opencode-windows-x64",
assetExt: "zip",
},
{
rustTarget: "x86_64-unknown-linux-gnu",
ocBinary: "opencode-linux-x64",
assetExt: "tar.gz",
},
]

export const RUST_TARGET = Bun.env.RUST_TARGET

export function getCurrentSidecar(target = RUST_TARGET) {
if (!target && !RUST_TARGET) throw new Error("RUST_TARGET not set")

const binaryConfig = SIDECAR_BINARIES.find((b) => b.rustTarget === target)
if (!binaryConfig) throw new Error(`Sidecar configuration not available for Rust target '${RUST_TARGET}'`)

return binaryConfig
}

export async function copyBinaryToSidecarFolder(source: string, target = RUST_TARGET) {
await $`mkdir -p src-tauri/sidecars`
const dest = `src-tauri/sidecars/opencode-${target}${process.platform === "win32" ? ".exe" : ""}`
await $`cp ${source} ${dest}`

console.log(`Copied ${source} to ${dest}`)
}
2 changes: 2 additions & 0 deletions packages/tauri/src-tauri/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
# Generated by Tauri
# will have schema files for capabilities auto-completion
/gen/schemas

sidecars
Loading