From 382a187175b593fea7953c06c00bd9c7c66c6586 Mon Sep 17 00:00:00 2001 From: Boshen Date: Tue, 23 Jan 2024 18:44:24 +0800 Subject: [PATCH] fix(npm): fix bin script for musl / gnu --- .github/workflows/release_oxlint.yml | 33 ++++-- npm/oxlint/bin/oxlint | 127 +++++++++++++++++++---- npm/oxlint/scripts/generate-packages.mjs | 1 + 3 files changed, 136 insertions(+), 25 deletions(-) diff --git a/.github/workflows/release_oxlint.yml b/.github/workflows/release_oxlint.yml index ea1d93ee2..847a653c3 100644 --- a/.github/workflows/release_oxlint.yml +++ b/.github/workflows/release_oxlint.yml @@ -121,21 +121,18 @@ jobs: publish: name: Publish + needs: build runs-on: ubuntu-latest permissions: contents: write # for softprops/action-gh-release@v1 id-token: write # for `npm publish --provenance` - needs: - - build - env: - version: ${{ needs.check.outputs.version }} steps: - uses: actions/checkout@v4 - name: Install Node.js uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 registry-url: 'https://registry.npmjs.org' - name: Download Artifacts @@ -176,8 +173,30 @@ jobs: - name: Create GitHub Release uses: softprops/action-gh-release@v1 with: - name: oxlint v${{ env.version }} - tag_name: oxlint_v${{ env.version }} + name: oxlint v${{ needs.check.outputs.version }} + tag_name: oxlint_v${{ needs.check.outputs.version }} draft: true files: oxlint-* fail_on_unmatched_files: true + + - name: wait 3 minutes for smoke test + shell: bash + run: sleep 180s + + smoke: + needs: publish + strategy: + matrix: + include: + - os: windows-latest + - os: ubuntu-latest + - os: macos-latest + name: Smoke Test ${{ matrix.os }} + runs-on: ${{ matrix.os }} + steps: + - name: Test + shell: bash + run: | + touch test.js + npx oxlint@${{ needs.check.outputs.version }} ./test.js + exit 0 diff --git a/npm/oxlint/bin/oxlint b/npm/oxlint/bin/oxlint index 30c9698e4..2ecae44ee 100755 --- a/npm/oxlint/bin/oxlint +++ b/npm/oxlint/bin/oxlint @@ -1,22 +1,114 @@ #!/usr/bin/env node -const { platform, arch, env, version, release } = process; -const PLATFORMS = { - win32: { - x64: "@oxlint/win32-x64/oxlint.exe", - arm64: "@oxlint/win32-arm64/oxlint.exe", - }, - darwin: { - x64: "@oxlint/darwin-x64/oxlint", - arm64: "@oxlint/darwin-arm64/oxlint", - }, - linux: { - x64: "@oxlint/linux-x64/oxlint", - arm64: "@oxlint/linux-arm64/oxlint", - }, +const isMusl = () => { + let musl = false; + if (process.platform === "linux") { + musl = isMuslFromFilesystem(); + if (musl === null) { + musl = isMuslFromReport(); + } + if (musl === null) { + musl = isMuslFromChildProcess(); + } + } + return musl; }; -const binPath = PLATFORMS?.[platform]?.[arch]; +const isFileMusl = (f) => f.includes("libc.musl-") || f.includes("ld-musl-"); + +const isMuslFromFilesystem = () => { + const { readFileSync } = require("fs"); + try { + return readFileSync("/usr/bin/ldd", "utf-8").includes("musl"); + } catch { + return null; + } +}; + +const isMuslFromReport = () => { + const report = + typeof process.report.getReport === "function" + ? process.report.getReport() + : null; + if (!report) { + return null; + } + if (report.header && report.header.glibcVersionRuntime) { + return false; + } + if (Array.isArray(report.sharedObjects)) { + if (report.sharedObjects.some(isFileMusl)) { + return true; + } + } + return false; +}; + +const isMuslFromChildProcess = () => { + try { + return require("child_process") + .execSync("ldd --version", { encoding: "utf8" }) + .includes("musl"); + } catch (e) { + // If we reach this case, we don't know if the system is musl or not, so is better to just fallback to false + return false; + } +}; + +const { platform, arch, env, version, release } = process; + +let binPath; + +switch (platform) { + case "win32": { + switch (arch) { + case "x64": { + binPath = "@oxlint/win32-x64/oxlint.exe"; + break; + } + case "arm64": { + binPath = "@oxlint/win32-arm64/oxlint.exe"; + break; + } + } + break; + } + case "darwin": { + switch (arch) { + case "x64": { + binPath = "@oxlint/darwin-x64/oxlint"; + break; + } + case "arm64": { + binPath = "@oxlint/darwin-arm64/oxlint"; + break; + } + } + break; + } + case "linux": { + switch (arch) { + case "x64": { + if (isMusl()) { + binPath = "@oxlint/linux-x64-musl/oxlint"; + } else { + binPath = "@oxlint/linux-x64-gnu/oxlint"; + } + break; + } + case "arm64": { + if (isMusl()) { + binPath = "@oxlint/linux-arm64-musl/oxlint"; + } else { + binPath = "@oxlint/linux-arm64-gnu/oxlint"; + } + break; + } + } + break; + } +} + if (binPath) { const result = require("child_process").spawnSync( require.resolve(binPath), @@ -30,7 +122,7 @@ if (binPath) { JS_RUNTIME_NAME: release.name, NODE_PACKAGE_MANAGER: detectPackageManager(), }, - } + }, ); if (result.error) { @@ -41,7 +133,7 @@ if (binPath) { } else { console.error( "The oxlint CLI package doesn't ship with prebuilt binaries for your platform yet. " + - "You can create an issue at https://github.com/oxc-project/oxc/issues for support." + "You can create an issue at https://github.com/oxc-project/oxc/issues for support.", ); process.exitCode = 1; } @@ -64,4 +156,3 @@ function detectPackageManager() { return userAgent.split(" ")[0]; } - diff --git a/npm/oxlint/scripts/generate-packages.mjs b/npm/oxlint/scripts/generate-packages.mjs index c038e4778..3852362fa 100644 --- a/npm/oxlint/scripts/generate-packages.mjs +++ b/npm/oxlint/scripts/generate-packages.mjs @@ -85,6 +85,7 @@ function writeManifest() { fs.writeFileSync(manifestPath, content); } +// NOTE: Must update npm/oxlint/bin/oxlint const TARGETS = [ "win32-x64", "win32-arm64",