From 065387ba351db9dcd7296719166f2c67d123533c Mon Sep 17 00:00:00 2001 From: quueli Date: Wed, 8 Apr 2026 18:51:14 +0300 Subject: [PATCH 1/6] feat(windows): port desktop build, CI job, postinstall, release artifacts - Cross-platform postinstall (Bun) + node-pty Spectre patch for Windows - copy-native-modules: unlink symlinks, robocopy, repair @superset workspace dirs - build-desktop: windows-latest NSIS x64 job - release-desktop: stable Superset-x64.exe copy for latest download URLs - electron-builder publish target quueli/superset-windows - README: fork banner, Windows docs, release how-to, contributing --- .github/workflows/build-desktop.yml | 119 ++++++++++++++++++++ .github/workflows/release-desktop.yml | 8 ++ README.md | 93 ++++++++++++--- apps/desktop/electron-builder.ts | 4 +- apps/desktop/package.json | 4 +- apps/desktop/scripts/copy-native-modules.ts | 115 +++++++++++++++++-- package.json | 5 +- scripts/patch-node-pty-spectre-windows.ts | 43 +++++++ scripts/postinstall.ts | 38 +++++++ 9 files changed, 395 insertions(+), 34 deletions(-) create mode 100644 scripts/patch-node-pty-spectre-windows.ts create mode 100644 scripts/postinstall.ts diff --git a/.github/workflows/build-desktop.yml b/.github/workflows/build-desktop.yml index b32ea6a59fd..f2af6569a25 100644 --- a/.github/workflows/build-desktop.yml +++ b/.github/workflows/build-desktop.yml @@ -261,3 +261,122 @@ jobs: path: apps/desktop/release/*-linux.yml retention-days: ${{ inputs.artifact_retention_days }} if-no-files-found: error + + build-windows: + name: Build - Windows (x64) + runs-on: windows-latest + environment: production + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Enable Git long paths + run: git config --global core.longpaths true + + - name: Setup Bun + id: setup-bun + uses: oven-sh/setup-bun@v2 + with: + bun-version-file: .bun-version + + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: | + ~/.bun/install/cache + key: ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-bun-${{ steps.setup-bun.outputs.bun-revision }}- + + - name: Install dependencies + run: bun install --frozen --ignore-scripts + + - name: Install desktop native dependencies + working-directory: apps/desktop + run: bun run install:deps + + - name: Set version suffix + if: inputs.version_suffix != '' + working-directory: apps/desktop + shell: bash + run: | + CURRENT_VERSION=$(node -p "require('./package.json').version") + NEW_VERSION="${CURRENT_VERSION}${{ inputs.version_suffix }}" + echo "Setting version to: $NEW_VERSION" + node -e " + const fs = require('fs'); + const pkg = require('./package.json'); + pkg.version = '$NEW_VERSION'; + fs.writeFileSync('./package.json', JSON.stringify(pkg, null, '\t') + '\n'); + " + echo "Updated package.json version to $NEW_VERSION" + + - name: Clean dev folder + working-directory: apps/desktop + run: bun run clean:dev + + - name: Generate file icons + working-directory: apps/desktop + run: bun run generate:icons + + - name: Compile app with electron-vite + working-directory: apps/desktop + env: + NEXT_PUBLIC_POSTHOG_KEY: ${{ secrets.NEXT_PUBLIC_POSTHOG_KEY }} + NEXT_PUBLIC_POSTHOG_HOST: ${{ secrets.NEXT_PUBLIC_POSTHOG_HOST }} + GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }} + GH_CLIENT_ID: ${{ secrets.GH_CLIENT_ID }} + NEXT_PUBLIC_WEB_URL: ${{ secrets.NEXT_PUBLIC_WEB_URL }} + NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }} + NEXT_PUBLIC_DOCS_URL: ${{ secrets.NEXT_PUBLIC_DOCS_URL }} + NEXT_PUBLIC_STREAMS_URL: ${{ secrets.NEXT_PUBLIC_STREAMS_URL }} + NEXT_PUBLIC_ELECTRIC_URL: ${{ secrets.NEXT_PUBLIC_ELECTRIC_URL }} + SENTRY_DSN_DESKTOP: ${{ secrets.SENTRY_DSN_DESKTOP }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SUPERSET_WORKSPACE_NAME: superset + run: bun run compile:app + + - name: Build Electron app + working-directory: apps/desktop + env: + CSC_IDENTITY_AUTO_DISCOVERY: "false" + run: bun run package -- --publish never --config ${{ inputs.electron_builder_config }} + + - name: Verify Windows NSIS + update manifest exist + working-directory: apps/desktop + shell: bash + run: | + ls -la release + test -n "$(ls -1 release/*-x64.exe 2>/dev/null | grep -v __uninstaller || true)" || { + echo "::error::No NSIS installer (*.exe) generated in apps/desktop/release" + exit 1 + } + test -f release/latest.yml || { + echo "::error::latest.yml missing from apps/desktop/release — auto-update may be broken" + exit 1 + } + + - name: Upload NSIS installer + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.artifact_prefix }}-win-x64-nsis + path: apps/desktop/release/*-x64.exe + retention-days: ${{ inputs.artifact_retention_days }} + if-no-files-found: error + + - name: Upload Windows block map + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.artifact_prefix }}-win-x64-blockmap + path: apps/desktop/release/*.blockmap + retention-days: ${{ inputs.artifact_retention_days }} + if-no-files-found: warn + + - name: Upload Windows auto-update manifest + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.artifact_prefix }}-win-x64-update-manifest + path: apps/desktop/release/latest.yml + retention-days: ${{ inputs.artifact_retention_days }} + if-no-files-found: error diff --git a/.github/workflows/release-desktop.yml b/.github/workflows/release-desktop.yml index 717b1a3806d..d98a248a48a 100644 --- a/.github/workflows/release-desktop.yml +++ b/.github/workflows/release-desktop.yml @@ -107,6 +107,14 @@ jobs: break fi done + # Windows NSIS: stable name for /releases/latest/download/Superset-x64.exe + for file in *-x64.exe; do + if [[ -f "$file" && "$file" != *"__uninstaller"* ]]; then + cp "$file" "Superset-x64.exe" + echo "Created stable copy: Superset-x64.exe" + break + fi + done echo "Release artifacts:" ls -la diff --git a/README.md b/README.md index 86ef7998d8a..fb786aed848 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,10 @@ ### The Code Editor for AI Agents -[![GitHub stars](https://img.shields.io/github/stars/superset-sh/superset?style=flat&logo=github)](https://github.com/superset-sh/superset/stargazers) -[![GitHub release](https://img.shields.io/github/v/release/superset-sh/superset?style=flat&logo=github)](https://github.com/superset-sh/superset/releases) +**Fork [quueli/superset-windows](https://github.com/quueli/superset-windows)** — Windows 10+ сборка десктопа, кроссплатформенный `postinstall`, job CI для Windows. Upstream: [superset-sh/superset](https://github.com/superset-sh/superset). + +[![GitHub stars](https://img.shields.io/github/stars/quueli/superset-windows?style=flat&logo=github)](https://github.com/quueli/superset-windows/stargazers) +[![GitHub release](https://img.shields.io/github/v/release/quueli/superset-windows?style=flat&logo=github)](https://github.com/quueli/superset-windows/releases) [![License](https://img.shields.io/github/license/superset-sh/superset?style=flat)](LICENSE.md) [![Twitter](https://img.shields.io/badge/@superset__sh-555?logo=x)](https://x.com/superset_sh) [![Discord](https://img.shields.io/badge/Discord-555?logo=discord)](https://discord.gg/cZeD9WYcV7) @@ -17,7 +19,7 @@ Works with any CLI agent. Built for local worktree-based development.
-[**Download for macOS**](https://github.com/superset-sh/superset/releases/latest)  •  [Documentation](https://docs.superset.sh)  •  [Changelog](https://github.com/superset-sh/superset/releases)  •  [Discord](https://discord.gg/cZeD9WYcV7) +[**Windows installer (x64)**](https://github.com/quueli/superset-windows/releases/latest)  •  [**macOS (upstream)**](https://github.com/superset-sh/superset/releases/latest)  •  [Documentation](https://docs.superset.sh)  •  [Changelog (upstream)](https://github.com/superset-sh/superset/releases)  •  [Discord](https://discord.gg/cZeD9WYcV7)
@@ -71,7 +73,7 @@ If it runs in a terminal, it runs on Superset | Requirement | Details | |:------------|:--------| -| **OS** | macOS (Windows/Linux untested) | +| **OS** | **Windows 10+ x64** (сборка из этого форка). macOS / Linux — как у upstream; для Windows включите `git config --global core.longpaths true` перед клоном при ошибках длинных путей. | | **Runtime** | [Bun](https://bun.sh/) v1.0+ | | **Version Control** | Git 2.20+ | | **GitHub CLI** | [gh](https://cli.github.com/) | @@ -81,7 +83,8 @@ If it runs in a terminal, it runs on Superset ### Quick Start (Pre-built) -**[Download Superset for macOS](https://github.com/superset-sh/superset/releases/latest)** +- **Windows x64:** [последний релиз форка](https://github.com/quueli/superset-windows/releases/latest) — установщик NSIS (`Superset-*-x64.exe` или стабильное имя `Superset-x64.exe` в релизе). +- **macOS:** [официальные сборки upstream](https://github.com/superset-sh/superset/releases/latest). ### Build from Source @@ -91,10 +94,14 @@ If it runs in a terminal, it runs on Superset **1. Clone the repository** ```bash -git clone https://github.com/superset-sh/superset.git -cd superset +git clone https://github.com/quueli/superset-windows.git +cd superset-windows ``` +На **Windows** перед клоном (при ошибке «Filename too long»): `git config --global core.longpaths true`. + +Для нативных модулей десктопа на Windows нужны **Visual Studio Build Tools** с рабочей нагрузкой **Desktop development with C++** (MSVC + Windows SDK). + **2. Set up environment variables** (choose one): Option A: Full setup @@ -127,11 +134,62 @@ bun run dev ```bash bun run build -open apps/desktop/release +``` + +Артефакты: `apps/desktop/release/` — на Windows установщик **NSIS** `*-x64.exe`, на macOS `.dmg` / `.zip`, на Linux `.AppImage`. + +Локально только Windows-инсталлятор: + +```bash +cd apps/desktop +bun run clean:dev && bun run generate:icons && bun run compile:app +set CSC_IDENTITY_AUTO_DISCOVERY=false # cmd +# PowerShell: $env:CSC_IDENTITY_AUTO_DISCOVERY='false' +bun run package ``` +## Releases in this fork / Релизы в форке + +GitHub Actions собирает **macOS**, **Linux** и **Windows (x64)**. Финальный **GitHub Release** с файлами создаётся **только при push тега** вида `desktop-v*.*.*` (например `desktop-v1.4.8`). Job `release` не запускается от обычного push в ветку. + +### Вариант A — релиз через тег (рекомендуется) + +1. Убедитесь, что секреты для environment **`production`** в репозитории заданы (как у upstream: переменные для `compile:app`, при необходимости Sentry и т.д.). Без них шаг компиляции в CI может упасть. +2. Обновите версию в [`apps/desktop/package.json`](apps/desktop/package.json) (`version`), закоммитьте. +3. Создайте и отправьте тег: + +```bash +git checkout main +git pull origin main +git tag desktop-v1.4.8 +git push origin desktop-v1.4.8 +``` + +4. Откройте **Actions** → workflow **Release Desktop App** → дождитесь окончания job **build** (все платформы) и **release**. +5. В репозитории появится **черновик** релиза (draft). Проверьте вложения (`.dmg`, `.AppImage`, `.exe`, манифесты), затем нажмите **Publish release**. + +Стабильные имена для прямых ссылок (скрипт релиза создаёт копии): например `Superset-x64.exe`, `Superset-arm64.dmg`, `latest-linux.yml`. + +### Вариант B — только сборка без автоматического релиза + +В **Actions** запустите **Release Desktop App** вручную (**Run workflow**). Соберутся артефакты для скачивания из вкладки run, но шаг **Create GitHub Release** выполняется только при условии `refs/tags/desktop-v*` — для полноценного релиза всё равно используйте тег из варианта A. + +### Вариант C — локальная сборка и ручная загрузка + +Соберите `apps/desktop/release/*` локально (см. выше), затем в GitHub: **Releases** → **Draft a new release** → прикрепите файлы и опубликуйте. + +### Синхронизация с upstream + +```bash +git remote add upstream https://github.com/superset-sh/superset.git # один раз +git fetch upstream +git checkout main +git merge upstream/main +# разрешите конфликты, проверьте сборку, затем push в origin +``` + ## Keyboard Shortcuts All shortcuts are customizable via **Settings > Keyboard Shortcuts** (`⌘/`). See [full documentation](https://docs.superset.sh/keyboard-shortcuts). @@ -230,17 +288,17 @@ This repo uses the published upstream `mastracode` and `@mastra/*` packages dire ## Contributing -We welcome contributions! If you have a suggestion that would make Superset better: +Contributions to **this fork** (Windows, CI, документация): -1. Fork the repository -2. Create your feature branch (`git checkout -b feature/amazing-feature`) -3. Commit your changes (`git commit -m 'Add amazing feature'`) -4. Push to the branch (`git push origin feature/amazing-feature`) -5. Open a Pull Request +1. Клонируйте [quueli/superset-windows](https://github.com/quueli/superset-windows) (или свой форк от него). +2. Ветка фичи: `git checkout -b feature/amazing-feature` +3. Коммит: `git commit -m 'Add amazing feature'` +4. Пуш: `git push origin feature/amazing-feature` +5. Откройте **Pull Request в `quueli/superset-windows`**. -You can also [open issues](https://github.com/superset-sh/superset/issues) for bugs or feature requests. +Issues и обсуждения по **апстриму**: [superset-sh/superset/issues](https://github.com/superset-sh/superset/issues). По сборке Windows и релизам форка удобнее заводить issue в [quueli/superset-windows/issues](https://github.com/quueli/superset-windows/issues). -See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed instructions and code of conduct. +Общие правила проекта: [CONTRIBUTING.md](CONTRIBUTING.md) (ориентир — upstream). @@ -252,7 +310,8 @@ Join the Superset community to get help, share feedback, and connect with other - **[Discord](https://discord.gg/cZeD9WYcV7)** — Chat with the team and community - **[Twitter](https://x.com/superset_sh)** — Follow for updates and announcements -- **[GitHub Issues](https://github.com/superset-sh/superset/issues)** — Report bugs and request features +- **[GitHub Issues (upstream)](https://github.com/superset-sh/superset/issues)** — Report bugs and request features +- **[Issues (this fork)](https://github.com/quueli/superset-windows/issues)** — Windows build / fork-specific - **[GitHub Discussions](https://github.com/superset-sh/superset/discussions)** — Ask questions and share ideas ### Team diff --git a/apps/desktop/electron-builder.ts b/apps/desktop/electron-builder.ts index 8b08ddd17ba..5da6da6e064 100644 --- a/apps/desktop/electron-builder.ts +++ b/apps/desktop/electron-builder.ts @@ -32,8 +32,8 @@ const config: Configuration = { // Generate latest-mac.yml for auto-update (workflow handles actual upload) publish: { provider: "github", - owner: "superset-sh", - repo: "superset", + owner: "quueli", + repo: "superset-windows", }, // Directories diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 93471c4e10d..5e723ed2f1a 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -7,7 +7,7 @@ "resources": "src/resources", "repository": { "type": "git", - "url": "https://github.com/superset-sh/superset.git" + "url": "https://github.com/quueli/superset-windows.git" }, "author": { "name": "Superset", @@ -26,6 +26,8 @@ "build": "cross-env CSC_IDENTITY_AUTO_DISCOVERY=false electron-builder --publish never", "prepackage": "bun run copy:native-modules && bun run validate:native-runtime", "package": "electron-builder --config electron-builder.ts", + "patch:node-pty-win-spectre": "bun ../../scripts/patch-node-pty-spectre-windows.ts", + "preinstall:deps": "bun run patch:node-pty-win-spectre", "install:deps": "electron-builder install-app-deps", "release": "electron-builder --publish always", "clean:dev": "rimraf ./node_modules/.dev", diff --git a/apps/desktop/scripts/copy-native-modules.ts b/apps/desktop/scripts/copy-native-modules.ts index 3b34f3ecc75..ed24a0b49ee 100644 --- a/apps/desktop/scripts/copy-native-modules.ts +++ b/apps/desktop/scripts/copy-native-modules.ts @@ -13,7 +13,7 @@ * This is safe because bun install will recreate the symlinks on next install. */ -import { execSync } from "node:child_process"; +import { execSync, spawnSync } from "node:child_process"; import { cpSync, existsSync, @@ -23,6 +23,7 @@ import { readFileSync, realpathSync, rmSync, + unlinkSync, } from "node:fs"; import { dirname, join } from "node:path"; import { satisfies } from "semver"; @@ -34,10 +35,64 @@ import { requiredMaterializedNodeModules } from "../runtime-dependencies"; const TARGET_ARCH = process.env.TARGET_ARCH || process.arch; const TARGET_PLATFORM = process.env.TARGET_PLATFORM || process.platform; +/** + * Deep copy of a directory tree. On Windows, Bun's cpSync can hit EPERM when the + * tree contains nested symlinks (e.g. workspace packages); robocopy follows files reliably. + */ +function copyDirectoryTree(src: string, dest: string): void { + if (process.platform === "win32") { + mkdirSync(dest, { recursive: true }); + const st = spawnSync( + "robocopy", + [ + src, + dest, + "/E", + "/COPY:DAT", + "/R:2", + "/W:1", + "/NFL", + "/NDL", + "/NJH", + "/NJS", + ], + { stdio: "pipe", encoding: "utf8", windowsHide: true }, + ); + const code = st.status ?? 0; + if (code >= 8) { + throw new Error( + `robocopy failed (${code}): ${st.stderr ?? st.stdout ?? ""}`, + ); + } + return; + } + cpSync(src, dest, { recursive: true }); +} + function getWorkspaceRootNodeModulesDir(nodeModulesDir: string): string { return join(nodeModulesDir, "..", "..", "..", "node_modules"); } +/** Repo root: apps/desktop/node_modules -> ../../../ */ +function getMonorepoRootFromDesktopNodeModules(nodeModulesDir: string): string { + return join(nodeModulesDir, "..", "..", ".."); +} + +/** Workspace `packages/` for `@superset/` (e.g. macos-process-metrics). */ +function resolveWorkspaceSupersetPackageDir( + nodeModulesDir: string, + moduleName: string, +): string | null { + if (!moduleName.startsWith("@superset/")) return null; + const shortName = moduleName.slice("@superset/".length); + const candidate = join( + getMonorepoRootFromDesktopNodeModules(nodeModulesDir), + "packages", + shortName, + ); + return existsSync(join(candidate, "package.json")) ? candidate : null; +} + function getBunFlatNodeModulesDir(nodeModulesDir: string): string { return join( getWorkspaceRootNodeModulesDir(nodeModulesDir), @@ -77,7 +132,7 @@ function copyModuleIfSymlink( if (existsSync(bunFlatModulePath)) { console.log(` ${moduleName}: materializing from Bun store index`); mkdirSync(dirname(modulePath), { recursive: true }); - cpSync(realpathSync(bunFlatModulePath), modulePath, { recursive: true }); + copyDirectoryTree(realpathSync(bunFlatModulePath), modulePath); console.log(` Copied to: ${modulePath}`); return true; } @@ -97,13 +152,43 @@ function copyModuleIfSymlink( console.log(` ${moduleName}: symlink -> replacing with real files`); console.log(` Real path: ${realPath}`); - // Remove the symlink - rmSync(modulePath); + // Remove the symlink/junction (unlink avoids Bun/Windows EFAULT from rmSync on links) + try { + unlinkSync(modulePath); + } catch { + rmSync(modulePath, { recursive: true, maxRetries: 3, force: true }); + } // Copy the actual files - cpSync(realPath, modulePath, { recursive: true }); + copyDirectoryTree(realPath, modulePath); console.log(` Copied to: ${modulePath}`); + } else if (!existsSync(join(modulePath, "package.json"))) { + // Leftover empty dir (e.g. failed copy) — materialize from workspace or Bun store + const workspaceSrc = resolveWorkspaceSupersetPackageDir( + nodeModulesDir, + moduleName, + ); + if (workspaceSrc) { + console.log( + ` ${moduleName}: repairing broken/empty install from workspace`, + ); + rmSync(modulePath, { recursive: true, maxRetries: 3, force: true }); + copyDirectoryTree(workspaceSrc, modulePath); + console.log(` Copied to: ${modulePath}`); + } else if (existsSync(bunFlatModulePath)) { + console.log( + ` ${moduleName}: repairing broken/empty install from Bun store`, + ); + rmSync(modulePath, { recursive: true, maxRetries: 3, force: true }); + copyDirectoryTree(realpathSync(bunFlatModulePath), modulePath); + console.log(` Copied to: ${modulePath}`); + } else if (required) { + console.error( + ` [ERROR] ${moduleName} at ${modulePath} has no package.json and no repair source`, + ); + process.exit(1); + } } else { console.log(` ${moduleName}: already real directory (not a symlink)`); } @@ -143,7 +228,7 @@ function copyExactModuleVersion( ); if (existsSync(sourcePath)) { mkdirSync(dirname(destPath), { recursive: true }); - cpSync(sourcePath, destPath, { recursive: true }); + copyDirectoryTree(sourcePath, destPath); console.log(` Copied ${moduleName}@${version} to: ${destPath}`); return true; } @@ -203,10 +288,16 @@ function copyDependencyForPackage( const nestedStats = lstatSync(nestedDependencyPath); if (nestedStats.isSymbolicLink()) { const realPath = realpathSync(nestedDependencyPath); - rmSync(nestedDependencyPath); - cpSync(realPath, nestedDependencyPath, { - recursive: true, - }); + try { + unlinkSync(nestedDependencyPath); + } catch { + rmSync(nestedDependencyPath, { + recursive: true, + maxRetries: 3, + force: true, + }); + } + copyDirectoryTree(realPath, nestedDependencyPath); } return; } @@ -315,7 +406,7 @@ function copyAstGrepPlatformPackages(nodeModulesDir: string): void { if (existsSync(sourcePath)) { console.log(` ${platformPkg.name}: copying from Bun store`); mkdirSync(dirname(destPath), { recursive: true }); - cpSync(sourcePath, destPath, { recursive: true }); + copyDirectoryTree(sourcePath, destPath); if (isTargetPkg) resolvedTargetPackage = true; continue; } @@ -458,7 +549,7 @@ function copyParcelWatcherPlatformPackages(nodeModulesDir: string): void { console.log(` ${platformPkg.name}: copying from Bun store`); mkdirSync(dirname(destPath), { recursive: true }); - cpSync(sourcePath, destPath, { recursive: true }); + copyDirectoryTree(sourcePath, destPath); resolvedPlatformPackage = true; } diff --git a/package.json b/package.json index 2cef5488f9f..631c7fce8d4 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,8 @@ "name": "@superset/repo", "version": "0.0.0", "repository": { - "type": "git" + "type": "git", + "url": "https://github.com/quueli/superset-windows.git" }, "devDependencies": { "@biomejs/biome": "2.4.2", @@ -30,7 +31,7 @@ "format:check": "bunx @biomejs/biome@2.4.2 format .", "typecheck": "turbo typecheck", "ui-add": "turbo run ui-add", - "postinstall": "./scripts/postinstall.sh", + "postinstall": "bun scripts/postinstall.ts", "clean": "git clean -xdf node_modules", "clean:workspaces": "turbo clean", "release:desktop": "./apps/desktop/create-release.sh", diff --git a/scripts/patch-node-pty-spectre-windows.ts b/scripts/patch-node-pty-spectre-windows.ts new file mode 100644 index 00000000000..1dd820020e6 --- /dev/null +++ b/scripts/patch-node-pty-spectre-windows.ts @@ -0,0 +1,43 @@ +/** + * node-pty enables MSVC Spectre mitigation in its gyp files, which requires + * optional "Spectre-mitigated libs" in VS Build Tools. Many Windows dev setups + * omit those; disabling mitigation matches relaxed local builds and fixes MSB8040. + */ +import { readFileSync, writeFileSync } from "node:fs"; +import { createRequire } from "node:module"; +import { dirname, join } from "node:path"; + +export function patchNodePtySpectreForWindows(): void { + if (process.platform !== "win32") { + return; + } + + let nodePtyDir: string; + try { + const req = createRequire(join(process.cwd(), "apps/desktop/package.json")); + const pkgJson = req.resolve("node-pty/package.json"); + nodePtyDir = dirname(pkgJson); + } catch { + return; + } + + const files = [ + join(nodePtyDir, "binding.gyp"), + join(nodePtyDir, "deps", "winpty", "src", "winpty.gyp"), + ]; + + for (const file of files) { + try { + const before = readFileSync(file, "utf8"); + const after = before.replaceAll( + "'SpectreMitigation': 'Spectre'", + "'SpectreMitigation': 'false'", + ); + if (after !== before) { + writeFileSync(file, after); + } + } catch { + // Optional paths (e.g. layout change) — ignore. + } + } +} diff --git a/scripts/postinstall.ts b/scripts/postinstall.ts new file mode 100644 index 00000000000..4196fdd1f9b --- /dev/null +++ b/scripts/postinstall.ts @@ -0,0 +1,38 @@ +/** + * Cross-platform postinstall (replaces postinstall.sh for Windows). + * Keeps the same behavior: sherif validation, then desktop native deps (non-CI). + */ +import { spawnSync } from "node:child_process"; +import { patchNodePtySpectreForWindows } from "./patch-node-pty-spectre-windows.ts"; + +if (process.env.SUPERSET_POSTINSTALL_RUNNING) { + process.exit(0); +} +process.env.SUPERSET_POSTINSTALL_RUNNING = "1"; + +function run(cmd: string, args: string[]): number { + const r = spawnSync(cmd, args, { + stdio: "inherit", + shell: process.platform === "win32", + env: process.env, + }); + return r.status ?? (r.error ? 1 : 0); +} + +const sherifExit = run("bunx", ["sherif"]); +if (sherifExit !== 0) { + process.exit(sherifExit); +} + +if (process.env.CI) { + process.exit(0); +} + +patchNodePtySpectreForWindows(); + +const depsExit = run("bun", [ + "run", + "--filter=@superset/desktop", + "install:deps", +]); +process.exit(depsExit); From f79a573716ac2ebfbfab5aa9ce6fb8083e850925 Mon Sep 17 00:00:00 2001 From: quueli Date: Wed, 8 Apr 2026 18:51:14 +0300 Subject: [PATCH 2/6] chore(desktop): bump version to 1.4.8 for fork release --- apps/desktop/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 5e723ed2f1a..9b2dc7ad19a 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -2,7 +2,7 @@ "name": "@superset/desktop", "productName": "Superset", "description": "The last developer tool you'll ever need", - "version": "1.4.7", + "version": "1.4.8", "main": "./dist/main/index.js", "resources": "src/resources", "repository": { From 05b7f7edc9c54b369f6561d18f5ac5312a633260 Mon Sep 17 00:00:00 2001 From: quueli Date: Wed, 8 Apr 2026 18:58:30 +0300 Subject: [PATCH 3/6] ci(windows): enable core.longpaths before checkout (fix MAX_PATH) --- .github/workflows/build-desktop.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-desktop.yml b/.github/workflows/build-desktop.yml index f2af6569a25..f2adb765169 100644 --- a/.github/workflows/build-desktop.yml +++ b/.github/workflows/build-desktop.yml @@ -268,12 +268,13 @@ jobs: environment: production steps: - - name: Checkout code - uses: actions/checkout@v4 - + # Must run before checkout: clone fails on deep paths otherwise (MAX_PATH). - name: Enable Git long paths run: git config --global core.longpaths true + - name: Checkout code + uses: actions/checkout@v4 + - name: Setup Bun id: setup-bun uses: oven-sh/setup-bun@v2 From f942ab2cc7afe00e56e1142093a77a024bb7b26d Mon Sep 17 00:00:00 2001 From: quueli Date: Wed, 8 Apr 2026 19:10:49 +0300 Subject: [PATCH 4/6] ci(windows): GIT_CONFIG_* + registry for long paths before checkout --- .github/workflows/build-desktop.yml | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-desktop.yml b/.github/workflows/build-desktop.yml index f2adb765169..83540f3fd81 100644 --- a/.github/workflows/build-desktop.yml +++ b/.github/workflows/build-desktop.yml @@ -266,11 +266,25 @@ jobs: name: Build - Windows (x64) runs-on: windows-latest environment: production + # Applies to Git spawned by actions/checkout (Git 2.31+). Shell-only config is too late for checkout. + env: + GIT_CONFIG_COUNT: 1 + GIT_CONFIG_KEY_0: core.longpaths + GIT_CONFIG_VALUE_0: "true" steps: - # Must run before checkout: clone fails on deep paths otherwise (MAX_PATH). - - name: Enable Git long paths - run: git config --global core.longpaths true + # OS + global config (redundant with env above; helps older Git / edge cases). + - name: Enable Windows long paths + shell: powershell + run: | + git config --global core.longpaths true + if (-not (Test-Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem')) { exit 0 } + try { + Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -Value 1 -Type DWord -Force -ErrorAction Stop + Write-Host 'LongPathsEnabled=1 set' + } catch { + Write-Host 'Registry LongPathsEnabled skipped (no permission):' $_.Exception.Message + } - name: Checkout code uses: actions/checkout@v4 From 18f450caf22a08ea3448af86f9f99c72ec6aa3c8 Mon Sep 17 00:00:00 2001 From: quueli Date: Wed, 8 Apr 2026 19:56:40 +0300 Subject: [PATCH 5/6] Update .github/workflows/build-desktop.yml Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- .github/workflows/build-desktop.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-desktop.yml b/.github/workflows/build-desktop.yml index 83540f3fd81..e7c082436b7 100644 --- a/.github/workflows/build-desktop.yml +++ b/.github/workflows/build-desktop.yml @@ -372,13 +372,9 @@ jobs: exit 1 } - - name: Upload NSIS installer - uses: actions/upload-artifact@v4 - with: - name: ${{ inputs.artifact_prefix }}-win-x64-nsis - path: apps/desktop/release/*-x64.exe - retention-days: ${{ inputs.artifact_retention_days }} - if-no-files-found: error + path: | + apps/desktop/release/*-x64.exe + !apps/desktop/release/**/*__uninstaller*.exe - name: Upload Windows block map uses: actions/upload-artifact@v4 From df692d63687e2a361068ada4746ac6f97127fbcb Mon Sep 17 00:00:00 2001 From: quueli Date: Wed, 8 Apr 2026 20:16:52 +0300 Subject: [PATCH 6/6] fix: point metadata and auto-update to superset-sh/superset; repair Windows CI artifact upload - electron-builder publish + package.json repository URLs use canonical upstream - Restore NSIS upload step; exclude __uninstaller from artifact glob - README: English fork blurb and OS requirements (CodeRabbit) --- .github/workflows/build-desktop.yml | 6 ++++++ README.md | 4 ++-- apps/desktop/electron-builder.ts | 4 ++-- apps/desktop/package.json | 2 +- package.json | 2 +- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-desktop.yml b/.github/workflows/build-desktop.yml index e7c082436b7..ea0a150a0df 100644 --- a/.github/workflows/build-desktop.yml +++ b/.github/workflows/build-desktop.yml @@ -372,9 +372,15 @@ jobs: exit 1 } + - name: Upload Windows NSIS installer + uses: actions/upload-artifact@v4 + with: + name: ${{ inputs.artifact_prefix }}-win-x64-nsis path: | apps/desktop/release/*-x64.exe !apps/desktop/release/**/*__uninstaller*.exe + retention-days: ${{ inputs.artifact_retention_days }} + if-no-files-found: error - name: Upload Windows block map uses: actions/upload-artifact@v4 diff --git a/README.md b/README.md index fb786aed848..5d4cc67c663 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ### The Code Editor for AI Agents -**Fork [quueli/superset-windows](https://github.com/quueli/superset-windows)** — Windows 10+ сборка десктопа, кроссплатформенный `postinstall`, job CI для Windows. Upstream: [superset-sh/superset](https://github.com/superset-sh/superset). +**Fork [quueli/superset-windows](https://github.com/quueli/superset-windows)** — Windows 10+ desktop builds, cross-platform `postinstall`, and Windows CI workflows. Upstream: [superset-sh/superset](https://github.com/superset-sh/superset). [![GitHub stars](https://img.shields.io/github/stars/quueli/superset-windows?style=flat&logo=github)](https://github.com/quueli/superset-windows/stargazers) [![GitHub release](https://img.shields.io/github/v/release/quueli/superset-windows?style=flat&logo=github)](https://github.com/quueli/superset-windows/releases) @@ -73,7 +73,7 @@ If it runs in a terminal, it runs on Superset | Requirement | Details | |:------------|:--------| -| **OS** | **Windows 10+ x64** (сборка из этого форка). macOS / Linux — как у upstream; для Windows включите `git config --global core.longpaths true` перед клоном при ошибках длинных путей. | +| **OS** | **Windows 10+ x64** (builds from this fork). macOS / Linux — same as upstream. On Windows, run `git config --global core.longpaths true` **before** cloning to avoid long-path errors. | | **Runtime** | [Bun](https://bun.sh/) v1.0+ | | **Version Control** | Git 2.20+ | | **GitHub CLI** | [gh](https://cli.github.com/) | diff --git a/apps/desktop/electron-builder.ts b/apps/desktop/electron-builder.ts index 5da6da6e064..8b08ddd17ba 100644 --- a/apps/desktop/electron-builder.ts +++ b/apps/desktop/electron-builder.ts @@ -32,8 +32,8 @@ const config: Configuration = { // Generate latest-mac.yml for auto-update (workflow handles actual upload) publish: { provider: "github", - owner: "quueli", - repo: "superset-windows", + owner: "superset-sh", + repo: "superset", }, // Directories diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 9b2dc7ad19a..391a56694c7 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -7,7 +7,7 @@ "resources": "src/resources", "repository": { "type": "git", - "url": "https://github.com/quueli/superset-windows.git" + "url": "https://github.com/superset-sh/superset.git" }, "author": { "name": "Superset", diff --git a/package.json b/package.json index 631c7fce8d4..d4d19cbefbc 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "repository": { "type": "git", - "url": "https://github.com/quueli/superset-windows.git" + "url": "https://github.com/superset-sh/superset.git" }, "devDependencies": { "@biomejs/biome": "2.4.2",