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
14 changes: 13 additions & 1 deletion .github/workflows/release-desktop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ on:
push:
tags:
- "desktop-v*"
- "DeskTop-v*"
- "Desktop-v*"
pull_request:
paths:
- "apps/desktop/**"
- ".github/workflows/release-desktop.yml"
workflow_dispatch:
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.

jobs:
release:
Expand Down Expand Up @@ -53,15 +60,20 @@ jobs:
if [ "${{ matrix.platform }}" = "windows-latest" ]; then EXT=".exe"; fi
mkdir -p apps/desktop/src-tauri/binaries
cp target/${{ matrix.target }}/release/api${EXT} apps/desktop/src-tauri/binaries/api-${{ matrix.target }}${EXT}
- name: Build Tauri app (PR / manual validation)
if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'

@cubic-dev-ai cubic-dev-ai Bot Mar 3, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: When workflow_dispatch is triggered from a tag ref, both this --no-bundle validation step and the release step below will execute, because github.event_name == 'workflow_dispatch' is true here AND startsWith(github.ref, 'refs/tags/') is true for the release step. This results in a redundant no-bundle build before the actual release build. Add a guard to skip this step when running on a tag.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/release-desktop.yml, line 64:

<comment>When `workflow_dispatch` is triggered from a tag ref, both this `--no-bundle` validation step and the release step below will execute, because `github.event_name == 'workflow_dispatch'` is true here AND `startsWith(github.ref, 'refs/tags/')` is true for the release step. This results in a redundant no-bundle build before the actual release build. Add a guard to skip this step when running on a tag.</comment>

<file context>
@@ -60,8 +60,8 @@ jobs:
-      - name: Build Tauri app (PR validation)
-        if: github.event_name == 'pull_request'
+      - name: Build Tauri app (PR / manual validation)
+        if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
         working-directory: apps/desktop
         run: bun tauri build ${{ matrix.args }} --no-bundle
</file context>
Suggested change
if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
if: (github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch') && !startsWith(github.ref, 'refs/tags/')
Fix with Cubic

working-directory: apps/desktop
run: bun tauri build ${{ matrix.args }} --no-bundle
- name: Build and release Tauri app
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
if: startsWith(github.ref, 'refs/tags/')
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
with:
projectPath: apps/desktop
tagName: desktop-v__VERSION__
tagName: ${{ github.ref_name }}
releaseName: Atmos Desktop v__VERSION__
releaseDraft: true
prerelease: false
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"tauri": "tauri",
"dev": "tauri dev",
"build": "tauri build",
"prepare:sidecar": "bash ./scripts/prepare-sidecar.sh"
"prepare:sidecar": "node ./scripts/before-build.mjs"
},
"devDependencies": {
"@tauri-apps/cli": "^2.0.0"
Expand Down
72 changes: 72 additions & 0 deletions apps/desktop/scripts/before-build.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { cpSync, existsSync, mkdirSync, rmSync } from "node:fs";
import { join, resolve } from "node:path";
import { spawnSync } from "node:child_process";

const rootDir = resolve(import.meta.dirname, "../../..");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify Node version expectations vs usage of import.meta.dirname
set -euo pipefail

echo "== package.json engines (all package.json files) =="
fd -a package.json -E node_modules -E dist -E build | while read -r f; do
  echo "--- $f"
  jq -r '.engines // {}' "$f"
done

echo
echo "== CI/workflow Node version pins =="
rg -n --glob '.github/workflows/**' 'setup-node|node-version|actions/setup-node'

echo
echo "== import.meta.dirname usage =="
rg -n 'import\.meta\.dirname'

Repository: AruNi-01/atmos

Length of output: 766


🌐 Web query:

Node.js import.meta.dirname availability version support when was it added

💡 Result:

import.meta.dirname (and import.meta.filename) support in Node.js:

  • Added: Node.js v20.11.0 (and also in the v21 line starting at v21.2.0). It’s available only in ES modules and only for file: modules. [1][2]
  • Status: Initially shipped as Stability: 1.2 (release candidate). [1]
  • Became non-experimental: Node.js v22.16.0 and v24.0.0. [2]

Sources: Node.js ESM docs (v20.18.0 / v20.19.0) and “latest” ESM docs showing the full version history. [1][2]


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check if file exists and read its content =="
if [ -f "apps/desktop/scripts/before-build.mjs" ]; then
  echo "File exists. Content:"
  cat -n "apps/desktop/scripts/before-build.mjs"
else
  echo "File not found"
fi

echo
echo "== Find CI/workflow files =="
find .github -type f -name "*.yml" -o -name "*.yaml" 2>/dev/null | head -20

echo
echo "== Check Node version in workflow files =="
find .github -type f \( -name "*.yml" -o -name "*.yaml" \) -exec grep -l "node-version\|setup-node" {} \; 2>/dev/null | while read f; do
  echo "--- $f"
  grep -n "node-version\|setup-node" "$f"
done

Repository: AruNi-01/atmos

Length of output: 2978


🌐 Web query:

Node.js v18 v19 support lifecycle when does it end deprecate

💡 Result:

  • Node.js 18 (Hydrogen, LTS): End-of-Life (no more security fixes) on April 30, 2025—so it’s already deprecated/EOL as of March 3, 2026. Node release posts for v18 reiterate this date and recommend upgrading to newer LTS lines. [1]
  • Node.js 19 (non‑LTS “Current” line): End-of-Life on April 10, 2023—also long EOL/deprecated. [2]

If you need a supported version today (March 2026), Node’s release list shows v24 as Active LTS and v22/v20 as Maintenance LTS (with v20 nearing its end). [2]

Sources
[1] Node.js v18.20.8 release post (EOL date) — nodejs.org [1]
[2] Node.js Releases table (status incl. v18/v19; current supported lines) — nodejs.org [2]


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Look for Node version management files =="
find . -maxdepth 2 -type f \( -name ".nvmrc" -o -name ".node-version" -o -name ".tool-versions" \) 2>/dev/null

echo
echo "== Check Tauri config (desktop app) =="
if [ -f "apps/desktop/src-tauri/tauri.conf.json" ]; then
  echo "Found tauri.conf.json, checking for Node requirements"
  cat "apps/desktop/src-tauri/tauri.conf.json" | head -50
fi

echo
echo "== Read CI workflow files for Node version =="
for f in .github/workflows/*.yml; do
  echo "--- $f"
  cat "$f" | grep -A 2 -B 2 "node\|Node" | head -20
done

Repository: AruNi-01/atmos

Length of output: 1363


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Read release-desktop.yml for Node version =="
head -100 ".github/workflows/release-desktop.yml" | grep -A 5 -B 5 "node\|Node\|setup"

echo
echo "== Check entire release-desktop.yml for version info =="
cat ".github/workflows/release-desktop.yml" | grep -i "node-version\|uses:.*node"

Repository: AruNi-01/atmos

Length of output: 449


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check what Node version is bundled with Bun =="
cat ".github/workflows/release-desktop.yml"

echo
echo "== Check if there are any .github/actions files with Node setup =="
cat ".github/actions/setup-bun/action.yml"

Repository: AruNi-01/atmos

Length of output: 3196


Guard import.meta.dirname for Node runtime compatibility.

Line 5 uses import.meta.dirname, which is not available in Node.js versions before v20.11.0. Since the project does not specify a minimum Node version in its configuration and this script is invoked by Tauri's beforeBuildCommand with the system node binary, developers with older Node installations will encounter build failures before packaging starts.

Proposed compatibility fix
 import { cpSync, existsSync, mkdirSync, rmSync } from "node:fs";
-import { join, resolve } from "node:path";
+import { dirname, join, resolve } from "node:path";
 import { spawnSync } from "node:child_process";
+import { fileURLToPath } from "node:url";
 
-const rootDir = resolve(import.meta.dirname, "../../..");
+const moduleDir =
+  typeof import.meta.dirname === "string"
+    ? import.meta.dirname
+    : dirname(fileURLToPath(import.meta.url));
+const rootDir = resolve(moduleDir, "../../..");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const rootDir = resolve(import.meta.dirname, "../../..");
import { cpSync, existsSync, mkdirSync, rmSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import { spawnSync } from "node:child_process";
import { fileURLToPath } from "node:url";
const moduleDir =
typeof import.meta.dirname === "string"
? import.meta.dirname
: dirname(fileURLToPath(import.meta.url));
const rootDir = resolve(moduleDir, "../../..");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/scripts/before-build.mjs` at line 5, The script uses
import.meta.dirname to compute rootDir which fails on Node < v20.11; update the
rootDir calculation in before-build.mjs to safely fall back when
import.meta.dirname is unavailable by detecting its presence and otherwise
computing dirname from fileURLToPath(import.meta.url) (using url.fileURLToPath
and path.dirname) before calling resolve; reference the rootDir variable and
import.meta.dirname and ensure any required imports (path and url/fileURLToPath)
are added so the script works across older Node runtimes invoked by Tauri's
beforeBuildCommand.


function run(command, args, options = {}) {
const result = spawnSync(command, args, {
stdio: "inherit",
cwd: rootDir,
env: process.env,
shell: process.platform === "win32",
...options,
});

if (result.status !== 0) {

@cubic-dev-ai cubic-dev-ai Bot Mar 3, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: Missing result.error check: if spawnSync fails to launch the process (e.g., command not on PATH), result.status is null and result.error holds the reason, but stdio: "inherit" won't surface it. The script will silently process.exit(1) with no diagnostic output, making CI failures hard to debug. Check result.error and log it before exiting.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/scripts/before-build.mjs, line 16:

<comment>Missing `result.error` check: if `spawnSync` fails to launch the process (e.g., command not on `PATH`), `result.status` is `null` and `result.error` holds the reason, but `stdio: "inherit"` won't surface it. The script will silently `process.exit(1)` with no diagnostic output, making CI failures hard to debug. Check `result.error` and log it before exiting.</comment>

<file context>
@@ -0,0 +1,72 @@
+    ...options,
+  });
+
+  if (result.status !== 0) {
+    process.exit(result.status ?? 1);
+  }
</file context>
Fix with Cubic

process.exit(result.status ?? 1);
}
}

run("bun", ["--filter", "web", "build"], {
env: {
...process.env,
BUILD_TARGET: "desktop",
},
});

let targetTriple = process.env.TARGET_TRIPLE;
if (!targetTriple) {
const rustc = spawnSync("rustc", ["-vV"], {
cwd: rootDir,
encoding: "utf-8",
shell: process.platform === "win32",
});

if (rustc.status !== 0) {
process.exit(rustc.status ?? 1);
}

const hostLine = rustc.stdout
.split("\n")
.find((line) => line.startsWith("host:"));

if (!hostLine) {
console.error("Unable to detect rust host triple from `rustc -vV`.");
process.exit(1);
}

targetTriple = hostLine.replace("host:", "").trim();
}

run("cargo", ["build", "--release", "--bin", "api", "--target", targetTriple]);

const binExt = targetTriple.includes("windows") ? ".exe" : "";
const binariesDir = join(rootDir, "apps/desktop/src-tauri/binaries");
mkdirSync(binariesDir, { recursive: true });

const fromSidecar = join(rootDir, `target/${targetTriple}/release/api${binExt}`);
const toSidecar = join(binariesDir, `api-${targetTriple}${binExt}`);
cpSync(fromSidecar, toSidecar);
console.log(`Prepared sidecar: ${toSidecar}`);

const webOut = join(rootDir, "apps/web/out");
const sidecarWebOut = join(binariesDir, "web-out");

if (existsSync(webOut)) {
rmSync(sidecarWebOut, { recursive: true, force: true });
cpSync(webOut, sidecarWebOut, { recursive: true });
console.log(`Copied web static export to: ${sidecarWebOut}`);
} else {
console.warn(`Warning: ${webOut} not found, skipping web static copy`);
}
4 changes: 2 additions & 2 deletions apps/desktop/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"identifier": "com.atmos.desktop",
"build": {
"beforeDevCommand": "bun --filter web dev",
"beforeBuildCommand": "BUILD_TARGET=desktop bun --filter web build && bash ./scripts/prepare-sidecar.sh",
"beforeBuildCommand": "node ./scripts/before-build.mjs",
"devUrl": "http://localhost:3030",
"frontendDist": "../../web/out"
},
Expand Down Expand Up @@ -36,7 +36,7 @@
}
},
"bundle": {
"active": false,
"active": true,
"targets": "all",
"icon": ["icons/icon.svg"],
"externalBin": [
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src-tauri/tauri.debug.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"build": {
"beforeDevCommand": "",
"devUrl": "http://localhost:3030",
"beforeBuildCommand": "BUILD_TARGET=desktop bun --filter web build && bash ./scripts/prepare-sidecar.sh",
"beforeBuildCommand": "node ./scripts/before-build.mjs",
"frontendDist": "../../web/out"
},
"app": {
Expand Down
Loading