Skip to content

Commit

Permalink
feat: split binaries into multiple packages
Browse files Browse the repository at this point in the history
  • Loading branch information
azat-io committed Nov 3, 2024
1 parent 8969970 commit 7317ae9
Show file tree
Hide file tree
Showing 14 changed files with 249 additions and 98 deletions.
6 changes: 5 additions & 1 deletion .github/actions/install-dependencies/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ name: Dependencies
runs:
using: composite
steps:
- name: Build Package Structure
shell: bash
run: node ./scripts/create-packages.js

- name: Get pnpm store directory
shell: bash
run: |
Expand All @@ -17,5 +21,5 @@ runs:
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install --frozen-lockfile --ignore-scripts
shell: bash
run: pnpm install --frozen-lockfile --ignore-scripts
63 changes: 40 additions & 23 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,32 +88,32 @@ jobs:
run: |
if [[ "${{ matrix.platform }}" == "ubuntu-latest" ]]; then
if [[ "${{ matrix.arch }}" == "x64" ]]; then
mkdir -p ./bin/linux/x64
cp target/x86_64-unknown-linux-gnu/release/todoctor ./bin/linux/x64/todoctor
chmod +x ./bin/linux/x64/todoctor
mkdir -p ./packages/linux-x64
cp target/x86_64-unknown-linux-gnu/release/todoctor ./packages/linux-x64/todoctor
chmod +x ./packages/linux-x64/todoctor
elif [[ "${{ matrix.arch }}" == "arm64" ]]; then
mkdir -p ./bin/linux/arm64
cp target/aarch64-unknown-linux-gnu/release/todoctor ./bin/linux/arm64/todoctor
chmod +x ./bin/linux/arm64/todoctor
mkdir -p ./packages/linux-arm64
cp target/aarch64-unknown-linux-gnu/release/todoctor ./packages/linux-arm64/todoctor
chmod +x ./packages/linux-arm64/todoctor
fi
elif [[ "${{ matrix.platform }}" == "macos-latest" ]]; then
if [[ "${{ matrix.arch }}" == "x64" ]]; then
mkdir -p ./bin/macos/x64
cp target/x86_64-apple-darwin/release/todoctor ./bin/macos/x64/todoctor
chmod +x ./bin/macos/x64/todoctor
mkdir -p ./packages/darwin-x64
cp target/x86_64-apple-darwin/release/todoctor ./packages/darwin-x64/todoctor
chmod +x ./packages/darwin-x64/todoctor
elif [[ "${{ matrix.arch }}" == "arm64" ]]; then
mkdir -p ./bin/macos/arm64
cp target/aarch64-apple-darwin/release/todoctor ./bin/macos/arm64/todoctor
chmod +x ./bin/macos/arm64/todoctor
mkdir -p ./packages/darwin-arm64
cp target/aarch64-apple-darwin/release/todoctor ./packages/darwin-arm64/todoctor
chmod +x ./packages/darwin-arm64/todoctor
fi
fi
shell: bash

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

- name: Upload Binaries
Expand Down Expand Up @@ -174,17 +174,17 @@ jobs:

- name: Set Execute Permissions on Binaries
run: |
chmod +x ./bin/linux/x64/todoctor
chmod +x ./bin/linux/arm64/todoctor
chmod +x ./bin/macos/x64/todoctor
chmod +x ./bin/macos/arm64/todoctor
chmod +x ./packages/linux-x64/todoctor
chmod +x ./packages/linux-arm64/todoctor
chmod +x ./packages/darwin-x64/todoctor
chmod +x ./packages/darwin-arm64/todoctor
- name: Verify Binary Permissions
run: |
ls -l ./bin/linux/x64/todoctor
ls -l ./bin/linux/arm64/todoctor
ls -l ./bin/macos/x64/todoctor
ls -l ./bin/macos/arm64/todoctor
ls -l ./packages/linux-x64/todoctor
ls -l ./packages/linux-arm64/todoctor
ls -l ./packages/darwin-x64/todoctor
ls -l ./packages/darwin-arm64/todoctor
- name: Create GitHub Release
run: pnpm run ci:changelog
Expand All @@ -194,8 +194,25 @@ jobs:
- name: Configure NPM Auth
run: echo "//registry.npmjs.org/:_authToken=${{ secrets.NODE_AUTH_TOKEN }}" > ~/.npmrc

- name: Update Package Versions
shell: bash
run: node ./scripts/version.js

- name: Clear Package JSON
run: pnpm run ci:clear

- name: Publish to NPM
- name: Publish Root Package to NPM
run: npm publish --access public --no-git-checks --provenance

- name: Publish Packages to NPM
run: |
for pkg in packages/*; do
if [ -d "$pkg" ]; then
echo "Publishing package $pkg"
cd "$pkg"
npm publish --access public --no-git-checks --provenance
cd -
fi
done
env:
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ node_modules/
target/

# Build
!bin/todoctor.js
packages/
dist/
bin/

Expand Down
3 changes: 3 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
link-workspace-packages = true
prefer-workspace-packages = true
recursive-install = true
39 changes: 17 additions & 22 deletions bin/todoctor.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,37 @@
#!/usr/bin/env node

import { createRequire } from 'node:module'
import { spawn } from 'node:child_process'
import { fileURLToPath } from 'node:url'
import path from 'node:path'
import os from 'node:os'
import fs from 'node:fs'

let require = createRequire(import.meta.url)
let filename = fileURLToPath(import.meta.url)
let dirname = path.dirname(filename)

let platform = os.platform()
let arch = os.arch()

export let binaries = {
'win32:x64': 'windows/x64/todoctor.exe',
'darwin:arm64': 'macos/arm64/todoctor',
'linux:arm64': 'linux/arm64/todoctor',
'darwin:x64': 'macos/x64/todoctor',
'linux:x64': 'linux/x64/todoctor',
}

let key = `${platform}:${arch}`
let relativePath = binaries[key]

if (!relativePath) {
console.error(`Unsupported platform or architecture: ${platform}, ${arch}`)
process.exit(1)
}

let binaryPath = path.join(dirname, relativePath)

if (!fs.existsSync(binaryPath)) {
console.error(`Binary not found: ${binaryPath}`)
let packageName = `@todoctor/${platform}-${arch}`
let binaryPath

try {
let packageBinaryFile = 'todoctor'
if (platform === 'win32') {
packageBinaryFile += '.exe'
}
binaryPath = require.resolve(`${packageName}/${packageBinaryFile}`)
} catch (error) {
console.error(`Failed to find binary for ${packageName}`)
console.error(error)
process.exit(1)
}

let distPath = path.join(dirname, '../dist')
let args = process.argv.slice(2)
let child = spawn(binaryPath, args, { stdio: 'inherit' })
let env = { ...process.env, DIST_PATH: distPath }
let child = spawn(binaryPath, args, { stdio: 'inherit', env })

child.on('exit', code => {
process.exit(code)
Expand Down
18 changes: 15 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,17 @@
"start": "pnpm run /^start:/",
"start:preview": "vite",
"build": "pnpm run /^build:/",
"build:lib": "cargo build --release && node ./scripts/build.js",
"build:lib": "cargo build --release && node \"./scripts/create-packages.js\" && node \"./scripts/build.js\"",
"build:preview": "vite build",
"docs:build": "DOCS=true vite build",
"release": "pnpm release:check && pnpm release:version",
"release": "pnpm release:check && pnpm release:version && pnpm release:git",
"release:check": "pnpm test && pnpm run build",
"release:version": "changelogen --output changelog.md --release --push",
"release:git": "pnpm release:git:add && pnpm release:git:commit && pnpm release:git:tag && pnpm release:git:push",
"release:git:add": "git add .",
"release:git:commit": "git commit -m \"build: publish v$(node -p \"require('./package.json').version\")\"",
"release:git:tag": "git tag v$(node -p \"require('./package.json').version\")",
"release:git:push": "git push --follow-tags && push origin v$(node -p \"require('./package.json').version\")",
"release:version": "changelogen --output changelog.md --release --no-commit --no-tag",
"ci:changelog": "changelogithub",
"ci:clear": "clear-package-json package.json --output package.json",
"test": "pnpm run /^test:/",
Expand Down Expand Up @@ -59,6 +64,13 @@
"./build",
"./dist"
],
"optionalDependencies": {
"@todoctor/darwin-arm64": "workspace:^",
"@todoctor/darwin-x64": "workspace:^",
"@todoctor/linux-arm64": "workspace:^",
"@todoctor/linux-x64": "workspace:^",
"@todoctor/win32-x64": "workspace:^"
},
"devDependencies": {
"@azat-io/eslint-config-typescript": "^1.10.0",
"@azat-io/stylelint-config": "^0.1.1",
Expand Down
26 changes: 26 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
packages:
- packages/**
40 changes: 18 additions & 22 deletions scripts/build.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,33 @@
import { fileURLToPath } from 'node:url'
import path from 'node:path'
import fs from 'node:fs'
import os from 'node:os'

import { platforms } from './platforms.js'

let platform = os.platform()
let arch = os.arch()

let platformMap = {
win32: 'windows',
darwin: 'macos',
linux: 'linux',
}

let archMap = {
arm64: 'arm64',
x64: 'x64',
}
let userPlatform = platforms.find(p => p.name === platform)

let filename = fileURLToPath(import.meta.url)
let dirname = path.dirname(filename)

let platformName = platformMap[platform]
let archName = archMap[arch]

if (!platformName || !archName) {
if (!userPlatform?.arch.includes(arch)) {
console.error(`Unsupported platform or architecture: ${platform}, ${arch}`)
process.exit(1)
}

let binaryName = platform === 'win32' ? 'todoctor.exe' : 'todoctor'

let sourcePath = path.join(dirname, '..', 'target', 'release', binaryName)
let destDir = path.join(dirname, '../bin/', platformName, archName)
let binaryName = ['todoctor', userPlatform.extension].filter(Boolean).join('.')

let sourcePath = path.join(
import.meta.dirname,
'..',
'target',
'release',
binaryName,
)
let destDir = path.join(
import.meta.dirname,
'../packages/',
`${platform}-${arch}`,
)
let destPath = path.join(destDir, binaryName)

if (!fs.existsSync(destDir)) {
Expand Down
73 changes: 73 additions & 0 deletions scripts/create-packages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/* eslint-disable perfectionist/sort-objects */

import fs from 'node:fs/promises'
import path from 'node:path'

import { getPackageJson } from './get-package-json.js'
import { platforms } from './platforms.js'

let packagesDir = path.join(import.meta.dirname, '../packages')
let rootPackageJson = await getPackageJson()

for (let platform of platforms) {
for (let arch of platform.arch) {
let packageDir = path.join(packagesDir, `${platform.name}-${arch}`)

await fs.mkdir(packageDir, {
recursive: true,
})

let name = `@todoctor/${platform.name}-${arch}`

fs.writeFile(
path.join(packageDir, 'package.json'),
JSON.stringify(
{
name,
description: `Platform-specific binary for Todoctor (${platform.name}, ${arch})`,
version: rootPackageJson.version,
repository: rootPackageJson.repository,
author: rootPackageJson.author,
license: rootPackageJson.license,
keywords: rootPackageJson.keywords,
os: [platform.name],
cpu: [arch],
},
null,
2,
),
)

fs.writeFile(
path.join(packageDir, 'readme.md'),
[
`# Todoctor (${platform.name[0].toUpperCase() + platform.name.slice(1)}, ${arch.toUpperCase()})`,
'',
'<img',
' src="https://raw.githubusercontent.com/azat-io/todoctor/main/assets/logo-light.webp"',
' alt="Todoctor Logo"',
' align="right"',
' height="160"',
' width="160"',
'/>',
'',
`[![Version](https://img.shields.io/npm/v/${name}.svg?color=2c7f50&labelColor=353c3c)](https://npmjs.com/package/${name})`,
'[![GitHub License](https://img.shields.io/badge/license-MIT-232428.svg?color=2c7f50&labelColor=353c3c)](https://github.com/azat-io/todoctor/blob/main/license)',
'',
'This is a platform-specific binary package for Todoctor. It contains the pre-compiled binary executable for your operating system and architecture.',
'',
'**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.',
'',
'## Usage',
'',
'```sh',
'npx todoctor',
'```',
'',
'## License',
'',
'MIT &copy; [Azat S.](https://azat.io)',
].join('\n'),
)
}
}
Loading

0 comments on commit 7317ae9

Please sign in to comment.