Compare commits

..

15 Commits

Author SHA1 Message Date
Shantur Rathore
c825ff066e bump version to 0.5.1 2026-01-07 08:56:19 +00:00
Shantur Rathore
f7ded37ea3 Fix macOS tauri cli package name 2026-01-07 06:35:59 +00:00
Shantur Rathore
847faf1214 Fix Tauri builds and Windows opencode-config loop 2026-01-07 06:25:19 +00:00
Shantur Rathore
b1691add1c Stabilize Tauri CLI install in CI 2026-01-07 06:10:30 +00:00
Shantur Rathore
3b9a44779a Exclude opencode-config from npm workspaces 2026-01-06 23:20:45 +00:00
Shantur Rathore
62fd88cd3f Install @tauri-apps/cli alongside platform bindings 2026-01-06 23:10:45 +00:00
Shantur Rathore
ce2273fe57 Sync package-lock for opencode-config workspace 2026-01-06 23:03:54 +00:00
Shantur Rathore
0eee325777 Stabilize Windows opencode-config install and pin tauri bindings 2026-01-06 22:57:38 +00:00
Shantur Rathore
f7c9db44ad Fix Windows builds by tracking opencode-config package.json 2026-01-06 22:43:46 +00:00
Shantur Rathore
1fcf89b945 Isolate opencode-config install from workspace 2026-01-06 20:58:01 +00:00
Shantur Rathore
f5682ea246 Fix dev CI build tool resolution and Windows npm spawning 2026-01-06 20:45:40 +00:00
Shantur Rathore
fa308696b4 Allow callers to control workflow permissions 2026-01-06 20:32:29 +00:00
Shantur Rathore
ac8dfcc607 Improve opencode-config install on Windows 2026-01-06 20:30:40 +00:00
Shantur Rathore
ac04d5daf7 Run build-only CI on dev pushes 2026-01-06 20:30:37 +00:00
Shantur Rathore
7fe8fee295 Fix Tauri CLI native dependency installs 2026-01-06 20:30:33 +00:00
12 changed files with 211 additions and 86 deletions

View File

@@ -4,21 +4,33 @@ on:
workflow_call:
inputs:
version:
description: "Version to apply to workspace packages"
required: true
description: "Version to apply to workspace packages (release builds)"
required: false
default: ""
type: string
tag:
description: "Git tag to upload assets to"
required: true
description: "Git tag to upload assets to (release builds)"
required: false
default: ""
type: string
release_name:
description: "Release name (unused here, for context)"
required: true
required: false
default: ""
type: string
upload:
description: "Upload built artifacts to the GitHub release"
required: false
default: true
type: boolean
set_versions:
description: "Run npm version to set workspace versions"
required: false
default: true
type: boolean
permissions:
id-token: write
contents: write
# Permissions are intentionally omitted here so callers can choose
# least-privilege (e.g. dev CI uses read-only; releases grant write).
env:
NODE_VERSION: 20
@@ -41,10 +53,11 @@ jobs:
cache: npm
- name: Set workspace versions
if: ${{ inputs.set_versions && inputs.version != '' }}
run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
- name: Install dependencies
run: npm ci --workspaces
run: npm ci --workspaces --include=optional
- name: Ensure rollup native binary
run: npm install @rollup/rollup-darwin-x64 --no-save
@@ -53,6 +66,7 @@ jobs:
run: npm run build:mac --workspace @neuralnomads/codenomad-electron-app
- name: Upload release assets
if: ${{ inputs.upload && inputs.tag != '' }}
run: |
set -euo pipefail
shopt -s nullglob
@@ -79,11 +93,12 @@ jobs:
cache: npm
- name: Set workspace versions
if: ${{ inputs.set_versions && inputs.version != '' }}
run: npm version ${{ env.VERSION }} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
shell: bash
- name: Install dependencies
run: npm ci --workspaces
run: npm ci --workspaces --include=optional
- name: Ensure rollup native binary
run: npm install @rollup/rollup-win32-x64-msvc --no-save
@@ -92,6 +107,7 @@ jobs:
run: npm run build:win --workspace @neuralnomads/codenomad-electron-app
- name: Upload release assets
if: ${{ inputs.upload && inputs.tag != '' }}
shell: pwsh
run: |
Get-ChildItem -Path "packages/electron-app/release" -Filter *.zip -File | ForEach-Object {
@@ -116,10 +132,11 @@ jobs:
cache: npm
- name: Set workspace versions
if: ${{ inputs.set_versions && inputs.version != '' }}
run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
- name: Install dependencies
run: npm ci --workspaces
run: npm ci --workspaces --include=optional
- name: Ensure rollup native binary
run: npm install @rollup/rollup-linux-x64-gnu --no-save
@@ -128,6 +145,7 @@ jobs:
run: npm run build:linux --workspace @neuralnomads/codenomad-electron-app
- name: Upload release assets
if: ${{ inputs.upload && inputs.tag != '' }}
run: |
set -euo pipefail
shopt -s nullglob
@@ -157,18 +175,38 @@ jobs:
uses: dtolnay/rust-toolchain@stable
- name: Set workspace versions
if: ${{ inputs.set_versions && inputs.version != '' }}
run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
- name: Install dependencies
run: npm ci --workspaces
run: npm ci --workspaces --include=optional
- name: Ensure rollup native binary
run: npm install @rollup/rollup-darwin-x64 --no-save
- name: Prebuild (Tauri)
run: npm run prebuild --workspace @codenomad/tauri-app
- name: Ensure tauri native binary
working-directory: packages/tauri-app
run: |
set -euo pipefail
for attempt in 1 2 3; do
if [ "$attempt" -gt 1 ]; then
echo "Retrying Tauri CLI install (attempt $attempt)..."
fi
npm install @tauri-apps/cli@2.9.4 @tauri-apps/cli-darwin-x64@2.9.4 --no-save --no-audit --no-fund --workspaces=false
node -e "require('@tauri-apps/cli'); console.log('Tauri CLI loaded')" && exit 0
done
echo "Tauri CLI failed to load after retries" >&2
exit 1
- name: Build macOS bundle (Tauri)
run: npm run build --workspace @codenomad/tauri-app
working-directory: packages/tauri-app
run: npm exec -- tauri build
- name: Package Tauri artifacts (macOS)
if: ${{ inputs.upload }}
run: |
set -euo pipefail
BUNDLE_ROOT="packages/tauri-app/target/release/bundle"
@@ -180,6 +218,7 @@ jobs:
fi
- name: Upload Tauri release assets (macOS)
if: ${{ inputs.upload && inputs.tag != '' }}
run: |
set -euo pipefail
shopt -s nullglob
@@ -209,18 +248,38 @@ jobs:
uses: dtolnay/rust-toolchain@stable
- name: Set workspace versions
if: ${{ inputs.set_versions && inputs.version != '' }}
run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
- name: Install dependencies
run: npm ci --workspaces
run: npm ci --workspaces --include=optional
- name: Ensure rollup native binary
run: npm install @rollup/rollup-darwin-arm64 --no-save
- name: Prebuild (Tauri)
run: npm run prebuild --workspace @codenomad/tauri-app
- name: Ensure tauri native binary
working-directory: packages/tauri-app
run: |
set -euo pipefail
for attempt in 1 2 3; do
if [ "$attempt" -gt 1 ]; then
echo "Retrying Tauri CLI install (attempt $attempt)..."
fi
npm install @tauri-apps/cli@2.9.4 @tauri-apps/cli-darwin-arm64@2.9.4 --no-save --no-audit --no-fund --workspaces=false
node -e "require('@tauri-apps/cli'); console.log('Tauri CLI loaded')" && exit 0
done
echo "Tauri CLI failed to load after retries" >&2
exit 1
- name: Build macOS bundle (Tauri, arm64)
run: npm run build --workspace @codenomad/tauri-app
working-directory: packages/tauri-app
run: npm exec -- tauri build
- name: Package Tauri artifacts (macOS arm64)
if: ${{ inputs.upload }}
run: |
set -euo pipefail
BUNDLE_ROOT="packages/tauri-app/target/release/bundle"
@@ -232,6 +291,7 @@ jobs:
fi
- name: Upload Tauri release assets (macOS arm64)
if: ${{ inputs.upload && inputs.tag != '' }}
run: |
set -euo pipefail
shopt -s nullglob
@@ -261,19 +321,41 @@ jobs:
uses: dtolnay/rust-toolchain@stable
- name: Set workspace versions
if: ${{ inputs.set_versions && inputs.version != '' }}
run: npm version ${{ env.VERSION }} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
shell: bash
- name: Install dependencies
run: npm ci --workspaces
run: npm ci --workspaces --include=optional
- name: Ensure rollup native binary
run: npm install @rollup/rollup-win32-x64-msvc --no-save
- name: Prebuild (Tauri)
run: npm run prebuild --workspace @codenomad/tauri-app
- name: Ensure tauri native binary
shell: bash
working-directory: packages/tauri-app
run: |
set -euo pipefail
for attempt in 1 2 3; do
if [ "$attempt" -gt 1 ]; then
echo "Retrying Tauri CLI install (attempt $attempt)..."
fi
npm install @tauri-apps/cli@2.9.4 @tauri-apps/cli-win32-x64-msvc@2.9.4 --no-save --no-audit --no-fund --workspaces=false
node -e "require('@tauri-apps/cli'); console.log('Tauri CLI loaded')" && exit 0
done
echo "Tauri CLI failed to load after retries" >&2
exit 1
- name: Build Windows bundle (Tauri)
run: npm run build --workspace @codenomad/tauri-app
shell: bash
working-directory: packages/tauri-app
run: npm exec -- tauri build
- name: Package Tauri artifacts (Windows)
if: ${{ inputs.upload }}
shell: pwsh
run: |
$bundleRoot = "packages/tauri-app/target/release/bundle"
@@ -287,6 +369,7 @@ jobs:
}
- name: Upload Tauri release assets (Windows)
if: ${{ inputs.upload && inputs.tag != '' }}
shell: pwsh
run: |
if (Test-Path "packages/tauri-app/release-tauri") {
@@ -329,18 +412,38 @@ jobs:
librsvg2-dev
- name: Set workspace versions
if: ${{ inputs.set_versions && inputs.version != '' }}
run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
- name: Install dependencies
run: npm ci --workspaces
run: npm ci --workspaces --include=optional
- name: Ensure rollup native binary
run: npm install @rollup/rollup-linux-x64-gnu --no-save
- name: Prebuild (Tauri)
run: npm run prebuild --workspace @codenomad/tauri-app
- name: Ensure tauri native binary
working-directory: packages/tauri-app
run: |
set -euo pipefail
for attempt in 1 2 3; do
if [ "$attempt" -gt 1 ]; then
echo "Retrying Tauri CLI install (attempt $attempt)..."
fi
npm install @tauri-apps/cli@2.9.4 @tauri-apps/cli-linux-x64-gnu@2.9.4 --no-save --no-audit --no-fund --workspaces=false
node -e "require('@tauri-apps/cli'); console.log('Tauri CLI loaded')" && exit 0
done
echo "Tauri CLI failed to load after retries" >&2
exit 1
- name: Build Linux bundle (Tauri)
run: npm run build --workspace @codenomad/tauri-app
working-directory: packages/tauri-app
run: npm exec -- tauri build
- name: Package Tauri artifacts (Linux)
if: ${{ inputs.upload }}
run: |
set -euo pipefail
SEARCH_ROOT="packages/tauri-app/target"
@@ -367,6 +470,7 @@ jobs:
cp "$rpm" "$ARTIFACT_DIR/CodeNomad-Tauri-${VERSION}-linux-x64.rpm"
- name: Upload Tauri release assets (Linux)
if: ${{ inputs.upload && inputs.tag != '' }}
run: |
set -euo pipefail
shopt -s nullglob
@@ -429,7 +533,7 @@ jobs:
run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
- name: Install dependencies
run: npm ci --workspaces
run: npm ci --workspaces --include=optional
- name: Ensure rollup native binary
run: npm install @rollup/rollup-linux-arm64-gnu --no-save
@@ -497,10 +601,11 @@ jobs:
sudo gem install --no-document fpm
- name: Set workspace versions
if: ${{ inputs.set_versions && inputs.version != '' }}
run: npm version ${VERSION} --workspaces --include-workspace-root --no-git-tag-version --allow-same-version
- name: Install project dependencies
run: npm ci --workspaces
run: npm ci --workspaces --include=optional
- name: Ensure rollup native binary
run: npm install @rollup/rollup-linux-x64-gnu --no-save
@@ -509,6 +614,7 @@ jobs:
run: npm run build:linux-rpm --workspace @neuralnomads/codenomad-electron-app
- name: Upload RPM release assets
if: ${{ inputs.upload && inputs.tag != '' }}
run: |
set -euo pipefail
shopt -s nullglob

View File

@@ -1,16 +1,18 @@
name: Dev Release
name: Dev CI
on:
push:
branches:
- dev
workflow_dispatch:
permissions:
id-token: write
contents: write
contents: read
jobs:
dev-release:
uses: ./.github/workflows/reusable-release.yml
dev-ci:
uses: ./.github/workflows/build-and-upload.yml
with:
version_suffix: -dev
dist_tag: dev
upload: false
set_versions: false
secrets: inherit

42
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "codenomad-workspace",
"version": "0.5.0",
"version": "0.5.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "codenomad-workspace",
"version": "0.5.0",
"version": "0.5.1",
"dependencies": {
"7zip-bin": "^5.2.0",
"google-auth-library": "^10.5.0"
@@ -16,7 +16,10 @@
},
"workspaces": {
"packages": [
"packages/*"
"packages/server",
"packages/ui",
"packages/electron-app",
"packages/tauri-app"
]
}
},
@@ -1092,25 +1095,6 @@
"node": ">= 8"
}
},
"node_modules/@opencode-ai/plugin": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@opencode-ai/plugin/-/plugin-1.1.1.tgz",
"integrity": "sha512-OZGvpDal8YsSo6dnatHfwviSToGZ6mJJyEKZGxUyWDuGCP7VhcoPkoM16ktl7TCVHkDK+TdwY9tKzkzFqQNc5w==",
"license": "MIT",
"dependencies": {
"@opencode-ai/sdk": "1.1.1",
"zod": "4.1.8"
}
},
"node_modules/@opencode-ai/plugin/node_modules/zod": {
"version": "4.1.8",
"resolved": "https://registry.npmjs.org/zod/-/zod-4.1.8.tgz",
"integrity": "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
},
"node_modules/@opencode-ai/sdk": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.1.1.tgz",
@@ -5268,10 +5252,6 @@
"regex-recursion": "^6.0.2"
}
},
"node_modules/opencode-config": {
"resolved": "packages/opencode-config",
"link": true
},
"node_modules/p-cancelable": {
"version": "2.1.1",
"dev": true,
@@ -7409,7 +7389,7 @@
},
"packages/electron-app": {
"name": "@neuralnomads/codenomad-electron-app",
"version": "0.5.0",
"version": "0.5.1",
"dependencies": {
"@codenomad/ui": "file:../ui",
"@neuralnomads/codenomad": "file:../server"
@@ -7434,14 +7414,16 @@
"license": "MIT"
},
"packages/opencode-config": {
"name": "@codenomad/opencode-config",
"version": "0.5.0",
"extraneous": true,
"dependencies": {
"@opencode-ai/plugin": "1.1.1"
}
},
"packages/server": {
"name": "@neuralnomads/codenomad",
"version": "0.5.0",
"version": "0.5.1",
"dependencies": {
"@fastify/cors": "^8.5.0",
"@fastify/reply-from": "^9.8.0",
@@ -7476,14 +7458,14 @@
},
"packages/tauri-app": {
"name": "@codenomad/tauri-app",
"version": "0.5.0",
"version": "0.5.1",
"devDependencies": {
"@tauri-apps/cli": "^2.9.4"
}
},
"packages/ui": {
"name": "@codenomad/ui",
"version": "0.5.0",
"version": "0.5.1",
"dependencies": {
"@git-diff-view/solid": "^0.0.8",
"@kobalte/core": "0.13.11",

View File

@@ -1,11 +1,14 @@
{
"name": "codenomad-workspace",
"version": "0.5.0",
"version": "0.5.1",
"private": true,
"description": "CodeNomad monorepo workspace",
"workspaces": {
"packages": [
"packages/*"
"packages/server",
"packages/ui",
"packages/electron-app",
"packages/tauri-app"
]
},
"scripts": {

View File

@@ -1,6 +1,6 @@
{
"name": "@neuralnomads/codenomad-electron-app",
"version": "0.5.0",
"version": "0.5.1",
"description": "CodeNomad - AI coding assistant",
"author": {
"name": "Neural Nomads",

View File

@@ -2,7 +2,7 @@
import { spawn } from "child_process"
import { existsSync } from "fs"
import { join } from "path"
import path, { join } from "path"
import { fileURLToPath } from "url"
const __dirname = fileURLToPath(new URL(".", import.meta.url))
@@ -55,12 +55,22 @@ const platforms = {
function run(command, args, options = {}) {
return new Promise((resolve, reject) => {
const env = { ...process.env, NODE_PATH: nodeModulesPath, ...(options.env || {}) }
const pathKey = Object.keys(env).find((key) => key.toLowerCase() === "path") ?? "PATH"
const binPaths = [
join(nodeModulesPath, ".bin"),
join(workspaceNodeModulesPath, ".bin"),
]
env[pathKey] = `${binPaths.join(path.delimiter)}${path.delimiter}${env[pathKey] ?? ""}`
const spawnOptions = {
cwd: appDir,
stdio: "inherit",
shell: process.platform === "win32",
...options,
env: { ...process.env, NODE_PATH: nodeModulesPath, ...(options.env || {}) },
env,
}
const child = spawn(command, args, spawnOptions)

View File

@@ -0,0 +1,8 @@
{
"name": "@codenomad/opencode-config",
"version": "0.5.0",
"private": true,
"dependencies": {
"@opencode-ai/plugin": "1.1.1"
}
}

View File

@@ -1,12 +1,12 @@
{
"name": "@neuralnomads/codenomad",
"version": "0.5.0",
"version": "0.5.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@neuralnomads/codenomad",
"version": "0.5.0",
"version": "0.5.1",
"dependencies": {
"@fastify/cors": "^8.5.0",
"commander": "^12.1.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@neuralnomads/codenomad",
"version": "0.5.0",
"version": "0.5.1",
"description": "CodeNomad Server",
"author": {
"name": "Neural Nomads",

View File

@@ -10,7 +10,9 @@ const cliRoot = path.resolve(__dirname, "..")
const sourceDir = path.resolve(cliRoot, "../opencode-config")
const targetDir = path.resolve(cliRoot, "dist/opencode-config")
const nodeModulesDir = path.resolve(sourceDir, "node_modules")
const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm"
const selfLinkDir = path.resolve(nodeModulesDir, "@codenomad", "opencode-config")
const npmExecPath = process.env.npm_execpath
const npmNodeExecPath = process.env.npm_node_execpath
if (!existsSync(sourceDir)) {
console.error(`[copy-opencode-config] Missing source directory at ${sourceDir}`)
@@ -19,27 +21,39 @@ if (!existsSync(sourceDir)) {
if (!existsSync(nodeModulesDir)) {
console.log(`[copy-opencode-config] Installing opencode-config dependencies in ${sourceDir}`)
const result = spawnSync(
npmCmd,
[
"install",
"--prefix",
sourceDir,
"--omit=dev",
"--ignore-scripts",
"--fund=false",
"--audit=false",
"--package-lock=false",
"--workspaces=false",
],
{ cwd: sourceDir, stdio: "inherit", env: { ...process.env, npm_config_workspaces: "false" } },
)
const npmArgs = [
"install",
"--prefix",
sourceDir,
"--omit=dev",
"--ignore-scripts",
"--fund=false",
"--audit=false",
"--package-lock=false",
"--workspaces=false",
]
const env = { ...process.env, npm_config_workspaces: "false" }
const npmCli = npmExecPath && npmNodeExecPath ? [npmNodeExecPath, [npmExecPath, ...npmArgs]] : null
const result = npmCli
? spawnSync(npmCli[0], npmCli[1], { cwd: sourceDir, stdio: "inherit", env })
: spawnSync("npm", npmArgs, { cwd: sourceDir, stdio: "inherit", env, shell: process.platform === "win32" })
if (result.status !== 0) {
if (result.error) {
console.error("[copy-opencode-config] npm install failed to start", result.error)
}
console.error("[copy-opencode-config] Failed to install opencode-config dependencies")
process.exit(result.status ?? 1)
}
}
// npm can create a self-referential link for scoped packages on Windows.
// That link causes recursive copies (ELOOP) during bundling.
rmSync(selfLinkDir, { recursive: true, force: true })
rmSync(targetDir, { recursive: true, force: true })
mkdirSync(path.dirname(targetDir), { recursive: true })
cpSync(sourceDir, targetDir, { recursive: true })

View File

@@ -1,15 +1,15 @@
{
"name": "@codenomad/tauri-app",
"version": "0.5.0",
"version": "0.5.1",
"private": true,
"scripts": {
"dev": "npx --yes @tauri-apps/cli@^2.9.4 dev",
"dev": "tauri dev",
"dev:ui": "npm run dev --workspace @codenomad/ui",
"dev:prep": "node ./scripts/dev-prep.js",
"dev:bootstrap": "npm run dev:prep && npm run dev:ui",
"prebuild": "node ./scripts/prebuild.js",
"bundle:server": "npm run prebuild",
"build": "npx --yes @tauri-apps/cli@^2.9.4 build"
"build": "tauri build"
},
"devDependencies": {
"@tauri-apps/cli": "^2.9.4"

View File

@@ -1,6 +1,6 @@
{
"name": "@codenomad/ui",
"version": "0.5.0",
"version": "0.5.1",
"private": true,
"type": "module",
"scripts": {