feat(npm/oxc-transform): setup npm/oxc-transform and publish

This commit is contained in:
Boshen 2024-06-18 21:43:48 +08:00
parent 02cc14e90c
commit 527bfc82f5
No known key found for this signature in database
GPG key ID: 67715A371E534061
4 changed files with 374 additions and 0 deletions

View file

@ -0,0 +1,212 @@
name: Release NAPI transform
on:
push:
branches:
- main
paths:
- npm/oxc-transform/package.json # Please only commit this file, so we don't need to wait for test CI to pass.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
defaults:
run:
shell: bash
jobs:
check:
name: Check version
runs-on: ubuntu-latest
outputs:
version: ${{ env.version }}
version_changed: ${{ steps.version.outputs.changed }}
steps:
- uses: taiki-e/checkout-action@v1
- name: Check version changes
uses: EndBug/version-check@v2
id: version
with:
static-checking: localIsNew
file-url: https://unpkg.com/oxc-transform@latest/package.json
file-name: npm/oxc-transform/package.json
- name: Set version name
if: steps.version.outputs.changed == 'true'
run: |
echo "Version change found! New version: ${{ steps.version.outputs.version }} (${{ steps.version.outputs.version_type }})"
echo "version=${{ steps.version.outputs.version }}" >> $GITHUB_ENV
build:
needs: check
if: needs.check.outputs.version_changed == 'true'
env:
version: ${{ needs.check.outputs.version }}
outputs:
version: ${{ env.version }}
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
target: x86_64-pc-windows-msvc
code-target: win32-x64-msvc
- os: windows-latest
target: aarch64-pc-windows-msvc
code-target: win32-arm64-msvc
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
code-target: linux-x64-gnu
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
code-target: linux-arm64-gnu
- os: ubuntu-latest
target: x86_64-unknown-linux-musl
code-target: linux-x64-musl
- os: ubuntu-latest
target: aarch64-unknown-linux-musl
code-target: linux-arm64-musl
- os: macos-13
target: x86_64-apple-darwin
code-target: darwin-x64
- os: macos-14 # M1
target: aarch64-apple-darwin
code-target: darwin-arm64
name: Package ${{ matrix.target }}
runs-on: ${{ matrix.os }}
steps:
- uses: taiki-e/checkout-action@v1
### install musl dependencies ###
- uses: goto-bus-stop/setup-zig@v2
if: ${{ contains(matrix.target, 'musl') }}
with:
version: 0.11.0
- name: Install cargo-zigbuild
if: ${{ contains(matrix.target, 'musl') }}
uses: taiki-e/install-action@v2
with:
tool: cargo-zigbuild
### install non-musl dependencies ###
- name: Install cross
if: ${{ !contains(matrix.target, 'musl') }}
uses: taiki-e/install-action@cross
### Build
- name: Add Rust Target
run: rustup target add ${{ matrix.target }}
- name: Build with cross
if: ${{ !contains(matrix.target, 'musl') }}
run: cross build --release -p oxc_transform_napi --target=${{ matrix.target }}
- name: Build with zig
if: ${{ contains(matrix.target, 'musl') }}
env:
RUSTFLAGS: "-C target-feature=-crt-static"
run: cargo zigbuild --release -p oxc_transform_napi --target=${{ matrix.target }}
### Build Done
- name: Move file on ${{ matrix.os }}
run: |
shopt -s extglob
ls target/${{ matrix.target }}/release/*.@(so|dll|dylib)
mv target/${{ matrix.target }}/release/*.@(so|dll|dylib) napi/transform/transform.${{ matrix.code-target }}.node
ls napi/transform
- name: Test
working-directory: napi/transform
if: ${{ contains(matrix.target, 'x86') && !contains(matrix.target, 'musl') }} # Need docker for aarch64
run: |
ls
node test.mjs
# The binary is zipped to fix permission loss https://github.com/actions/upload-artifact#permission-loss
- name: Archive Binary
if: runner.os == 'Windows'
run: 7z a ${{ matrix.code-target }}.zip napi/transform/transform.${{ matrix.code-target }}.node
# The binary is zipped to fix permission loss https://github.com/actions/upload-artifact#permission-loss
- name: Archive Binary
if: runner.os != 'Windows'
run: tar czf ${{ matrix.code-target }}.tar.gz napi/transform/transform.${{ matrix.code-target }}.node
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
if-no-files-found: error
name: binaries-${{ matrix.code-target }}
path: |
*.zip
*.tar.gz
publish:
name: Publish NAPI
runs-on: ubuntu-latest
permissions:
id-token: write # for `npm publish --provenance`
needs:
- build
steps:
- uses: taiki-e/checkout-action@v1
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version-file: .node-version
registry-url: 'https://registry.npmjs.org'
- name: Download Artifacts
uses: actions/download-artifact@v4
with:
merge-multiple: true
- name: Unzip
uses: montudor/action-zip@v1
with:
args: unzip -qq *.zip -d .
- name: Untar
run: ls *.gz | xargs -i tar xvf {}
- name: Generate npm packages
run: |
ls
ls napi/transform
node npm/oxc-transform/scripts/generate-packages.mjs
cat npm/oxc-transform/package.json
for package in npm/oxc-transform*
do
ls $package
cat $package/package.json
echo '----'
done
- name: Publish npm packages as latest
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# NOTE: The trailing slash on $package/ changes it to publishing the directory
run: |
# publish subpackages first
for package in npm/oxc-transform-*
do
npm publish $package/ --tag latest --provenance --access public
done
# publish root package last
npm publish npm/oxc-transform/ --provenance --access public --tag latest

View file

@ -0,0 +1,17 @@
# The JavaScript Oxidation Compiler
See index.d.ts for `parseSync` and `parseAsync` API.
## ESM
```javascript
import oxc from './index.js';
import assert from 'assert';
test(oxc.isolatedDeclaration("test.ts", "class A {}"), "declare class A {}\n");
function test(ret, expected) {
assert.equal(ret.sourceText, expected);
assert(ret.errors.length == 0);
}
```

View file

@ -0,0 +1,25 @@
{
"name": "oxc-transform",
"version": "0.0.1",
"description": "Oxc transform Node API",
"keywords": [
"transform"
],
"author": "Boshen and oxc contributors",
"license": "MIT",
"homepage": "https://oxc.rs",
"bugs": "https://github.com/oxc-project/oxc/issues",
"repository": {
"type": "git",
"url": "https://github.com/oxc-project/oxc.git",
"directory": "npm/oxc-transform"
},
"funding": {
"url": "https://github.com/sponsors/Boshen"
},
"main": "index.js",
"files": [
"index.d.ts",
"index.js"
]
}

View file

@ -0,0 +1,120 @@
// Code copied from [Rome](https://github.com/rome/tools/blob/main/npm/rome/scripts/generate-packages.mjs)
import { resolve } from "node:path";
import { fileURLToPath } from "node:url";
import * as fs from "node:fs";
const OXC_ROOT = resolve(fileURLToPath(import.meta.url), "../..");
const PACKAGES_ROOT = resolve(OXC_ROOT, "..");
const BINARY_ROOT = resolve(OXC_ROOT, "../../napi/transform");
const MANIFEST_PATH = resolve(OXC_ROOT, "package.json");
console.log('OXC_ROOT', OXC_ROOT);
console.log('PACKAGES_ROOT', PACKAGES_ROOT);
console.log('BINARY_ROOT', BINARY_ROOT);
console.log('MANIFEST_PATH', MANIFEST_PATH);
const LIBC_MAPPING = {
"gnu": "glibc",
"musl": "musl",
}
const rootManifest = JSON.parse(
fs.readFileSync(MANIFEST_PATH).toString("utf-8")
);
function package_name(target) {
return `@oxc-transform/binding-${target}`
}
function generateNativePackage(target) {
const binaryName = `transform.${target}.node`;
const packageRoot = resolve(PACKAGES_ROOT, `oxc-transform-${target}`);
const binarySource = resolve(BINARY_ROOT, binaryName);
const binaryTarget = resolve(packageRoot, binaryName);
// Remove the directory just in case it already exists (it's autogenerated
// so there shouldn't be anything important there anyway)
fs.rmSync(packageRoot, { recursive: true, force: true });
// Create the package directory
console.log(`Create directory ${packageRoot}`);
fs.mkdirSync(packageRoot);
// Generate the package.json manifest
const { version, author, license, homepage, bugs, repository } = rootManifest;
const triple = target.split("-");
const platform = triple[0];
const arch = triple[1];
const libc = triple[2] && { libc: [LIBC_MAPPING[triple[2]]] }
const manifest = {
name: package_name(target),
version,
main: binaryName,
license,
author,
bugs,
homepage,
repository,
files: [binaryName],
cpu: [arch],
os: [platform],
...libc
};
const manifestPath = resolve(packageRoot, "package.json");
console.log(`Create manifest ${manifestPath}`);
fs.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
console.log(`Copy binary ${binaryTarget}`);
fs.copyFileSync(binarySource, binaryTarget);
}
function writeManifest() {
const packageRoot = resolve(PACKAGES_ROOT, 'oxc-transform');
const manifestPath = resolve(packageRoot, "package.json");
console.log('packageRoot', packageRoot);
const manifestData = JSON.parse(
fs.readFileSync(manifestPath).toString("utf-8")
);
const nativePackages = TARGETS.map((target) => [
package_name(target),
rootManifest.version,
]);
manifestData["version"] = rootManifest.version;
manifestData["optionalDependencies"] = Object.fromEntries(nativePackages);
console.log('manifestPath', manifestPath);
console.log('manifestData', manifestData);
const content = JSON.stringify(manifestData, null, 2);
fs.writeFileSync(manifestPath, content);
let files = ["index.js", "index.d.ts"];
for (const file of files) {
fs.copyFileSync(resolve(BINARY_ROOT, file), resolve(packageRoot, file));
}
}
// NOTE: Must update npm/oxc-transform/package.json
const TARGETS = [
"win32-x64-msvc",
"win32-arm64-msvc",
"linux-x64-gnu",
"linux-arm64-gnu",
"linux-x64-musl",
"linux-arm64-musl",
"darwin-x64",
"darwin-arm64",
];
for (const target of TARGETS) {
generateNativePackage(target);
}
writeManifest();