diff --git a/.gitignore b/.gitignore index 0cdac6d89..33b20b217 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,18 @@ package-lock.json # Generated extension bridges (created by scripts/generate-ext-bridge.mjs) electron/extensions/_ext-bridge.generated.ts src/extensions/_ext-bridge.generated.ts + +# Allow committing release binaries when explicitly staged under artifacts/releases/. +!artifacts/ +artifacts/** +!artifacts/releases/ +!artifacts/releases/** +!artifacts/releases/**/*.exe +!artifacts/releases/**/*.msi +!artifacts/releases/**/*.zip +!artifacts/releases/**/*.yml +!artifacts/releases/**/*.blockmap +!artifacts/releases/**/*.dmg +!artifacts/releases/**/*.AppImage +!artifacts/releases/**/*.deb +!artifacts/releases/**/*.rpm diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 000000000..9b30f0ea9 --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,23 @@ +# DeskClaw — Windows Builds (Installer / Portable) + +This repository tracks source code. If you explicitly want Windows binaries committed into git, stage them under `artifacts/releases/win/`. + +## Build on Windows + +```powershell +corepack enable +corepack prepare pnpm@10.31.0 --activate +pnpm run init +pnpm run package:win +node scripts/stage-release-artifacts.mjs --platform=win +git add artifacts/releases/win +git commit -m "chore(release): add windows artifacts" +git push +``` + +## Notes + +- `package:win` outputs to `release/` (gitignored). +- `stage-release-artifacts.mjs` copies files from `release/` into `artifacts/releases/win/` and writes a `manifest.json`. +- Committing binaries will significantly increase repo size; prefer Releases if possible. + diff --git a/package.json b/package.json index 9c39b4fea..f9093721e 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,8 @@ "package:mac": "pnpm run package && electron-builder --mac --publish never", "package:mac:local": "SKIP_PREINSTALLED_SKILLS=1 pnpm run package && electron-builder --mac --publish never", "package:win": "pnpm run prep:win-binaries && pnpm run package && electron-builder --win --publish never", + "stage:artifacts:win": "node scripts/stage-release-artifacts.mjs --platform=win", + "package:win:artifacts": "pnpm run package:win && pnpm run stage:artifacts:win", "package:linux": "pnpm run package && electron-builder --linux --publish never", "release": "pnpm run uv:download && pnpm run package && electron-builder --publish always", "version": "node scripts/assert-release-version.mjs", diff --git a/scripts/stage-release-artifacts.mjs b/scripts/stage-release-artifacts.mjs new file mode 100644 index 000000000..706cb24d4 --- /dev/null +++ b/scripts/stage-release-artifacts.mjs @@ -0,0 +1,66 @@ +import { mkdir, readdir, rm, copyFile, stat, writeFile } from 'node:fs/promises' +import { join, resolve } from 'node:path' + +function parseArgs(argv) { + const args = {} + for (const raw of argv.slice(2)) { + if (!raw.startsWith('--')) continue + const [k, v] = raw.slice(2).split('=') + args[k] = v ?? true + } + return args +} + +async function exists(p) { + try { + await stat(p) + return true + } catch { + return false + } +} + +async function main() { + const args = parseArgs(process.argv) + const platform = typeof args.platform === 'string' ? args.platform : 'unknown' + + const repoRoot = resolve(process.cwd()) + const fromDir = join(repoRoot, 'release') + const toDir = join(repoRoot, 'artifacts', 'releases', platform) + + if (!(await exists(fromDir))) { + throw new Error(`Missing release/ directory at: ${fromDir}`) + } + + await mkdir(toDir, { recursive: true }) + + const entries = await readdir(fromDir) + const copied = [] + + for (const name of entries) { + const src = join(fromDir, name) + const st = await stat(src) + if (!st.isFile()) continue + + const dst = join(toDir, name) + await copyFile(src, dst) + copied.push({ name, size: st.size }) + } + + const manifest = { + platform, + sourceDir: 'release', + destDir: `artifacts/releases/${platform}`, + files: copied.sort((a, b) => a.name.localeCompare(b.name)), + createdAt: new Date().toISOString(), + } + + await writeFile(join(toDir, 'manifest.json'), JSON.stringify(manifest, null, 2), 'utf8') + await rm(fromDir, { recursive: true, force: true }) +} + +main().catch((err) => { + console.error(err) + process.exit(1) +}) +