Skip to content

Commit f4bd9f6

Browse files
authored
Merge pull request #37 from TrueNine/dev
Dev
2 parents dcc44c8 + a867ab4 commit f4bd9f6

File tree

224 files changed

+15237
-2357
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

224 files changed

+15237
-2357
lines changed
Lines changed: 79 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
* Version Sync Script
44
* Auto-sync all sub-package versions before commit
55
*/
6-
import { readFileSync, writeFileSync } from 'node:fs'
6+
import { readFileSync, writeFileSync, readdirSync, existsSync, statSync } from 'node:fs'
77
import { execSync } from 'node:child_process'
8-
import { resolve } from 'node:path'
8+
import { resolve, join } from 'node:path'
99
import process from 'node:process'
1010

1111
interface PackageEntry {
@@ -47,21 +47,74 @@ const packages: readonly PackageEntry[] = [
4747
{ path: 'doc/package.json', name: 'doc' },
4848
]
4949

50-
let changed = false
50+
// Discover all libraries and their npm sub-packages
51+
function discoverLibraryPackages(): PackageEntry[] {
52+
const entries: PackageEntry[] = []
53+
const librariesDir = resolve('libraries')
54+
if (!existsSync(librariesDir)) return entries
55+
for (const lib of readdirSync(librariesDir)) {
56+
const libDir = join(librariesDir, lib)
57+
if (!statSync(libDir).isDirectory()) continue
58+
const libPkg = join(libDir, 'package.json')
59+
if (existsSync(libPkg)) {
60+
entries.push({ path: `libraries/${lib}/package.json`, name: `lib:${lib}` })
61+
}
62+
}
63+
return entries
64+
}
5165

52-
for (const pkg of packages) {
53-
const fullPath = resolve(pkg.path)
54-
const content = readFileSync(fullPath, 'utf-8')
55-
const pkgJson: PackageJson = JSON.parse(content)
66+
// Discover npm platform sub-packages under a given directory (e.g. cli/npm/)
67+
function discoverNpmSubPackages(baseDir: string, prefix: string): PackageEntry[] {
68+
const entries: PackageEntry[] = []
69+
const npmDir = resolve(baseDir, 'npm')
70+
if (!existsSync(npmDir) || !statSync(npmDir).isDirectory()) return entries
71+
for (const platform of readdirSync(npmDir)) {
72+
const platformDir = join(npmDir, platform)
73+
if (!statSync(platformDir).isDirectory()) continue
74+
const platformPkg = join(platformDir, 'package.json')
75+
if (existsSync(platformPkg)) {
76+
entries.push({ path: `${baseDir}/npm/${platform}/package.json`, name: `${prefix}/${platform}` })
77+
}
78+
}
79+
return entries
80+
}
5681

57-
if (pkgJson.version !== rootVersion) {
58-
console.log(` ✓ ${pkg.name}: version ${pkgJson.version}${rootVersion}`)
59-
pkgJson.version = rootVersion
60-
changed = true
82+
// Discover all packages under packages/
83+
function discoverPackagesDir(): PackageEntry[] {
84+
const entries: PackageEntry[] = []
85+
const packagesDir = resolve('packages')
86+
if (!existsSync(packagesDir)) return entries
87+
for (const pkg of readdirSync(packagesDir)) {
88+
const pkgDir = join(packagesDir, pkg)
89+
if (!statSync(pkgDir).isDirectory()) continue
90+
const pkgFile = join(pkgDir, 'package.json')
91+
if (existsSync(pkgFile)) {
92+
entries.push({ path: `packages/${pkg}/package.json`, name: `pkg:${pkg}` })
93+
}
6194
}
95+
return entries
96+
}
97+
98+
const libraryPackages = discoverLibraryPackages()
99+
const packagesPackages = discoverPackagesDir()
100+
const cliNpmPackages = discoverNpmSubPackages('cli', 'cli-napi')
101+
102+
let changed = false
103+
104+
for (const pkg of [...packages, ...libraryPackages, ...packagesPackages, ...cliNpmPackages]) {
105+
const fullPath = resolve(pkg.path)
106+
try {
107+
const content = readFileSync(fullPath, 'utf-8').replace(/^\uFEFF/, '')
108+
const pkgJson: PackageJson = JSON.parse(content)
62109

63-
if (changed) {
64-
writeFileSync(fullPath, JSON.stringify(pkgJson, null, 2) + '\n', 'utf-8')
110+
if (pkgJson.version !== rootVersion) {
111+
console.log(` ✓ ${pkg.name}: version ${pkgJson.version}${rootVersion}`)
112+
pkgJson.version = rootVersion
113+
writeFileSync(fullPath, JSON.stringify(pkgJson, null, 2) + '\n', 'utf-8')
114+
changed = true
115+
}
116+
} catch {
117+
console.log(`⚠️ ${pkg.path} not found or invalid, skipping`)
65118
}
66119
}
67120

@@ -96,8 +149,7 @@ try {
96149

97150
// Sync version field in tnmsc.example.json files
98151
const exampleConfigPaths = [
99-
'cli/public/tnmsc.example.json',
100-
'packages/init-bundle/public/public/tnmsc.example.json',
152+
'libraries/init-bundle/public/public/tnmsc.example.json',
101153
]
102154

103155
for (const examplePath of exampleConfigPaths) {
@@ -119,8 +171,19 @@ for (const examplePath of exampleConfigPaths) {
119171
if (changed) {
120172
console.log('\n📦 Versions synced, auto-staging changes...')
121173
try {
174+
const filesToStage = [
175+
'cli/package.json',
176+
'gui/package.json',
177+
'doc/package.json',
178+
'gui/src-tauri/Cargo.toml',
179+
'gui/src-tauri/tauri.conf.json',
180+
'libraries/init-bundle/public/public/tnmsc.example.json',
181+
...libraryPackages.map(p => p.path),
182+
...packagesPackages.map(p => p.path),
183+
...cliNpmPackages.map(p => p.path),
184+
]
122185
execSync(
123-
'git add cli/package.json gui/package.json doc/package.json gui/src-tauri/Cargo.toml gui/src-tauri/tauri.conf.json cli/public/tnmsc.example.json packages/init-bundle/public/public/tnmsc.example.json',
186+
`git add ${filesToStage.join(' ')}`,
124187
{ stdio: 'inherit' }
125188
)
126189
console.log('✅ Staged modified files')

.github/workflows/ci.yml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
- uses: actions/checkout@v4
1313

1414
- name: Install GTK development dependencies
15-
run: sudo apt-get update && sudo apt-get install -y libgtk-3-dev libglib2.0-dev pkg-config
15+
run: sudo apt-get update && sudo apt-get install -y libgtk-3-dev libglib2.0-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf pkg-config
1616

1717
- name: Setup pnpm
1818
uses: pnpm/action-setup@v4
@@ -46,3 +46,20 @@ jobs:
4646

4747
- name: Typecheck
4848
run: pnpm exec turbo run typecheck
49+
50+
- name: Install Rust stable
51+
uses: dtolnay/rust-toolchain@stable
52+
53+
- name: Cache cargo
54+
uses: actions/cache@v4
55+
with:
56+
path: |
57+
~/.cargo/registry
58+
~/.cargo/git
59+
target
60+
key: ${{ runner.os }}-cargo-ci-${{ hashFiles('Cargo.lock') }}
61+
restore-keys: |
62+
${{ runner.os }}-cargo-ci-
63+
64+
- name: Rust tests (excluding GUI)
65+
run: cargo test --workspace --exclude memory-sync-gui
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
name: Release CLI Binary
2+
3+
concurrency:
4+
group: ${{ github.workflow }}-${{ inputs.version || github.run_id }}
5+
cancel-in-progress: true
6+
7+
on:
8+
workflow_call:
9+
inputs:
10+
version:
11+
required: true
12+
type: string
13+
workflow_dispatch:
14+
inputs:
15+
version:
16+
description: 'Version to release (without v prefix, e.g. 2026.10222.0)'
17+
required: true
18+
type: string
19+
20+
permissions:
21+
contents: read
22+
23+
jobs:
24+
build-cli-binary:
25+
strategy:
26+
fail-fast: false
27+
matrix:
28+
include:
29+
- platform: ubuntu-24.04
30+
target: x86_64-unknown-linux-gnu
31+
binary: tnmsc
32+
archive: tnmsc-linux-x86_64.tar.gz
33+
- platform: ubuntu-24.04
34+
target: aarch64-unknown-linux-gnu
35+
binary: tnmsc
36+
archive: tnmsc-linux-aarch64.tar.gz
37+
cross: true
38+
- platform: macos-14
39+
target: aarch64-apple-darwin
40+
binary: tnmsc
41+
archive: tnmsc-darwin-aarch64.tar.gz
42+
- platform: macos-14
43+
target: x86_64-apple-darwin
44+
binary: tnmsc
45+
archive: tnmsc-darwin-x86_64.tar.gz
46+
- platform: windows-latest
47+
target: x86_64-pc-windows-msvc
48+
binary: tnmsc.exe
49+
archive: tnmsc-windows-x86_64.zip
50+
51+
runs-on: ${{ matrix.platform }}
52+
steps:
53+
- uses: actions/checkout@v4
54+
55+
# 1. Build plugin-runtime.mjs first (needed for embedded-runtime feature)
56+
- name: Setup pnpm
57+
uses: pnpm/action-setup@v4
58+
59+
- name: Setup Node
60+
uses: actions/setup-node@v4
61+
with:
62+
node-version: 25
63+
64+
- name: Get pnpm store directory
65+
id: pnpm-cache
66+
shell: bash
67+
run: echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
68+
69+
- uses: actions/cache@v4
70+
name: Setup pnpm cache
71+
with:
72+
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
73+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
74+
restore-keys: |
75+
${{ runner.os }}-pnpm-store-
76+
77+
- name: Install & bundle plugin-runtime
78+
shell: bash
79+
run: |
80+
pnpm install --frozen-lockfile
81+
pnpm exec turbo run build --filter=@truenine/memory-sync-cli...
82+
ls -la cli/dist/plugin-runtime.mjs
83+
84+
# 2. Build Rust binary with embedded plugin-runtime.mjs
85+
- name: Install Rust stable
86+
uses: dtolnay/rust-toolchain@stable
87+
with:
88+
targets: ${{ matrix.target }}
89+
90+
- name: Install cross-compilation tools (aarch64-linux)
91+
if: matrix.cross
92+
run: |
93+
sudo apt-get update
94+
sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
95+
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
96+
97+
- name: Cache cargo registry & target
98+
uses: actions/cache@v4
99+
with:
100+
path: |
101+
~/.cargo/registry
102+
~/.cargo/git
103+
target
104+
key: ${{ runner.os }}-${{ matrix.target }}-cargo-cli-${{ hashFiles('Cargo.lock') }}
105+
restore-keys: |
106+
${{ runner.os }}-${{ matrix.target }}-cargo-cli-
107+
108+
- name: Build tnmsc binary (release, with embedded runtime)
109+
run: cargo build --release --target ${{ matrix.target }} -p tnmsc --features embedded-runtime
110+
111+
- name: Run tests (native only)
112+
if: ${{ !matrix.cross }}
113+
run: cargo test --release --target ${{ matrix.target }} -p tnmsc --features embedded-runtime
114+
115+
# 3. Package binary + plugin-runtime.mjs
116+
- name: Package (unix)
117+
if: runner.os != 'Windows'
118+
shell: bash
119+
run: |
120+
mkdir -p staging
121+
cp target/${{ matrix.target }}/release/${{ matrix.binary }} staging/
122+
cp cli/dist/plugin-runtime.mjs staging/
123+
cd staging
124+
tar czf ../${{ matrix.archive }} *
125+
126+
- name: Package (windows)
127+
if: runner.os == 'Windows'
128+
shell: pwsh
129+
run: |
130+
New-Item -ItemType Directory -Force -Path staging
131+
Copy-Item "target/${{ matrix.target }}/release/${{ matrix.binary }}" staging/
132+
Copy-Item "cli/dist/plugin-runtime.mjs" staging/
133+
Compress-Archive -Path staging/* -DestinationPath ${{ matrix.archive }}
134+
135+
- name: Upload artifact
136+
uses: actions/upload-artifact@v4
137+
with:
138+
name: cli-${{ matrix.target }}
139+
path: ${{ matrix.archive }}
140+
if-no-files-found: error

0 commit comments

Comments
 (0)