Skip to content

Commit 706c3c8

Browse files
committed
feat: split binaries into multiple packages
1 parent 8969970 commit 706c3c8

File tree

13 files changed

+244
-96
lines changed

13 files changed

+244
-96
lines changed

.github/workflows/release.yml

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -88,32 +88,32 @@ jobs:
8888
run: |
8989
if [[ "${{ matrix.platform }}" == "ubuntu-latest" ]]; then
9090
if [[ "${{ matrix.arch }}" == "x64" ]]; then
91-
mkdir -p ./bin/linux/x64
92-
cp target/x86_64-unknown-linux-gnu/release/todoctor ./bin/linux/x64/todoctor
93-
chmod +x ./bin/linux/x64/todoctor
91+
mkdir -p ./packages/linux-x64
92+
cp target/x86_64-unknown-linux-gnu/release/todoctor ./packages/linux-x64/todoctor
93+
chmod +x ./packages/linux-x64/todoctor
9494
elif [[ "${{ matrix.arch }}" == "arm64" ]]; then
95-
mkdir -p ./bin/linux/arm64
96-
cp target/aarch64-unknown-linux-gnu/release/todoctor ./bin/linux/arm64/todoctor
97-
chmod +x ./bin/linux/arm64/todoctor
95+
mkdir -p ./packages/linux-arm64
96+
cp target/aarch64-unknown-linux-gnu/release/todoctor ./packages/linux-arm64/todoctor
97+
chmod +x ./packages/linux-arm64/todoctor
9898
fi
9999
elif [[ "${{ matrix.platform }}" == "macos-latest" ]]; then
100100
if [[ "${{ matrix.arch }}" == "x64" ]]; then
101-
mkdir -p ./bin/macos/x64
102-
cp target/x86_64-apple-darwin/release/todoctor ./bin/macos/x64/todoctor
103-
chmod +x ./bin/macos/x64/todoctor
101+
mkdir -p ./packages/darwin-x64
102+
cp target/x86_64-apple-darwin/release/todoctor ./packages/darwin-x64/todoctor
103+
chmod +x ./packages/darwin-x64/todoctor
104104
elif [[ "${{ matrix.arch }}" == "arm64" ]]; then
105-
mkdir -p ./bin/macos/arm64
106-
cp target/aarch64-apple-darwin/release/todoctor ./bin/macos/arm64/todoctor
107-
chmod +x ./bin/macos/arm64/todoctor
105+
mkdir -p ./packages/darwin-arm64
106+
cp target/aarch64-apple-darwin/release/todoctor ./packages/darwin-arm64/todoctor
107+
chmod +x ./packages/darwin-arm64/todoctor
108108
fi
109109
fi
110110
shell: bash
111111

112112
- name: Move Binaries to Bin Folder (Windows)
113113
if: runner.os == 'Windows'
114114
run: |
115-
mkdir bin\windows\x64
116-
copy target\x86_64-pc-windows-msvc\release\todoctor.exe bin\windows\x64\todoctor.exe
115+
mkdir packages\win32-x64
116+
copy target\x86_64-pc-windows-msvc\release\todoctor.exe packages\win32-x64\todoctor.exe
117117
shell: cmd
118118

119119
- name: Upload Binaries
@@ -142,6 +142,9 @@ jobs:
142142
- name: Build Static Assets
143143
run: pnpm run build:preview
144144

145+
- name: Build Package Structure
146+
run: node ./scripts/create-packages.js
147+
145148
- name: Download Binaries for Linux x64
146149
uses: actions/download-artifact@v4
147150
with:
@@ -174,17 +177,17 @@ jobs:
174177

175178
- name: Set Execute Permissions on Binaries
176179
run: |
177-
chmod +x ./bin/linux/x64/todoctor
178-
chmod +x ./bin/linux/arm64/todoctor
179-
chmod +x ./bin/macos/x64/todoctor
180-
chmod +x ./bin/macos/arm64/todoctor
180+
chmod +x ./packages/linux-x64/todoctor
181+
chmod +x ./packages/linux-arm64/todoctor
182+
chmod +x ./packages/darwin-x64/todoctor
183+
chmod +x ./packages/darwin-arm64/todoctor
181184
182185
- name: Verify Binary Permissions
183186
run: |
184-
ls -l ./bin/linux/x64/todoctor
185-
ls -l ./bin/linux/arm64/todoctor
186-
ls -l ./bin/macos/x64/todoctor
187-
ls -l ./bin/macos/arm64/todoctor
187+
ls -l ./packages/linux-x64/todoctor
188+
ls -l ./packages/linux-arm64/todoctor
189+
ls -l ./packages/darwin-x64/todoctor
190+
ls -l ./packages/darwin-arm64/todoctor
188191
189192
- name: Create GitHub Release
190193
run: pnpm run ci:changelog
@@ -199,3 +202,16 @@ jobs:
199202

200203
- name: Publish to NPM
201204
run: npm publish --access public --no-git-checks --provenance
205+
206+
- name: Publish Packages to NPM
207+
run: |
208+
for pkg in packages/*; do
209+
if [ -d "$pkg" ]; then
210+
echo "Publishing package $pkg"
211+
cd "$pkg"
212+
npm publish --access public --no-git-checks --provenance
213+
cd -
214+
fi
215+
done
216+
env:
217+
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ node_modules/
66
target/
77

88
# Build
9-
!bin/todoctor.js
9+
packages/
1010
dist/
1111
bin/
1212

.npmrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
link-workspace-packages = true
2+
prefer-workspace-packages = true
3+
recursive-install = true

bin/todoctor.js

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,37 @@
11
#!/usr/bin/env node
22

3+
import { createRequire } from 'node:module'
34
import { spawn } from 'node:child_process'
45
import { fileURLToPath } from 'node:url'
56
import path from 'node:path'
67
import os from 'node:os'
7-
import fs from 'node:fs'
88

9+
let require = createRequire(import.meta.url)
910
let filename = fileURLToPath(import.meta.url)
1011
let dirname = path.dirname(filename)
1112

1213
let platform = os.platform()
1314
let arch = os.arch()
1415

15-
export let binaries = {
16-
'win32:x64': 'windows/x64/todoctor.exe',
17-
'darwin:arm64': 'macos/arm64/todoctor',
18-
'linux:arm64': 'linux/arm64/todoctor',
19-
'darwin:x64': 'macos/x64/todoctor',
20-
'linux:x64': 'linux/x64/todoctor',
21-
}
22-
23-
let key = `${platform}:${arch}`
24-
let relativePath = binaries[key]
25-
26-
if (!relativePath) {
27-
console.error(`Unsupported platform or architecture: ${platform}, ${arch}`)
28-
process.exit(1)
29-
}
30-
31-
let binaryPath = path.join(dirname, relativePath)
32-
33-
if (!fs.existsSync(binaryPath)) {
34-
console.error(`Binary not found: ${binaryPath}`)
16+
let packageName = `@todoctor/${platform}-${arch}`
17+
let binaryPath
18+
19+
try {
20+
let packageBinaryFile = 'todoctor'
21+
if (platform === 'win32') {
22+
packageBinaryFile += '.exe'
23+
}
24+
binaryPath = require.resolve(`${packageName}/${packageBinaryFile}`)
25+
} catch (error) {
26+
console.error(`Failed to find binary for ${packageName}`)
27+
console.error(error)
3528
process.exit(1)
3629
}
3730

31+
let distPath = path.join(dirname, '../dist')
3832
let args = process.argv.slice(2)
39-
let child = spawn(binaryPath, args, { stdio: 'inherit' })
33+
let env = { ...process.env, DIST_PATH: distPath }
34+
let child = spawn(binaryPath, args, { stdio: 'inherit', env })
4035

4136
child.on('exit', code => {
4237
process.exit(code)

package.json

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,19 @@
2323
"start": "pnpm run /^start:/",
2424
"start:preview": "vite",
2525
"build": "pnpm run /^build:/",
26-
"build:lib": "cargo build --release && node ./scripts/build.js",
26+
"build:lib": "cargo build --release && node \"./scripts/create-packages.js\" && node \"./scripts/build.js\"",
2727
"build:preview": "vite build",
2828
"docs:build": "DOCS=true vite build",
29-
"release": "pnpm release:check && pnpm release:version",
29+
"release": "pnpm release:check && pnpm release:version && pnpm release:git",
3030
"release:check": "pnpm test && pnpm run build",
31-
"release:version": "changelogen --output changelog.md --release --push",
31+
"release:git": "pnpm release:git:add && pnpm release:git:commit && pnpm release:git:tag && pnpm release:git:push",
32+
"release:git:add": "git add .",
33+
"release:git:commit": "git commit -m \"build: publish v$(node -p \"require('./package.json').version\")\"",
34+
"release:git:tag": "git tag v$(node -p \"require('./package.json').version\")",
35+
"release:git:push": "git push --follow-tags",
36+
"release:version": "pnpm release:version:root && pnpm release:version:packages",
37+
"release:version:root": "changelogen --output changelog.md --release --no-commit --no-tag",
38+
"release:version:packages": "node ./scripts/version.js",
3239
"ci:changelog": "changelogithub",
3340
"ci:clear": "clear-package-json package.json --output package.json",
3441
"test": "pnpm run /^test:/",
@@ -59,6 +66,13 @@
5966
"./build",
6067
"./dist"
6168
],
69+
"optionalDependencies": {
70+
"@todoctor/darwin-arm64": "^1.2.0",
71+
"@todoctor/darwin-x64": "^1.2.0",
72+
"@todoctor/linux-arm64": "^1.2.0",
73+
"@todoctor/linux-x64": "^1.2.0",
74+
"@todoctor/win32-x64": "^1.2.0"
75+
},
6276
"devDependencies": {
6377
"@azat-io/eslint-config-typescript": "^1.10.0",
6478
"@azat-io/stylelint-config": "^0.1.1",

pnpm-lock.yaml

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pnpm-workspace.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
packages:
2+
- packages/**

scripts/build.js

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,33 @@
1-
import { fileURLToPath } from 'node:url'
21
import path from 'node:path'
32
import fs from 'node:fs'
43
import os from 'node:os'
54

5+
import { platforms } from './platforms.js'
6+
67
let platform = os.platform()
78
let arch = os.arch()
89

9-
let platformMap = {
10-
win32: 'windows',
11-
darwin: 'macos',
12-
linux: 'linux',
13-
}
14-
15-
let archMap = {
16-
arm64: 'arm64',
17-
x64: 'x64',
18-
}
10+
let userPlatform = platforms.find(p => p.name === platform)
1911

20-
let filename = fileURLToPath(import.meta.url)
21-
let dirname = path.dirname(filename)
22-
23-
let platformName = platformMap[platform]
24-
let archName = archMap[arch]
25-
26-
if (!platformName || !archName) {
12+
if (!userPlatform?.arch.includes(arch)) {
2713
console.error(`Unsupported platform or architecture: ${platform}, ${arch}`)
2814
process.exit(1)
2915
}
3016

31-
let binaryName = platform === 'win32' ? 'todoctor.exe' : 'todoctor'
32-
33-
let sourcePath = path.join(dirname, '..', 'target', 'release', binaryName)
34-
let destDir = path.join(dirname, '../bin/', platformName, archName)
17+
let binaryName = ['todoctor', userPlatform.extension].filter(Boolean).join('.')
18+
19+
let sourcePath = path.join(
20+
import.meta.dirname,
21+
'..',
22+
'target',
23+
'release',
24+
binaryName,
25+
)
26+
let destDir = path.join(
27+
import.meta.dirname,
28+
'../packages/',
29+
`${platform}-${arch}`,
30+
)
3531
let destPath = path.join(destDir, binaryName)
3632

3733
if (!fs.existsSync(destDir)) {

scripts/create-packages.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/* eslint-disable perfectionist/sort-objects */
2+
3+
import fs from 'node:fs/promises'
4+
import path from 'node:path'
5+
6+
import { getPackageJson } from './get-package-json.js'
7+
import { platforms } from './platforms.js'
8+
9+
let packagesDir = path.join(import.meta.dirname, '../packages')
10+
let rootPackageJson = await getPackageJson()
11+
12+
for (let platform of platforms) {
13+
for (let arch of platform.arch) {
14+
let packageDir = path.join(packagesDir, `${platform.name}-${arch}`)
15+
16+
await fs.mkdir(packageDir, {
17+
recursive: true,
18+
})
19+
20+
let name = `@todoctor/${platform.name}-${arch}`
21+
22+
fs.writeFile(
23+
path.join(packageDir, 'package.json'),
24+
JSON.stringify(
25+
{
26+
name,
27+
description: `Platform-specific binary for Todoctor (${platform.name}, ${arch})`,
28+
version: rootPackageJson.version,
29+
repository: rootPackageJson.repository,
30+
author: rootPackageJson.author,
31+
license: rootPackageJson.license,
32+
keywords: rootPackageJson.keywords,
33+
os: [platform.name],
34+
cpu: [arch],
35+
},
36+
null,
37+
2,
38+
),
39+
)
40+
41+
fs.writeFile(
42+
path.join(packageDir, 'readme.md'),
43+
[
44+
`# Todoctor (${platform.name[0].toUpperCase() + platform.name.slice(1)}, ${arch.toUpperCase()})`,
45+
'',
46+
'<img',
47+
' src="https://raw.githubusercontent.com/azat-io/todoctor/main/assets/logo-light.webp"',
48+
' alt="Todoctor Logo"',
49+
' align="right"',
50+
' height="160"',
51+
' width="160"',
52+
'/>',
53+
'',
54+
`[![Version](https://img.shields.io/npm/v/${name}.svg?color=2c7f50&labelColor=353c3c)](https://npmjs.com/package/${name})`,
55+
'[![GitHub License](https://img.shields.io/badge/license-MIT-232428.svg?color=2c7f50&labelColor=353c3c)](https://github.com/azat-io/todoctor/blob/main/license)',
56+
'',
57+
'This is a platform-specific binary package for Todoctor. It contains the pre-compiled binary executable for your operating system and architecture.',
58+
'',
59+
'**Note:** This package is not meant to be installed directly by users. Instead, please install the main Todoctor package, which will automatically download the correct binary for your platform.',
60+
'',
61+
'## Usage',
62+
'',
63+
'```sh',
64+
'npx todoctor',
65+
'```',
66+
'',
67+
'## License',
68+
'',
69+
'MIT &copy; [Azat S.](https://azat.io)',
70+
].join('\n'),
71+
)
72+
}
73+
}

scripts/get-package-json.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import fs from 'node:fs/promises'
2+
import path from 'node:path'
3+
4+
export let getPackageJson = async () => {
5+
let rootPackageJsonPath = path.join(import.meta.dirname, '../package.json')
6+
return JSON.parse(await fs.readFile(rootPackageJsonPath, 'utf-8'))
7+
}

0 commit comments

Comments
 (0)