oxc-project/oxc

27 workflows · maturity 100% · 13 patterns · GitHub ↗

Security 33.06/100

Security dimensions

permissions
22.2
security scan
4.2
supply chain
6.7
secret handling
0
harden runner
0

Tools: github/codeql-action/upload-sarif

Workflows (27)

autofix perms .github/workflows/autofix.yml
Triggers
pull_request
Runs on
ubuntu-latest
Jobs
autofix
Actions
taiki-e/checkout-action, oxc-project/setup-node, oxc-project/setup-rust, autofix-ci/action
Commands
  • if ! cargo shear --fix; then echo "shear=true" >> $GITHUB_OUTPUT fi
  • cargo check --all-features --all-targets
  • just fmt
View raw YAML
name: autofix.ci # For security reasons, the workflow in which the autofix.ci action is used must be named "autofix.ci".

permissions: {}

on:
  pull_request:
    types: [opened, synchronize]
    branches-ignore:
      - "**/graphite-base/**"

concurrency:
  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
  cancel-in-progress: ${{ github.ref_name != 'main' }}

jobs:
  autofix:
    runs-on: ubuntu-latest
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0

      - uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
        with:
          restore-cache: true
          cache-key: warm
          tools: just,cargo-shear@1.11.2
          components: rustfmt

      - name: cargo-shear
        id: shear
        shell: bash
        run: |
          if ! cargo shear --fix; then
            echo "shear=true" >> $GITHUB_OUTPUT
          fi

      - name: Check and update lock file
        run: cargo check --all-features --all-targets
        if: ${{ steps.shear.outputs.shear == 'true' }}

      - run: just fmt

      - uses: autofix-ci/action@7a166d7532b277f34e16238930461bf77f9d7ed8 # v1.3.3
        with:
          fail-fast: false
benchmark matrix perms .github/workflows/benchmark.yml
Triggers
workflow_dispatch, pull_request, push
Runs on
ubuntu-latest, ubuntu-latest
Jobs
determine-matrix, benchmark
Matrix
include→ ${{ fromJSON(needs.determine-matrix.outputs.matrix) }}
Actions
taiki-e/checkout-action, taiki-e/checkout-action, oxc-project/setup-rust, CodSpeedHQ/action
Commands
  • MATRIX=$(node .github/scripts/generate-benchmark-matrix.js) echo "Matrix: $MATRIX" echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
  • if [ "${{ matrix.component }}" = "linter" ]; then cargo build --release -p oxc_benchmark --bench linter \ --no-default-features --features ${{ matrix.feature }} --features codspeed else cargo build --release -p oxc_benchmark \ --bench ${{ matrix.component }} \ --no-default-features --features ${{ matrix.feature }} --features codspeed fi mkdir -p target/codspeed/analysis/oxc_benchmark mv target/release/deps/${{ matrix.component }}-* target/codspeed/analysis/oxc_benchmark rm target/codspeed/analysis/oxc_benchmark/*.d
View raw YAML
# Benchmarks are sharded.
#
# Each benchmark (parser, transformer, etc) runs in parallel in a separate job.
#
# See https://docs.codspeed.io/features/sharded-benchmarks

name: Benchmark

permissions: {}

on:
  workflow_dispatch:
  pull_request:
    types: [opened, synchronize]
    branches-ignore:
      - "**/graphite-base/**"
    paths: &paths
      - "crates/**/*.rs"
      - "tasks/benchmark/**/*.rs"
      - "tasks/common/**/*.rs"
      - "Cargo.lock"
      - "rust-toolchain.toml"
      - ".github/workflows/benchmark.yml"
  push:
    branches:
      - main
    paths: *paths

concurrency:
  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
  cancel-in-progress: true

jobs:
  determine-matrix:
    name: Determine Benchmark
    runs-on: ubuntu-latest
    if: ${{ github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, '0-merge') }}
    outputs:
      matrix: ${{ steps.set-matrix.outputs.matrix }}
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - name: Determine affected components
        id: set-matrix
        env:
          GITHUB_EVENT_NAME: ${{ github.event_name }}
          GITHUB_BASE_REF: ${{ github.base_ref }}
          GITHUB_REPOSITORY: ${{ github.repository }}
          GITHUB_SHA: ${{ github.sha }}
          GITHUB_REF: ${{ github.ref }}
          GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          MATRIX=$(node .github/scripts/generate-benchmark-matrix.js)
          echo "Matrix: $MATRIX"
          echo "matrix=$MATRIX" >> $GITHUB_OUTPUT

  benchmark:
    needs: determine-matrix
    if: needs.determine-matrix.outputs.matrix != '[]'
    runs-on: ubuntu-latest
    permissions:
      id-token: write # required for OIDC authentication with CodSpeed
    strategy:
      fail-fast: false
      matrix:
        include: ${{ fromJSON(needs.determine-matrix.outputs.matrix) }}
    name: Bench ${{ matrix.component }}
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
        with:
          cache-key: benchmark-${{ matrix.feature }}
          save-cache: ${{ github.ref_name == 'main' }}
          tools: cargo-codspeed

      - name: Build benchmark
        env:
          RUSTFLAGS: "-C debuginfo=1 -C strip=none -g --cfg codspeed"
        run: |
          if [ "${{ matrix.component }}" = "linter" ]; then
            cargo build --release -p oxc_benchmark --bench linter \
              --no-default-features --features ${{ matrix.feature }} --features codspeed
          else
            cargo build --release -p oxc_benchmark \
              --bench ${{ matrix.component }} \
              --no-default-features --features ${{ matrix.feature }} --features codspeed
          fi
          mkdir -p target/codspeed/analysis/oxc_benchmark
          mv target/release/deps/${{ matrix.component }}-* target/codspeed/analysis/oxc_benchmark
          rm target/codspeed/analysis/oxc_benchmark/*.d

      - name: Run benchmark
        uses: CodSpeedHQ/action@1c8ae4843586d3ba879736b7f6b7b0c990757fab # v4.12.1
        timeout-minutes: 30
        with:
          mode: simulation
          run: cargo codspeed run ${{ matrix.component }}
bloat perms .github/workflows/bloat.yml
Triggers
workflow_dispatch
Runs on
ubuntu-latest
Jobs
bloat
Actions
taiki-e/checkout-action, oxc-project/setup-rust
Commands
  • echo "# Bloat Summary" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "## Largest functions" >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY cargo bloat --release -p oxlint --features allocator -n 15 >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY echo "## Largest crates" >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY cargo bloat --release -p oxlint --features allocator --crates -n 15 >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY
View raw YAML
# Run `cargo bloat` for finding out what takes most of the space in your executable.

name: Cargo Bloat

permissions: {}

on:
  workflow_dispatch:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
  cancel-in-progress: true

jobs:
  bloat:
    name: Cargo Bloat
    runs-on: ubuntu-latest
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
        with:
          cache-key: warm
          tools: cargo-bloat

      - name: Run
        env:
          RUSTFLAGS: "-C debuginfo=2 -C strip=none"
        shell: bash
        run: |
          echo "# Bloat Summary" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY

          echo "## Largest functions" >> $GITHUB_STEP_SUMMARY
          echo '```' >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          cargo bloat --release -p oxlint --features allocator -n 15 >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo '```' >> $GITHUB_STEP_SUMMARY

          echo "## Largest crates" >> $GITHUB_STEP_SUMMARY
          echo '```' >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          cargo bloat --release -p oxlint --features allocator --crates -n 15 >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo '```' >> $GITHUB_STEP_SUMMARY
cargo_llvm_lines perms .github/workflows/cargo_llvm_lines.yml
Triggers
workflow_dispatch
Runs on
ubuntu-latest
Jobs
bloat
Actions
taiki-e/checkout-action, oxc-project/setup-rust, taiki-e/install-action
Commands
  • cargo llvm-lines -p oxc_parser | head -20 > $GITHUB_STEP_SUMMARY
View raw YAML
# Run `cargo-llvm-lines` for finding out bloat generic functions

name: Cargo LLVM Lines

permissions: {}

on:
  workflow_dispatch:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
  cancel-in-progress: true

jobs:
  bloat:
    name: Cargo LLVM Lines
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16

      - name: Install cargo-llvm-lines
        uses: taiki-e/install-action@06203676c62f0d3c765be3f2fcfbebbcb02d09f5 # v2.69.6
        with:
          tool: cargo-llvm-lines

      - name: Run
        run: cargo llvm-lines -p oxc_parser | head -20 > $GITHUB_STEP_SUMMARY
ci perms .github/workflows/ci.yml
Triggers
workflow_dispatch, pull_request, push
Runs on
namespace-profile-linux-x64-default, ubuntu-24.04-arm, namespace-profile-mac-default, windows-latest, namespace-profile-linux-x64-default, namespace-profile-linux-x64-default, namespace-profile-linux-x64-default, namespace-profile-linux-x64-default, namespace-profile-linux-x64-default, namespace-profile-linux-x64-default, windows-latest, windows-latest, windows-latest, ubuntu-slim, namespace-profile-linux-x64-default, namespace-profile-linux-x64-default, namespace-profile-linux-x64-default, namespace-profile-linux-x64-default, namespace-profile-linux-x64-default, namespace-profile-linux-x64-default, namespace-profile-linux-x64-default
Jobs
test-ubuntu, test-ubuntu-aarch64, test-mac, test-windows, test-big-endian, test-32bit, test-wasm32-wasip1-threads, test-napi-compiler, test-napi-oxlint, test-napi-oxfmt, test-napi-compiler-windows, test-napi-oxlint-windows, test-napi-oxfmt-windows, typos, lint, doc, conformance, minification, allocs, ast_changes, lintgen
Actions
taiki-e/checkout-action, oxc-project/setup-node, namespacelabs/nscloud-cache-action, taiki-e/checkout-action, oxc-project/setup-node, oxc-project/setup-rust, taiki-e/checkout-action, oxc-project/setup-node, namespacelabs/nscloud-cache-action, taiki-e/checkout-action, oxc-project/setup-node, samypr100/setup-dev-drive, Swatinem/rust-cache, taiki-e/checkout-action, namespacelabs/nscloud-cache-action, taiki-e/install-action, taiki-e/checkout-action, namespacelabs/nscloud-cache-action, taiki-e/install-action, taiki-e/checkout-action, oxc-project/setup-node, namespacelabs/nscloud-cache-action, taiki-e/checkout-action, oxc-project/setup-node, namespacelabs/nscloud-cache-action, taiki-e/checkout-action, oxc-project/setup-node, namespacelabs/nscloud-cache-action, taiki-e/checkout-action, oxc-project/setup-node, namespacelabs/nscloud-cache-action, taiki-e/checkout-action, oxc-project/setup-node, samypr100/setup-dev-drive, oxc-project/setup-rust, taiki-e/checkout-action, oxc-project/setup-node, samypr100/setup-dev-drive, oxc-project/setup-rust, taiki-e/checkout-action, oxc-project/setup-node, samypr100/setup-dev-drive, oxc-project/setup-rust, taiki-e/checkout-action, crate-ci/typos, taiki-e/checkout-action, oxc-project/setup-node, namespacelabs/nscloud-cache-action, taiki-e/checkout-action, namespacelabs/nscloud-cache-action, taiki-e/checkout-action, oxc-project/setup-node, namespacelabs/nscloud-cache-action, taiki-e/install-action, taiki-e/checkout-action, namespacelabs/nscloud-cache-action, taiki-e/checkout-action, namespacelabs/nscloud-cache-action, taiki-e/checkout-action, dorny/paths-filter, oxc-project/setup-node, namespacelabs/nscloud-cache-action, taiki-e/checkout-action, namespacelabs/nscloud-cache-action
Commands
  • cargo ck
  • cargo test --all-features
  • git diff --exit-code
  • cargo ck
  • cargo test --all-features
  • git diff --exit-code
  • cargo ck
  • cargo test --all-features
View raw YAML
name: CI

permissions: {}

on:
  workflow_dispatch:
  pull_request:
    types: [opened, synchronize]
    branches-ignore:
      - "**/graphite-base/**"
  push:
    branches:
      - main

concurrency:
  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
  cancel-in-progress: ${{ github.ref_name != 'main' }}

jobs:
  test-ubuntu:
    name: Test Linux
    runs-on: namespace-profile-linux-x64-default
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0
      - uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
        with:
          path: /home/runner/.rustup
          cache: |
            rust
            pnpm
      - run: cargo ck
      - run: cargo test --all-features
      - run: git diff --exit-code # Must commit everything

  test-ubuntu-aarch64:
    if: ${{ github.ref_name == 'main' }}
    name: Test Linux ARM64
    runs-on: ubuntu-24.04-arm
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0
      - uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
        with:
          save-cache: ${{ github.ref_name == 'main' }}
          cache-key: warm-aarch64
      - run: cargo ck
      - run: cargo test --all-features
      - run: git diff --exit-code # Must commit everything

  test-mac: # Separate job to save a job on PRs
    if: ${{ github.ref_name == 'main' }}
    name: Test Mac
    runs-on: namespace-profile-mac-default
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0
      - uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
        with:
          cache: |
            rust
            pnpm
      - run: cargo ck
      - run: cargo test --all-features
      - run: git diff --exit-code # Must commit everything

  test-windows:
    if: ${{ github.ref_name == 'main' }}
    name: Test Windows
    runs-on: windows-latest
    steps:
      - run: git config --system core.longpaths true
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      # Unsung heroes of the internet, who led me here to speed up Windows' slowness:
      # https://github.com/actions/cache/issues/752#issuecomment-1847036770
      # https://github.com/astral-sh/uv/blob/502e04200d52de30d3159894833b3db4f0d6644d/.github/workflows/ci.yml#L158
      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0
      - uses: samypr100/setup-dev-drive@30f0f98ae5636b2b6501e181dfb3631b9974818d # v4.0.0
        with:
          workspace-copy: true
          drive-size: 12GB
          drive-format: ReFS
          env-mapping: |
            CARGO_HOME,{{ DEV_DRIVE }}/.cargo
            RUSTUP_HOME,{{ DEV_DRIVE }}/.rustup

      - name: Install Rust
        working-directory: ${{ env.DEV_DRIVE_WORKSPACE }}
        shell: bash
        run: |
          # This `awk` command will find the value of our Minimum Supported Rust Version and store it as `MSRV`.
          # NOTE: this will fail if there are any other items named `rust-version`. We assume there is only one in our `Cargo.toml`.
          MSRV=$(awk -F'=' '/rust-version/ {gsub(/[" ]/, "", $2); printf "%s", ($2 + "")}' Cargo.toml)
          # Set profile to minimal and channel to our Minimum Supported Rust Version.
          # Running our tests on this channel ensures that our code uses APIs that are supported in our `MSRV`.
          sed -i -e 's/profile = "default"/profile = "minimal"/g' -e "s/channel = .*/channel = \"$MSRV\"/g" rust-toolchain.toml
          rustup set profile minimal
          rustup show
          git restore .

      - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
        with:
          workspaces: ${{ env.DEV_DRIVE_WORKSPACE }}
          save-if: ${{ github.ref_name == 'main' }}
          shared-key: windows-latest

      - name: Run tests
        # No need for `cargo ck` because it's already checked in linux
        # Run `website` tests separately to avoid feature unification problems with `oxlint`
        run: cargo test --all-features
        working-directory: ${{ env.DEV_DRIVE_WORKSPACE }}
        shell: bash

  test-big-endian:
    if: ${{ github.ref_name == 'main' }}
    name: Test big-endian # s390x-unknown-linux-gnu is a big-endian
    runs-on: namespace-profile-linux-x64-default
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
        with:
          path: /home/runner/.rustup
          cache: rust
      - uses: taiki-e/install-action@06203676c62f0d3c765be3f2fcfbebbcb02d09f5 # v2.69.6
        with:
          tool: cross
      # `--lib --bins --tests` to skip doctests which are very slow to run via `cross`.
      # https://github.com/cross-rs/cross/issues/1703
      - run: cross test --lib --bins --tests --all-features --target s390x-unknown-linux-gnu

  test-32bit:
    if: ${{ github.ref_name == 'main' }}
    name: Test 32-bit # armv7-unknown-linux-gnueabihf is a 32-bit target
    runs-on: namespace-profile-linux-x64-default
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
        with:
          path: /home/runner/.rustup
          cache: rust
      - uses: taiki-e/install-action@06203676c62f0d3c765be3f2fcfbebbcb02d09f5 # v2.69.6
        with:
          tool: cross
      # `--lib --bins --tests` to skip doctests which are very slow to run via `cross`.
      # https://github.com/cross-rs/cross/issues/1703
      - run: cross test --workspace --lib --bins --tests --all-features --exclude oxc_language_server --exclude oxc_linter --exclude oxlint --target armv7-unknown-linux-gnueabihf

  test-wasm32-wasip1-threads:
    name: Test wasm32-wasip1-threads
    runs-on: namespace-profile-linux-x64-default
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: ./.github/actions/check-changes
        id: filter
        with:
          exclude: oxc_linter
          paths: napi/,npm/,apps/,pnpm-lock.yaml,package.json
          token: ${{ secrets.GITHUB_TOKEN }}
          pr-number: ${{ github.event.pull_request.number }}
      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0
        if: steps.filter.outputs.changed == 'true'
      - uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
        if: steps.filter.outputs.changed == 'true'
        with:
          path: /home/runner/.rustup
          cache: |
            rust
            pnpm
      - name: Build
        if: steps.filter.outputs.changed == 'true'
        run: |
          rustup target add wasm32-wasip1-threads
          pnpm run build-wasm-dev
          git diff --exit-code # Must commit everything
      - name: Test wasi in browser
        if: steps.filter.outputs.changed == 'true'
        working-directory: napi/parser
        run: |
          rm -rf *.wasm
          pnpm exec playwright install chromium
          pnpm run build-wasi
          pnpm run build-wasm-dev
          pnpm run build-npm-dir
          pnpm run test-browser
          pnpm build-browser-bundle --npmDir npm-dir

  test-napi-compiler:
    name: Test NAPI Compiler
    runs-on: namespace-profile-linux-x64-default
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: ./.github/actions/check-changes
        id: filter
        with:
          exclude: oxc_linter,oxc_language_server
          paths: napi/parser/,napi/minify/,napi/transform/,npm/oxc-types/,npm/runtime/,tasks/e2e/,pnpm-lock.yaml,package.json
          token: ${{ secrets.GITHUB_TOKEN }}
          pr-number: ${{ github.event.pull_request.number }}
      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0
        if: steps.filter.outputs.changed == 'true'
      - uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
        if: steps.filter.outputs.changed == 'true'
        with:
          path: /home/runner/.rustup
          cache: |
            rust
            pnpm
      - uses: ./.github/actions/clone-submodules
        if: steps.filter.outputs.changed == 'true'
        with:
          babel: false
          prettier: false
          node-compat-table: false
      - if: steps.filter.outputs.changed == 'true'
        name: Run tests
        env:
          RUN_RAW_RANGE_TESTS: "true"
          RUN_RAW_TOKENS_TESTS: "true"
        run: |
          pnpm --workspace-concurrency=1 --filter "./napi/parser" --filter "./napi/minify" --filter "./napi/transform" build-test
          pnpm --workspace-concurrency=1 --filter "./napi/parser" --filter "./napi/minify" --filter "./napi/transform" test
      - if: steps.filter.outputs.changed == 'true'
        name: Run e2e tests
        working-directory: tasks/e2e
        run: pnpm run test
      - if: steps.filter.outputs.changed == 'true'
        run: |
          git diff --exit-code # Must commit everything

  test-napi-oxlint:
    name: Test NAPI Oxlint
    runs-on: namespace-profile-linux-x64-default
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: ./.github/actions/check-changes
        id: filter
        with:
          paths: apps/oxlint/,npm/oxlint/,npm/oxlint-plugin-eslint/,npm/oxlint-plugins/,npm/oxc-types/,pnpm-lock.yaml,package.json
          token: ${{ secrets.GITHUB_TOKEN }}
          pr-number: ${{ github.event.pull_request.number }}
      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0
        if: steps.filter.outputs.changed == 'true'
      - uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
        if: steps.filter.outputs.changed == 'true'
        with:
          path: /home/runner/.rustup
          cache: |
            rust
            pnpm
      - if: steps.filter.outputs.changed == 'true'
        name: Run tests
        run: |
          pnpm --filter "./apps/oxlint" build-test
          pnpm --filter "./apps/oxlint" test
      - if: steps.filter.outputs.changed == 'true'
        run: |
          git diff --exit-code # Must commit everything

  test-napi-oxfmt:
    name: Test NAPI Oxfmt
    runs-on: namespace-profile-linux-x64-default
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: ./.github/actions/check-changes
        id: filter
        with:
          paths: apps/oxfmt/,npm/oxfmt/,pnpm-lock.yaml,package.json
          token: ${{ secrets.GITHUB_TOKEN }}
          pr-number: ${{ github.event.pull_request.number }}
      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0
        if: steps.filter.outputs.changed == 'true'
      - uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
        if: steps.filter.outputs.changed == 'true'
        with:
          path: /home/runner/.rustup
          cache: |
            rust
            pnpm
      - if: steps.filter.outputs.changed == 'true'
        name: Run tests
        run: |
          pnpm --filter "./apps/oxfmt" build-test
          pnpm --filter "./apps/oxfmt" test
      - if: steps.filter.outputs.changed == 'true'
        run: |
          git diff --exit-code # Must commit everything

  test-napi-compiler-windows:
    name: Test NAPI Compiler (windows)
    runs-on: windows-latest
    if: ${{ github.ref_name == 'main' }}
    steps:
      - run: git config --system core.longpaths true
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: ./.github/actions/check-changes
        id: filter
        with:
          exclude: oxc_linter,oxc_language_server
          paths: napi/parser/,napi/minify/,napi/transform/,npm/oxc-types/,npm/runtime/,tasks/e2e/,pnpm-lock.yaml,package.json
          token: ${{ secrets.GITHUB_TOKEN }}
          pr-number: ${{ github.event.pull_request.number }}
      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0
        if: steps.filter.outputs.changed == 'true'
      - uses: samypr100/setup-dev-drive@30f0f98ae5636b2b6501e181dfb3631b9974818d # v4.0.0
        if: steps.filter.outputs.changed == 'true'
        with:
          workspace-copy: true
          drive-size: 12GB
          drive-format: ReFS
          env-mapping: |
            CARGO_HOME,{{ DEV_DRIVE }}/.cargo
            RUSTUP_HOME,{{ DEV_DRIVE }}/.rustup
      - uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
        if: steps.filter.outputs.changed == 'true'
        with:
          cache-key: napi
          save-cache: ${{ github.ref_name == 'main' }}
      - uses: ./.github/actions/clone-submodules
        if: steps.filter.outputs.changed == 'true'
        with:
          babel: false
          prettier: false
          node-compat-table: false
      - if: steps.filter.outputs.changed == 'true'
        name: Run tests
        working-directory: ${{ env.DEV_DRIVE_WORKSPACE }}
        env:
          RUN_RAW_RANGE_TESTS: "true"
        run: |
          pnpm --workspace-concurrency=1 --filter "./napi/parser" --filter "./napi/minify" --filter "./napi/transform" build-test
          pnpm --workspace-concurrency=1 --filter "./napi/parser" --filter "./napi/minify" --filter "./napi/transform" test
      - if: steps.filter.outputs.changed == 'true'
        name: Run e2e tests
        working-directory: ${{ env.DEV_DRIVE_WORKSPACE }}/tasks/e2e
        run: |
          pnpm install --frozen-lockfile
          pnpm run test
      - if: steps.filter.outputs.changed == 'true'
        working-directory: ${{ env.DEV_DRIVE_WORKSPACE }}
        run: |
          git diff --exit-code # Must commit everything

  test-napi-oxlint-windows:
    name: Test NAPI Oxlint (windows)
    runs-on: windows-latest
    if: ${{ github.ref_name == 'main' }}
    steps:
      - run: git config --system core.longpaths true
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: ./.github/actions/check-changes
        id: filter
        with:
          paths: apps/oxlint/,npm/oxlint/,npm/oxlint-plugin-eslint/,npm/oxlint-plugins/,npm/oxc-types/,pnpm-lock.yaml,package.json
          token: ${{ secrets.GITHUB_TOKEN }}
          pr-number: ${{ github.event.pull_request.number }}
      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0
        if: steps.filter.outputs.changed == 'true'
      - uses: samypr100/setup-dev-drive@30f0f98ae5636b2b6501e181dfb3631b9974818d # v4.0.0
        if: steps.filter.outputs.changed == 'true'
        with:
          workspace-copy: true
          drive-size: 12GB
          drive-format: ReFS
          env-mapping: |
            CARGO_HOME,{{ DEV_DRIVE }}/.cargo
            RUSTUP_HOME,{{ DEV_DRIVE }}/.rustup
      - uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
        if: steps.filter.outputs.changed == 'true'
        with:
          cache-key: napi
          save-cache: ${{ github.ref_name == 'main' }}
      - if: steps.filter.outputs.changed == 'true'
        name: Run tests
        working-directory: ${{ env.DEV_DRIVE_WORKSPACE }}
        run: |
          pnpm --filter "./apps/oxlint" build-test
          pnpm --filter "./apps/oxlint" test
      - if: steps.filter.outputs.changed == 'true'
        working-directory: ${{ env.DEV_DRIVE_WORKSPACE }}
        run: |
          git diff --exit-code # Must commit everything

  test-napi-oxfmt-windows:
    name: Test NAPI Oxfmt (windows)
    runs-on: windows-latest
    if: ${{ github.ref_name == 'main' }}
    steps:
      - run: git config --system core.longpaths true
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: ./.github/actions/check-changes
        id: filter
        with:
          paths: apps/oxfmt/,npm/oxfmt/,pnpm-lock.yaml,package.json
          token: ${{ secrets.GITHUB_TOKEN }}
          pr-number: ${{ github.event.pull_request.number }}
      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0
        if: steps.filter.outputs.changed == 'true'
      - uses: samypr100/setup-dev-drive@30f0f98ae5636b2b6501e181dfb3631b9974818d # v4.0.0
        if: steps.filter.outputs.changed == 'true'
        with:
          workspace-copy: true
          drive-size: 12GB
          drive-format: ReFS
          env-mapping: |
            CARGO_HOME,{{ DEV_DRIVE }}/.cargo
            RUSTUP_HOME,{{ DEV_DRIVE }}/.rustup
      - uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
        if: steps.filter.outputs.changed == 'true'
        with:
          cache-key: napi
          save-cache: ${{ github.ref_name == 'main' }}
      - if: steps.filter.outputs.changed == 'true'
        name: Run tests
        working-directory: ${{ env.DEV_DRIVE_WORKSPACE }}
        run: |
          pnpm --filter "./apps/oxfmt" build-test
          pnpm --filter "./apps/oxfmt" test
      - if: steps.filter.outputs.changed == 'true'
        working-directory: ${{ env.DEV_DRIVE_WORKSPACE }}
        run: |
          git diff --exit-code # Must commit everything

  typos:
    name: Spell Check
    runs-on: ubuntu-slim
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: crate-ci/typos@631208b7aac2daa8b707f55e7331f9112b0e062d # v1.44.0
        with:
          files: .

  lint:
    name: Lint
    runs-on: namespace-profile-linux-x64-default
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0
      - uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
        with:
          path: /home/runner/.rustup
          cache: |
            rust
            pnpm
      - run: rustup component add clippy
      - run: cargo lint -- -D warnings
      - run: cargo lint --profile dev-no-debug-assertions -- -D warnings
      - run: pnpm --filter oxlint-app build-js
      - run: pnpm --filter oxfmt-app build-js
      - run: node --run lint

  doc:
    name: Doc
    runs-on: namespace-profile-linux-x64-default
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
        with:
          path: /home/runner/.rustup
          cache: rust
      - run: rustup toolchain install nightly --profile minimal --component rust-docs
      # https://github.com/rust-lang/rust/issues/146895
      - run: RUSTDOCFLAGS='-D warnings' cargo +nightly doc --no-deps --document-private-items -Zrustdoc-mergeable-info

  conformance:
    name: Conformance
    runs-on: namespace-profile-linux-x64-default
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - name: Check if conformance should run
        id: filter
        uses: ./.github/actions/check-changes
        with:
          packages: oxc_coverage,oxc_transform_conformance,oxc_prettier_conformance
          paths: tasks/coverage/,tasks/common/,tasks/oxc_transform_conformance/,tasks/oxc_prettier_conformance/,pnpm-lock.yaml
          token: ${{ secrets.GITHUB_TOKEN }}
          pr-number: ${{ github.event.pull_request.number }}

      - uses: ./.github/actions/clone-submodules
        if: steps.filter.outputs.changed == 'true'
        with:
          node-compat-table: false

      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0
        if: steps.filter.outputs.changed == 'true'

      - uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
        if: steps.filter.outputs.changed == 'true'
        with:
          path: /home/runner/.rustup
          cache: |
            rust
            pnpm

      - uses: taiki-e/install-action@06203676c62f0d3c765be3f2fcfbebbcb02d09f5 # v2.69.6
        if: steps.filter.outputs.changed == 'true'
        with:
          tool: just

      - name: Check Conformance
        if: steps.filter.outputs.changed == 'true'
        run: |
          just update-transformer-fixtures
          just coverage
          git diff --exit-code

  minification:
    name: Minification Size
    runs-on: namespace-profile-linux-x64-default
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: ./.github/actions/check-changes
        id: filter
        with:
          packages: oxc_minsize
          token: ${{ secrets.GITHUB_TOKEN }}
          pr-number: ${{ github.event.pull_request.number }}

      - uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
        with:
          path: /home/runner/.rustup
          cache: rust

      - name: Check minification size
        if: steps.filter.outputs.changed == 'true'
        run: |
          cargo minsize
          git diff --exit-code

  allocs:
    name: Allocations
    runs-on: namespace-profile-linux-x64-default
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: ./.github/actions/check-changes
        id: filter
        with:
          packages: oxc_track_memory_allocations
          token: ${{ secrets.GITHUB_TOKEN }}
          pr-number: ${{ github.event.pull_request.number }}

      - uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
        with:
          path: /home/runner/.rustup
          cache: rust

      - name: Check allocations
        if: steps.filter.outputs.changed == 'true'
        run: |
          cargo allocs
          git diff --exit-code ||
          (echo 'Allocations have changed. Run the `cargo allocs` command to update the allocation snapshot, otherwise please fix the regression.' && exit 1)

  ast_changes:
    name: AST Changes
    runs-on: namespace-profile-linux-x64-default
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
        id: filter
        with:
          filters: ".github/generated/ast_changes_watch_list.yml"

      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0
        if: steps.filter.outputs.src == 'true'

      - uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
        if: steps.filter.outputs.src == 'true'
        with:
          path: /home/runner/.rustup
          cache: |
            rust
            pnpm

      - run: rustup component add rustfmt
        if: steps.filter.outputs.src == 'true'

      - name: Check AST Changes
        if: steps.filter.outputs.src == 'true'
        run: |
          cargo run -p oxc_ast_tools
          git diff --exit-code ||
          (echo 'AST changes caused the "generated" code to get outdated. Have you forgotten to run the `just ast` command and/or commit generated codes?' && exit 1)

  lintgen:
    name: Linter changes
    runs-on: namespace-profile-linux-x64-default
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: ./.github/actions/check-changes
        id: filter
        with:
          packages: oxc_linter
          paths: tasks/linter_codegen/
          token: ${{ secrets.GITHUB_TOKEN }}
          pr-number: ${{ github.event.pull_request.number }}

      - uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
        with:
          path: /home/runner/.rustup
          cache: rust

      - run: rustup component add rustfmt
        if: steps.filter.outputs.changed == 'true'

      - name: Check linter changes
        if: steps.filter.outputs.changed == 'true'
        run: |
          cargo lintgen
          git diff --exit-code ||
          (echo 'Linter codegen has changed. Run the `cargo lintgen` command to update the linter code generated and commit it.' && exit 1)
ci_security perms security .github/workflows/ci_security.yml
Triggers
workflow_dispatch, pull_request, push
Runs on
ubuntu-slim
Jobs
zizmor
Actions
taiki-e/checkout-action, taiki-e/install-action, github/codeql-action/upload-sarif
Commands
  • zizmor --format sarif . > results.sarif
View raw YAML
name: GitHub Actions Security Analysis

permissions: {}

on:
  workflow_dispatch:
  pull_request:
    types: [opened, synchronize]
    paths:
      - ".github/workflows/**"
  push:
    branches:
      - main
    paths:
      - ".github/workflows/**"

jobs:
  zizmor:
    name: zizmor
    runs-on: ubuntu-slim
    permissions:
      security-events: write
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: taiki-e/install-action@06203676c62f0d3c765be3f2fcfbebbcb02d09f5 # v2.69.6
        with:
          tool: zizmor

      - name: Run zizmor
        run: zizmor --format sarif . > results.sarif
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Upload SARIF file
        uses: github/codeql-action/upload-sarif@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1
        with:
          sarif_file: results.sarif
          category: zizmor
claude AI .github/workflows/claude.yml
Triggers
issues
Runs on
ubuntu-slim
Jobs
analyze
Actions
anthropics/claude-code-action
Commands
  • gh issue edit ${{ github.event.issue.number }} --remove-assignee boshen
View raw YAML
name: Claude Code

on:
  issues:
    types: [assigned]

jobs:
  analyze:
    if: github.event.action == 'assigned' && github.event.assignee.login == 'boshen' && github.event.sender.login == 'boshen'
    runs-on: ubuntu-slim
    permissions:
      contents: read
      issues: write
      id-token: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 100
          persist-credentials: true

      - name: Run Claude Code
        id: claude
        uses: anthropics/claude-code-action@6062f3709600659be5e47fcddf2cf76993c235c2 # v1.0.76
        with:
          claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
          assignee_trigger: "boshen"
          claude_args: --allowedTools "Edit,Write,Read,Glob,Grep,Bash(gh:*),Bash(cargo:*),Bash(git:*),Bash(just:*),WebFetch,TodoWrite"
          prompt: |
            Analyze issue #${{ github.event.issue.number }} in ${{ github.repository }} and determine if it can be fixed.

            First, use `gh issue view ${{ github.event.issue.number }}` to read the issue details.

            Then:
            1. Search the codebase to gather relevant context (related files, existing implementations, tests)
            2. Determine if the issue is fixable and estimate the complexity

            Finally, post a comment on the issue with:
            - A brief summary of your understanding of the issue
            - Relevant files/code you found
            - Whether this issue is fixable (yes/no/needs clarification)
            - If the issue is unclear, ask for more context
            - If fixable, provide a concrete implementation plan with specific steps
            - Any potential concerns or blockers

      - name: Unassign boshen
        if: always()
        env:
          GH_TOKEN: ${{ github.token }}
        run: gh issue edit ${{ github.event.issue.number }} --remove-assignee boshen
codecov perms .github/workflows/codecov.yml
Triggers
workflow_dispatch, push
Runs on
namespace-profile-linux-x64-default, ubuntu-slim
Jobs
coverage, upload-codecov
Actions
taiki-e/checkout-action, namespacelabs/nscloud-cache-action, oxc-project/setup-node, taiki-e/install-action, taiki-e/checkout-action, codecov/codecov-action
Commands
  • rustup component add llvm-tools-preview
  • cargo codecov --lcov --output-path lcov.info
View raw YAML
# Run cargo-llvm-cov and upload to codecov.io

name: Code Coverage

permissions: {}

on:
  workflow_dispatch:
  push:
    branches:
      - main
    paths:
      - "**.rs"
      - ".github/workflows/codecov.yml"

concurrency:
  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
  cancel-in-progress: ${{ github.ref_name != 'main' }}

jobs:
  coverage:
    if: github.repository == 'oxc-project/oxc'
    name: Code Coverage
    runs-on: namespace-profile-linux-x64-default
    steps:
      - name: Checkout
        uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - name: Clone submodules
        uses: ./.github/actions/clone-submodules

      - uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
        with:
          path: /home/runner/.rustup
          cache: rust

      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0

      - run: rustup component add llvm-tools-preview
      - uses: taiki-e/install-action@06203676c62f0d3c765be3f2fcfbebbcb02d09f5 # v2.69.6
        with:
          tool: cargo-llvm-cov

      - name: Run
        env:
          # Increase stack size to 10MB, avoid `oxc_formatter` from stack overflowing when printing long assignment expressions.
          RUST_MIN_STACK: 104857600
        run: cargo codecov --lcov --output-path lcov.info

      - name: Upload Artifact
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          if-no-files-found: error
          name: codecov
          path: lcov.info

  # codecov often fails, use another workflow for retry
  upload-codecov:
    name: Upload coverage file
    runs-on: ubuntu-slim
    needs: coverage
    # Check if the event is not triggered by a fork by checking whether CODECOV_TOKEN is set
    env:
      CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
    steps:
      - name: Checkout
        if: env.CODECOV_TOKEN
        uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - name: Download coverage file
        if: env.CODECOV_TOKEN
        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
        with:
          name: codecov

      - name: Upload to codecov.io
        if: env.CODECOV_TOKEN
        uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # v5.5.3
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          fail_ci_if_error: true
          files: lcov.info
copilot-setup-steps perms .github/workflows/copilot-setup-steps.yml
Triggers
workflow_dispatch, pull_request, push
Runs on
ubuntu-latest
Jobs
copilot-setup-steps
Actions
oxc-project/setup-rust, oxc-project/setup-node
View raw YAML
name: Copilot Setup Steps

# This workflow defines the setup steps that GitHub Copilot agents will use
# to prepare the development environment for the oxc project.
# It preinstalls tools and dependencies needed for Rust and Node.js development.

on:
  workflow_dispatch:
  pull_request:
    types: [opened, synchronize]
    paths:
      - .github/workflows/copilot-setup-steps.yml
  push:
    branches:
      - main
    paths:
      - .github/workflows/copilot-setup-steps.yml

permissions: {}

jobs:
  copilot-setup-steps:
    name: Setup Development Environment for Copilot
    runs-on: ubuntu-latest
    steps:
      # Checkout full repo for git history.
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          persist-credentials: false

      - uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
        with:
          cache-key: warm
          save-cache: false
          tools: just,cargo-insta,typos-cli,cargo-shear@1.11.2,ast-grep
          components: clippy rust-docs rustfmt rust-analyzer

      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0
deny perms .github/workflows/deny.yml
Triggers
workflow_dispatch, pull_request, push
Runs on
ubuntu-latest
Jobs
deny
Actions
taiki-e/checkout-action, oxc-project/setup-rust
Commands
  • cargo deny check
View raw YAML
name: Cargo Deny

permissions: {}

on:
  workflow_dispatch:
  pull_request:
    types: [opened, synchronize]
    paths:
      - "Cargo.lock"
      - "deny.toml"
      - ".github/workflows/deny.yml"
  push:
    branches:
      - main
    paths:
      - "Cargo.lock"
      - "deny.toml"
      - ".github/workflows/deny.yml"

concurrency:
  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
  cancel-in-progress: ${{ github.ref_name != 'main' }}

jobs:
  deny:
    name: Cargo Deny
    runs-on: ubuntu-latest
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
        with:
          restore-cache: false
          tools: cargo-deny

      - run: cargo deny check
issue-close-require .github/workflows/issue-close-require.yml
Triggers
schedule
Runs on
ubuntu-latest
Jobs
close-issues
Actions
actions-cool/issues-helper
View raw YAML
name: Issue Close Require

on:
  schedule:
    - cron: "0 0 * * *"

jobs:
  close-issues:
    if: github.repository == 'oxc-project/oxc'
    runs-on: ubuntu-latest
    permissions:
      issues: write
      pull-requests: write
    steps:
      - name: needs reproduction
        uses: actions-cool/issues-helper@200c78641dbf33838311e5a1e0c31bbdb92d7cf0 # v3.8.0
        with:
          actions: "close-issues"
          token: ${{ secrets.GITHUB_TOKEN }}
          labels: "needs reproduction"
          inactive-day: 3
issue-labeled .github/workflows/issue-labeled.yml
Triggers
issues
Runs on
ubuntu-latest
Jobs
reply-labeled
Actions
actions-cool/issues-helper, actions-cool/issues-helper
View raw YAML
name: Issue Labeled

on:
  issues:
    types: [labeled]

jobs:
  reply-labeled:
    if: github.repository == 'oxc-project/oxc'
    runs-on: ubuntu-latest
    permissions:
      issues: write
      pull-requests: write
    steps:
      - name: contribution welcome
        if: github.event.label.name == 'good first issue' || github.event.label.name == 'E-Help Wanted'
        uses: actions-cool/issues-helper@200c78641dbf33838311e5a1e0c31bbdb92d7cf0 # v3.8.0
        with:
          actions: "remove-labels"
          token: ${{ secrets.GITHUB_TOKEN }}
          issue-number: ${{ github.event.issue.number }}
          labels: "pending triage, needs reproduction"

      - name: needs reproduction
        if: github.event.label.name == 'needs reproduction'
        uses: actions-cool/issues-helper@200c78641dbf33838311e5a1e0c31bbdb92d7cf0 # v3.8.0
        with:
          actions: "create-comment, remove-labels"
          token: ${{ secrets.GITHUB_TOKEN }}
          issue-number: ${{ github.event.issue.number }}
          labels: "pending triage"
          body: |
            Hello @${{ github.event.issue.user.login }}

            Please provide a [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) using a GitHub repository or a link to the [Oxc Playground](https://playground.oxc.rs). This helps us understand and resolve your issue much faster.

            **A good reproduction should be:**
            - **Minimal** - include only the code necessary to demonstrate the issue
            - **Complete** - contain everything needed to run and observe the problem
            - **Reproducible** - consistently show the issue with clear steps

            If no reproduction is provided, issues labeled `needs reproduction` will be closed after 3 days of inactivity.

            For more context on why this is required, please read: https://antfu.me/posts/why-reproductions-are-required
lint_rules perms .github/workflows/lint_rules.yml
Triggers
push
Runs on
ubuntu-slim
Jobs
lint_rules
Actions
taiki-e/checkout-action, oxc-project/setup-node
Commands
  • npm install
  • node ./tasks/lint_rules --update
View raw YAML
name: Update implementation status of all linter plugins

permissions: {}

on:
  push:
    branches:
      - main
    paths:
      - ".github/workflows/lint_rules.yml"
      - "crates/oxc_linter/src/rules.rs"
      - "crates/oxc_linter/src/utils/mod.rs" # here are the remaps for some plugins
      - "tasks/lint_rules/**"

jobs:
  lint_rules:
    if: github.repository == 'oxc-project/oxc'
    runs-on: ubuntu-slim
    permissions:
      contents: read
      issues: write
    steps:
      - name: Checkout Branch
        uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0

      - name: Install latest plugins
        working-directory: tasks/lint_rules
        run: npm install

      - name: Run task
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: node ./tasks/lint_rules --update
miri perms .github/workflows/miri.yml
Triggers
workflow_dispatch, pull_request, push
Runs on
namespace-profile-linux-x64-default
Jobs
miri
Actions
taiki-e/checkout-action, namespacelabs/nscloud-cache-action
Commands
  • rustup toolchain install "${MIRI_TOOLCHAIN}" --component miri cargo +"${MIRI_TOOLCHAIN}" miri setup
  • cargo +"${MIRI_TOOLCHAIN}" miri test --lib --bins --tests --all-features -p oxc_allocator -p oxc_ast -p oxc_data_structures cargo +"${MIRI_TOOLCHAIN}" miri test --lib --bins --tests -p oxc_parser -p oxc_transformer
View raw YAML
name: Miri

permissions: {}

on:
  workflow_dispatch:
  pull_request:
    types: [opened, synchronize]
    paths:
      - "crates/oxc_allocator/**"
      - "crates/oxc_ast/src/utf8_to_utf16.rs"
      - "crates/oxc_ast/src/generated/utf8_to_utf16_converter.rs"
      - "crates/oxc_data_structures/**"
      - "crates/oxc_parser/**"
      - "crates/oxc_traverse/**"
      - ".github/workflows/miri.yml"
  push:
    branches:
      - main
    paths:
      - "crates/oxc_allocator/**"
      - "crates/oxc_ast/src/utf8_to_utf16.rs"
      - "crates/oxc_ast/src/generated/utf8_to_utf16_converter.rs"
      - "crates/oxc_data_structures/**"
      - "crates/oxc_parser/**"
      - "crates/oxc_traverse/**"
      - ".github/workflows/miri.yml"

concurrency:
  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
  cancel-in-progress: true

jobs:
  miri:
    name: Miri
    runs-on: namespace-profile-linux-x64-default
    env:
      # FIXME: cargo-miri is broken on nightly-2026-02-12.
      # https://github.com/rust-lang/miri/issues/4855
      MIRI_TOOLCHAIN: nightly-2026-02-11
    steps:
      - name: Checkout
        uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: ./.github/actions/check-changes
        id: filter
        with:
          packages: oxc_allocator,oxc_ast,oxc_data_structures,oxc_parser,oxc_transformer
          paths: .github/workflows/miri.yml
          token: ${{ secrets.GITHUB_TOKEN }}
          pr-number: ${{ github.event.pull_request.number }}

      - uses: namespacelabs/nscloud-cache-action@a90bb5d4b27522ce881c6e98eebd7d7e6d1653f9 # v1.4.2
        with:
          path: /home/runner/.rustup
          cache: rust

      - name: Install Miri
        if: steps.filter.outputs.changed == 'true'
        run: |
          rustup toolchain install "${MIRI_TOOLCHAIN}" --component miri
          cargo +"${MIRI_TOOLCHAIN}" miri setup

      # `--lib --bins --tests` omits doctests, which Miri can't run
      # https://github.com/oxc-project/oxc/pull/11092
      - name: Test with Miri
        if: steps.filter.outputs.changed == 'true'
        run: |
          cargo +"${MIRI_TOOLCHAIN}" miri test --lib --bins --tests --all-features -p oxc_allocator -p oxc_ast -p oxc_data_structures
          cargo +"${MIRI_TOOLCHAIN}" miri test --lib --bins --tests -p oxc_parser -p oxc_transformer
pr perms .github/workflows/pr.yml
Triggers
pull_request_target
Runs on
ubuntu-slim
Jobs
pr
Actions
taiki-e/checkout-action, actions/labeler, amannn/action-semantic-pull-request, actions-ecosystem/action-add-labels
View raw YAML
name: Check PR

permissions: {}

on:
  pull_request_target: # zizmor: ignore[dangerous-triggers]
    types:
      - opened
      - edited
      - synchronize
    branches-ignore:
      - "**/graphite-base/**"

jobs:
  pr:
    if: github.repository == 'oxc-project/oxc'
    name: Label and Check PR Title
    permissions:
      contents: read
      pull-requests: write
    runs-on: ubuntu-slim
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1

      - name: Validate PR title
        id: pr-title
        uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          requireScope: true
          types: |
            build
            chore
            ci
            docs
            feat
            fix
            perf
            refactor
            release
            revert
            style
            test

      - name: Add category label
        uses: actions-ecosystem/action-add-labels@18f1af5e3544586314bbe15c0273249c770b2daf # v1.1.3
        env:
          CATEGORY: ${{ case(
            steps.pr-title.outputs.type == 'feat', 'C-enhancement',
            steps.pr-title.outputs.type == 'fix', 'C-bug',
            steps.pr-title.outputs.type == 'test', 'C-test',
            contains(fromJson('["refactor", "chore", "style"]'), steps.pr-title.outputs.type), 'C-cleanup',
            steps.pr-title.outputs.type == 'docs', 'C-docs',
            steps.pr-title.outputs.type == 'perf', 'C-performance',
            '') }}
        if: ${{ env.CATEGORY != '' }}
        with:
          labels: ${{ env.CATEGORY }}
prepare_release_apps perms .github/workflows/prepare_release_apps.yml
Triggers
workflow_dispatch, schedule
Runs on
ubuntu-latest, ubuntu-slim, ubuntu-slim
Jobs
prepare, ecosystem-ci, website
Actions
oxc-project/setup-rust, oxc-project/setup-node, peter-evans/create-pull-request, taiki-e/checkout-action, peter-evans/create-or-update-comment, peter-evans/create-or-update-comment, benc-uk/workflow-dispatch, benc-uk/workflow-dispatch, taiki-e/checkout-action, benc-uk/workflow-dispatch
Commands
  • cargo release-oxc update --release oxlint --release oxfmt echo "OXLINT_VERSION=$(cat ./target/OXLINT_VERSION)" >> $GITHUB_OUTPUT echo "OXFMT_VERSION=$(cat ./target/OXFMT_VERSION)" >> $GITHUB_OUTPUT { echo "# Oxlint" cat ./target/OXLINT_CHANGELOG echo "" echo "# Oxfmt" cat ./target/OXFMT_CHANGELOG } > ./target/PR_BODY.md
  • pnpm --filter oxlint-app run build-dev pnpm --filter oxfmt-app run build-dev
  • cargo check
View raw YAML
name: Prepare Release Apps

permissions: {}

on:
  workflow_dispatch:
  schedule:
    # Triggers every Monday at 5pm Shanghai time (9am UTC)
    - cron: "0 9 * * 1"

concurrency:
  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
  cancel-in-progress: true

jobs:
  prepare:
    if: github.repository == 'oxc-project/oxc'
    name: Prepare Release
    runs-on: ubuntu-latest
    outputs:
      pull-request-number: ${{ steps.pr.outputs.pull-request-number }}
      oxlint_version: ${{ steps.run.outputs.OXLINT_VERSION }}
      oxfmt_version: ${{ steps.run.outputs.OXFMT_VERSION }}
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 0
          persist-credentials: false

      - uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
        with:
          cache-key: warm
          tools: cargo-release-oxc

      - name: Generate version and changelog
        id: run
        run: |
          cargo release-oxc update --release oxlint --release oxfmt
          echo "OXLINT_VERSION=$(cat ./target/OXLINT_VERSION)" >> $GITHUB_OUTPUT
          echo "OXFMT_VERSION=$(cat ./target/OXFMT_VERSION)" >> $GITHUB_OUTPUT
          {
            echo "# Oxlint"
            cat ./target/OXLINT_CHANGELOG
            echo ""
            echo "# Oxfmt"
            cat ./target/OXFMT_CHANGELOG
          } > ./target/PR_BODY.md

      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0

      - name: Rebuild NAPI bindings
        run: |
          pnpm --filter oxlint-app run build-dev
          pnpm --filter oxfmt-app run build-dev

      - name: Update Cargo.lock
        run: cargo check

      - uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
        id: pr
        with:
          # bot account with PAT required for triggering workflow runs
          # See https://github.com/peter-evans/create-pull-request/blob/main/docs/concepts-guidelines.md#triggering-further-workflow-runs
          token: ${{ secrets.OXC_BOT_PAT }}
          commit-message: "release(apps): oxlint v${{ steps.run.outputs.OXLINT_VERSION }} && oxfmt v${{ steps.run.outputs.OXFMT_VERSION }}"
          title: "release(apps): oxlint v${{ steps.run.outputs.OXLINT_VERSION }} && oxfmt v${{ steps.run.outputs.OXFMT_VERSION }}"
          branch: release/apps
          branch-suffix: timestamp
          base: main
          body-path: ./target/PR_BODY.md
          assignees: Boshen

  ecosystem-ci:
    needs: prepare
    name: Trigger Ecosystem CI
    runs-on: ubuntu-slim
    permissions:
      pull-requests: write
      contents: write
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
        id: comment-oxlint
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          issue-number: ${{ needs.prepare.outputs.pull-request-number }}
          body: |
            Triggering Oxlint Ecosystem CI
            https://github.com/oxc-project/oxc-ecosystem-ci/actions/workflows/oxlint-ci.yml

      - uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
        id: comment-oxfmt
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          issue-number: ${{ needs.prepare.outputs.pull-request-number }}
          body: |
            Triggering Oxfmt Ecosystem CI
            https://github.com/oxc-project/oxc-ecosystem-ci/actions/workflows/oxfmt-ci.yml

      - uses: benc-uk/workflow-dispatch@7a027648b88c2413826b6ddd6c76114894dc5ec4 # v1.3.1
        with:
          repo: oxc-project/oxc-ecosystem-ci
          workflow: oxlint-ci.yml
          token: ${{ secrets.OXC_BOT_PAT }}
          ref: main
          inputs: '{ "issue-number": "${{ needs.prepare.outputs.pull-request-number }}", "comment-id": "${{ steps.comment-oxlint.outputs.comment-id }}" }'

      - uses: benc-uk/workflow-dispatch@7a027648b88c2413826b6ddd6c76114894dc5ec4 # v1.3.1
        with:
          repo: oxc-project/oxc-ecosystem-ci
          workflow: oxfmt-ci.yml
          token: ${{ secrets.OXC_BOT_PAT }}
          ref: main
          inputs: '{ "issue-number": "${{ needs.prepare.outputs.pull-request-number }}", "comment-id": "${{ steps.comment-oxfmt.outputs.comment-id }}" }'

  website:
    needs: prepare
    name: Update oxc.rs
    runs-on: ubuntu-slim
    permissions:
      actions: write
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: benc-uk/workflow-dispatch@7a027648b88c2413826b6ddd6c76114894dc5ec4 # v1.3.1
        with:
          repo: oxc-project/website
          workflow: release.yml
          token: ${{ secrets.OXC_BOT_PAT }}
          ref: main
          inputs: '{ "issue-number": "${{ needs.prepare.outputs.pull-request-number }}", "version": "${{ needs.prepare.outputs.oxlint_version }}" }'
prepare_release_crates perms .github/workflows/prepare_release_crates.yml
Triggers
workflow_dispatch, schedule
Runs on
ubuntu-latest, ubuntu-latest, ubuntu-slim
Jobs
check, prepare, ecosystem-ci
Actions
taiki-e/checkout-action, oxc-project/setup-rust, oxc-project/setup-rust, oxc-project/setup-node, peter-evans/create-pull-request, taiki-e/checkout-action, peter-evans/create-or-update-comment, benc-uk/workflow-dispatch
Commands
  • cargo ck
  • cargo release-oxc publish --release crates --dry-run
  • cargo ck cargo release-oxc update --release crates echo "CRATES_VERSION=$(cat ./target/CRATES_VERSION)" >> $GITHUB_OUTPUT
  • pnpm --filter oxc-minify run build-dev pnpm --filter oxc-parser run build-dev pnpm --filter oxc-transform run build-dev
  • cargo check
View raw YAML
name: Prepare Release Crates

permissions: {}

on:
  workflow_dispatch:
  schedule:
    # Triggers every Monday at 5pm Shanghai time (9am UTC)
    - cron: "0 9 * * 1"

concurrency:
  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
  cancel-in-progress: true

jobs:
  check:
    if: github.repository == 'oxc-project/oxc'
    name: Check
    runs-on: ubuntu-latest
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
        with:
          cache-key: warm
          tools: cargo-release-oxc
      - run: cargo ck
      - run: cargo release-oxc publish --release crates --dry-run # zizmor: ignore[use-trusted-publishing]

  prepare:
    if: github.repository == 'oxc-project/oxc'
    name: Prepare Release
    runs-on: ubuntu-latest
    outputs:
      pull-request-number: ${{ steps.pr.outputs.pull-request-number }}
      version: ${{ steps.run.outputs.CRATES_VERSION }}
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 0
          persist-credentials: false

      - uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
        with:
          cache-key: warm
          tools: cargo-release-oxc

      - name: Run
        id: run
        run: |
          cargo ck
          cargo release-oxc update --release crates
          echo "CRATES_VERSION=$(cat ./target/CRATES_VERSION)" >> $GITHUB_OUTPUT

      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0

      # Run NAPI-RS build, because NAPI-RS uses version from `package.json` in the bindings file,
      # which is committed to the repo. The version has just been bumped in previous step.
      # We don't use the compiled `.node` binary, so only do a development build, as it's faster.
      - name: Rebuild NAPI packages bindings
        run: |
          pnpm --filter oxc-minify run build-dev
          pnpm --filter oxc-parser run build-dev
          pnpm --filter oxc-transform run build-dev

      - name: Update Cargo.lock
        run: cargo check

      - uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
        id: pr
        with:
          # bot account with PAT required for triggering workflow runs
          # See https://github.com/peter-evans/create-pull-request/blob/main/docs/concepts-guidelines.md#triggering-further-workflow-runs
          token: ${{ secrets.OXC_BOT_PAT }}
          commit-message: "release(crates): oxc v${{ steps.run.outputs.CRATES_VERSION }}"
          title: "release(crates): oxc v${{ steps.run.outputs.CRATES_VERSION }}"
          branch: release/crates
          branch-suffix: timestamp
          base: main
          body-path: ./target/CRATES_CHANGELOG
          assignees: Boshen

  ecosystem-ci:
    needs: prepare
    name: Trigger Monitor Oxc
    runs-on: ubuntu-slim
    permissions:
      issues: write
      pull-requests: write
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
        id: comment
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          issue-number: ${{ needs.prepare.outputs.pull-request-number }}
          body: Triggering Monitor Oxc https://github.com/oxc-project/monitor-oxc/actions/workflows/ci.yml

      - uses: benc-uk/workflow-dispatch@7a027648b88c2413826b6ddd6c76114894dc5ec4 # v1.3.1
        with:
          repo: oxc-project/monitor-oxc
          workflow: ci.yml
          token: ${{ secrets.OXC_BOT_PAT }}
          ref: main
          inputs: '{ "issue-number": "${{ needs.prepare.outputs.pull-request-number }}", "comment-id": "${{ steps.comment.outputs.comment-id }}" }'
pullfrog perms .github/workflows/pullfrog.yml
Triggers
workflow_dispatch
Runs on
ubuntu-latest
Jobs
pullfrog
Actions
pullfrog/pullfrog
View raw YAML
# PULLFROG ACTION — DO NOT EDIT EXCEPT WHERE INDICATED
name: Pullfrog
run-name: ${{ inputs.name || github.workflow }}
on:
  workflow_dispatch:
    inputs:
      prompt:
        type: string
        description: Agent prompt
      name:
        type: string
        description: Run name

permissions:
  id-token: write
  contents: write
  pull-requests: write
  issues: write
  actions: read
  checks: read

jobs:
  pullfrog:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          fetch-depth: 1
      - name: Run agent
        uses: pullfrog/pullfrog@30d68e53a7e1d9eb2e7a98a1f35f9baef9b40313 # v0.0.181
        with:
          prompt: ${{ inputs.prompt }}
        env:
          # add any additional keys your agent(s) need
          # optionally, comment out any you won't use
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
          GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
          GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
          CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
          MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
          GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
          DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
          OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
release_apps matrix perms .github/workflows/release_apps.yml
Triggers
workflow_dispatch, push
Runs on
ubuntu-slim, ${{ matrix.os }}, ubuntu-latest, ubuntu-slim, ${{ matrix.os }}, ubuntu-latest, ubuntu-slim, ubuntu-latest, ${{ matrix.os }}, ubuntu-slim
Jobs
check, build-oxlint, build-oxlint-freebsd, publish-oxlint, build-oxfmt, build-oxfmt-freebsd, publish-oxfmt, github-release, smoke, bump
Matrix
include, include.build, include.container, include.os, include.target→ aarch64-apple-darwin, aarch64-linux-android, aarch64-pc-windows-msvc, aarch64-unknown-linux-gnu, aarch64-unknown-linux-musl, aarch64-unknown-linux-ohos, armv7-linux-androideabi, armv7-unknown-linux-gnueabihf, armv7-unknown-linux-musleabihf, export CFLAGS="-fuse-ld=lld" && pnpm run build-napi-release --target s390x-unknown-linux-gnu --use-napi-cross, i686-pc-windows-msvc, macos-latest, node:24-alpine, pnpm run build-napi-release --target aarch64-apple-darwin, pnpm run build-napi-release --target aarch64-linux-android, pnpm run build-napi-release --target aarch64-pc-windows-msvc, pnpm run build-napi-release --target aarch64-unknown-linux-gnu --use-napi-cross, pnpm run build-napi-release --target aarch64-unknown-linux-musl -x, pnpm run build-napi-release --target aarch64-unknown-linux-ohos, pnpm run build-napi-release --target armv7-linux-androideabi, pnpm run build-napi-release --target armv7-unknown-linux-gnueabihf --use-napi-cross, pnpm run build-napi-release --target armv7-unknown-linux-musleabihf -x, pnpm run build-napi-release --target i686-pc-windows-msvc, pnpm run build-napi-release --target powerpc64le-unknown-linux-gnu --use-napi-cross, pnpm run build-napi-release --target riscv64gc-unknown-linux-musl -x, pnpm run build-napi-release --target x86_64-apple-darwin, pnpm run build-napi-release --target x86_64-pc-windows-msvc, pnpm run build-napi-release --target x86_64-unknown-linux-gnu --use-napi-cross, pnpm run build-napi-release --target x86_64-unknown-linux-musl -x, powerpc64le-unknown-linux-gnu, riscv64gc-unknown-linux-gnu, riscv64gc-unknown-linux-musl, s390x-unknown-linux-gnu, sudo apt-get update sudo apt-get install gcc-riscv64-linux-gnu g++-riscv64-linux-gnu -y export TARGET_CC=riscv64-linux-gnu-gcc export CXX=riscv64-linux-gnu-g++ pnpm run build-napi-release --target riscv64gc-unknown-linux-gnu , ubuntu-latest, windows-latest, x86_64-apple-darwin, x86_64-pc-windows-msvc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl
Actions
taiki-e/checkout-action, taiki-e/checkout-action, taiki-e/install-action, oxc-project/setup-node, goto-bus-stop/setup-zig, Boshen/setup-ohos-sdk, taiki-e/checkout-action, cross-platform-actions/action, taiki-e/checkout-action, oxc-project/setup-node, taiki-e/checkout-action, taiki-e/install-action, oxc-project/setup-node, goto-bus-stop/setup-zig, Boshen/setup-ohos-sdk, taiki-e/checkout-action, cross-platform-actions/action, taiki-e/checkout-action, oxc-project/setup-node, oxc-project/setup-rust, tsickert/discord-webhook, taiki-e/checkout-action, benc-uk/workflow-dispatch, benc-uk/workflow-dispatch, benc-uk/workflow-dispatch, benc-uk/workflow-dispatch
Commands
  • git config --system core.longpaths true
  • rustup target add ${{ matrix.target }}
  • ${{ matrix.build }}
  • cross build --release -p oxlint --features allocator --target=${{ matrix.target }}
  • pip3 install cargo-zigbuild cargo zigbuild --release -p oxlint --features allocator --target=${{ matrix.target }}
  • pnpm run build-js
  • mkdir -p ${npm_dir}
  • pnpm napi create-npm-dirs --package-json-path ${package_path}/package.json --npm-dir ${npm_dir}
View raw YAML
name: Release Apps

permissions: {}

on:
  workflow_dispatch:
  push:
    branches:
      - main
    paths:
      - npm/oxfmt/package.json
      - npm/oxlint/package.json

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  check:
    if: github.repository == 'oxc-project/oxc'
    name: Check version
    runs-on: ubuntu-slim
    outputs:
      version_changed: ${{ steps.oxfmt.outputs.version_changed && steps.oxlint.outputs.version_changed }}
      oxfmt_version: ${{ steps.oxfmt.outputs.version }}
      oxlint_version: ${{ steps.oxlint.outputs.version }}
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: ./.github/actions/check-version
        id: oxfmt
        with:
          file-name: npm/oxfmt/package.json
          file-url: https://unpkg.com/oxfmt@latest/package.json

      - uses: ./.github/actions/check-version
        id: oxlint
        with:
          file-name: npm/oxlint/package.json
          file-url: https://unpkg.com/oxlint@latest/package.json

  build-oxlint:
    needs: check
    if: needs.check.outputs.version_changed == 'true'
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            build: pnpm run build-napi-release --target x86_64-pc-windows-msvc

          - os: windows-latest
            target: aarch64-pc-windows-msvc
            build: pnpm run build-napi-release --target aarch64-pc-windows-msvc

          - os: windows-latest
            target: i686-pc-windows-msvc
            build: pnpm run build-napi-release --target i686-pc-windows-msvc

          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            build: pnpm run build-napi-release --target x86_64-unknown-linux-gnu --use-napi-cross

          - os: ubuntu-latest
            target: aarch64-unknown-linux-gnu
            build: pnpm run build-napi-release --target aarch64-unknown-linux-gnu --use-napi-cross

          - os: ubuntu-latest
            target: armv7-unknown-linux-gnueabihf
            build: pnpm run build-napi-release --target armv7-unknown-linux-gnueabihf --use-napi-cross

          - os: ubuntu-latest
            target: x86_64-unknown-linux-musl
            build: pnpm run build-napi-release --target x86_64-unknown-linux-musl -x

          - os: ubuntu-latest
            target: aarch64-unknown-linux-musl
            build: pnpm run build-napi-release --target aarch64-unknown-linux-musl -x

          - os: ubuntu-latest
            target: armv7-unknown-linux-musleabihf
            build: pnpm run build-napi-release --target armv7-unknown-linux-musleabihf -x

          - os: macos-latest
            target: x86_64-apple-darwin
            build: pnpm run build-napi-release --target x86_64-apple-darwin

          - os: macos-latest
            target: aarch64-apple-darwin
            build: pnpm run build-napi-release --target aarch64-apple-darwin

          - os: ubuntu-latest
            target: aarch64-linux-android
            build: pnpm run build-napi-release --target aarch64-linux-android

          - os: ubuntu-latest
            target: armv7-linux-androideabi
            build: pnpm run build-napi-release --target armv7-linux-androideabi

          - os: ubuntu-latest
            target: aarch64-unknown-linux-ohos
            build: pnpm run build-napi-release --target aarch64-unknown-linux-ohos

          - os: ubuntu-latest
            target: powerpc64le-unknown-linux-gnu
            build: pnpm run build-napi-release --target powerpc64le-unknown-linux-gnu --use-napi-cross

          - os: ubuntu-latest
            target: riscv64gc-unknown-linux-gnu
            build: |
              sudo apt-get update
              sudo apt-get install gcc-riscv64-linux-gnu g++-riscv64-linux-gnu -y
              export TARGET_CC=riscv64-linux-gnu-gcc
              export CXX=riscv64-linux-gnu-g++
              pnpm run build-napi-release --target riscv64gc-unknown-linux-gnu

          - os: ubuntu-latest
            target: riscv64gc-unknown-linux-musl
            build: pnpm run build-napi-release --target riscv64gc-unknown-linux-musl -x

          - os: ubuntu-latest
            target: s390x-unknown-linux-gnu
            build: export CFLAGS="-fuse-ld=lld" && pnpm run build-napi-release --target s390x-unknown-linux-gnu --use-napi-cross

    name: Build Oxlint ${{ matrix.target }}
    runs-on: ${{ matrix.os }}
    env:
      TARGET_CC: clang # for mimalloc
    defaults:
      run:
        shell: bash
    steps:
      - if: ${{ contains(matrix.os, 'windows') }}
        run: git config --system core.longpaths true

      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - name: Install cross
        uses: taiki-e/install-action@06203676c62f0d3c765be3f2fcfbebbcb02d09f5 # v2.69.6
        with:
          tool: cross # cross installs the latest rust toolchain

      # No Rust cache is provided, to avoid cache poisoning attack.

      - name: Add Rust Target
        run: rustup target add ${{ matrix.target }}

      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0

      # For cargo-zigbuild in musl builds.
      - uses: goto-bus-stop/setup-zig@abea47f85e598557f500fa1fd2ab7464fcb39406 # v2.2.1
        if: ${{ contains(matrix.target, 'musl') }}
        with:
          version: 0.13.0

      - name: Setup OpenHarmony SDK
        if: ${{ contains(matrix.target, 'ohos') }}
        uses: Boshen/setup-ohos-sdk@edb865a89a712f1f15dbad932dfa9cfce849d95c # v1.0.0

      - name: Build oxlint for node.js
        working-directory: apps/oxlint
        run: ${{ matrix.build }}

      - name: Build Rust binary
        if: ${{ !contains(matrix.target, 'wasm') && !contains(matrix.target, 'android') && !contains(matrix.target, 'ohos') && !contains(matrix.target, 'riscv64gc-unknown-linux-musl') }}
        run: cross build --release -p oxlint --features allocator --target=${{ matrix.target }}

      - name: Build Rust binary (zigbuild)
        if: ${{ contains(matrix.target, 'riscv64gc-unknown-linux-musl') }}
        run: |
          pip3 install cargo-zigbuild
          cargo zigbuild --release -p oxlint --features allocator --target=${{ matrix.target }}

      - name: Upload NAPI artifact
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          if-no-files-found: error
          name: oxlint-bindings-${{ matrix.target }}
          path: |
            apps/oxlint/src-js/*.node
            apps/oxlint/src-js/*.wasm

      # The binaries are zipped to fix permission loss https://github.com/actions/upload-artifact#permission-loss
      - name: Archive Rust binary
        if: ${{ !contains(matrix.target, 'wasm') && !contains(matrix.target, 'android') && !contains(matrix.target, 'ohos') }}
        uses: ./.github/actions/archive-binary
        with:
          source_path: target/${{ matrix.target }}/release/oxlint${{ runner.os == 'Windows' && '.exe' || '' }}
          binary_name: oxlint-${{ matrix.target }}${{ runner.os == 'Windows' && '.exe' || '' }}
          archive_name: rust-oxlint-${{ matrix.target }}

      # For github release
      - name: Upload Rust binary
        if: ${{ !contains(matrix.target, 'wasm') && !contains(matrix.target, 'android') && !contains(matrix.target, 'ohos') }}
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          if-no-files-found: error
          name: rust-oxlint-${{ matrix.target }}
          path: |
            rust-oxlint-**.zip
            rust-oxlint-**.tar.gz

  build-oxlint-freebsd:
    needs: check
    if: needs.check.outputs.version_changed == 'true'
    name: Build Oxlint FreeBSD
    runs-on: ubuntu-latest
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - name: Build
        id: build
        uses: cross-platform-actions/action@492b0c80085400348c599edace11141a4ee73524 # v0.32.0
        env:
          DEBUG: napi:*
          RUSTUP_IO_THREADS: 1
        with:
          operating_system: freebsd
          version: "14.2"
          memory: 8G
          cpu_count: 3
          environment_variables: "DEBUG RUSTUP_IO_THREADS"
          shell: bash
          run: |
            sudo pkg install -y -f curl libnghttp2 node22 npm cmake ca_root_nss
            curl https://sh.rustup.rs -sSf --output rustup.sh
            sh rustup.sh -y --profile minimal --default-toolchain stable
            source "$HOME/.cargo/env"
            echo "~~~~ rustc --version ~~~~"
            rustc --version
            echo "~~~~ node -v ~~~~"
            node -v
            pwd
            ls -lah
            whoami
            env
            export COREPACK_INTEGRITY_KEYS=0
            sudo corepack enable
            pnpm install --ignore-scripts # postinstall: The current platform (freebsd) and architecture (x64) is not supported.
            cd apps/oxlint
            pnpm run build-napi-release --target x86_64-unknown-freebsd
            cd ../..
            cargo build --release -p oxlint --features allocator --target=x86_64-unknown-freebsd
            rm -rf node_modules
            rm -rf target/x86_64-unknown-freebsd/release/build
            rm -rf target/x86_64-unknown-freebsd/release/deps
            rm -rf target/x86_64-unknown-freebsd/release/incremental

      - name: Upload NAPI artifact
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          if-no-files-found: error
          name: oxlint-bindings-x86_64-unknown-freebsd
          path: apps/oxlint/src-js/*.node

      - name: Archive Rust binary
        uses: ./.github/actions/archive-binary
        with:
          source_path: target/x86_64-unknown-freebsd/release/oxlint
          binary_name: oxlint-x86_64-unknown-freebsd
          archive_name: rust-oxlint-x86_64-unknown-freebsd

      - name: Upload Rust binary
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          if-no-files-found: error
          name: rust-oxlint-x86_64-unknown-freebsd
          path: |
            rust-oxlint-**.zip
            rust-oxlint-**.tar.gz

  publish-oxlint:
    name: Publish Oxlint
    needs: [check, build-oxlint, build-oxlint-freebsd]
    runs-on: ubuntu-slim
    permissions:
      id-token: write # for `pnpm publish --provenance`
    env:
      package_path: npm/oxlint
      plugins_package_path: npm/oxlint-plugins
      plugin_eslint_package_path: npm/oxlint-plugin-eslint
      npm_dir: npm/oxlint-release
      PUBLISH_FLAGS: "--provenance --access public --no-git-checks"
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
        with:
          path: artifacts
          pattern: oxlint-bindings-*

      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0

      - name: Generate oxlint JS build
        working-directory: apps/oxlint
        run: pnpm run build-js

      - run: mkdir -p ${npm_dir}

      - run: pnpm napi create-npm-dirs --package-json-path ${package_path}/package.json --npm-dir ${npm_dir}

      - run: pnpm napi artifacts --package-json-path ${package_path}/package.json --build-output-dir apps/oxlint/src-js --npm-dir ${npm_dir}

      - name: Copy dist files to npm package
        run: cp -r apps/oxlint/dist npm/oxlint/dist

      - name: Copy dist files to @oxlint/plugins npm package
        run: |
          cp apps/oxlint/dist-pkg-plugins/* ${plugins_package_path}/

      - name: Copy dist files to oxlint-plugin-eslint npm package
        run: |
          cp -r apps/oxlint/dist-pkg-plugin-eslint/. ${plugin_eslint_package_path}/

      - run: npm install -g npm@latest # For trusted publishing support

      - name: Check Publish
        run: |
          node .github/scripts/check-npm-packages.js "${npm_dir}/*" "${package_path}"
          node .github/scripts/check-npm-packages.js "${plugins_package_path}"
          node .github/scripts/check-npm-packages.js "${plugin_eslint_package_path}"

      - name: Trusted Publish
        run: |
          # Trusted publishing is configured, publish token is not required.
          # Publish sub-packages and adds `optionalDependencies` to main package.
          pnpm napi pre-publish --no-gh-release -t npm --package-json-path ${package_path}/package.json --npm-dir ${npm_dir}
          # Publish `oxlint` package
          bash .github/scripts/publish-if-needed.sh ${package_path} ${PUBLISH_FLAGS}
          # Publish `@oxlint/plugins` package
          bash .github/scripts/publish-if-needed.sh ${plugins_package_path} ${PUBLISH_FLAGS}
          # Publish `oxlint-plugin-eslint` package
          bash .github/scripts/publish-if-needed.sh ${plugin_eslint_package_path} ${PUBLISH_FLAGS}

  build-oxfmt:
    needs: check
    if: needs.check.outputs.version_changed == 'true'
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            build: pnpm run build-napi-release --target x86_64-pc-windows-msvc

          - os: windows-latest
            target: aarch64-pc-windows-msvc
            build: pnpm run build-napi-release --target aarch64-pc-windows-msvc

          - os: windows-latest
            target: i686-pc-windows-msvc
            build: pnpm run build-napi-release --target i686-pc-windows-msvc

          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            build: pnpm run build-napi-release --target x86_64-unknown-linux-gnu --use-napi-cross

          - os: ubuntu-latest
            target: aarch64-unknown-linux-gnu
            build: pnpm run build-napi-release --target aarch64-unknown-linux-gnu --use-napi-cross

          - os: ubuntu-latest
            target: armv7-unknown-linux-gnueabihf
            build: pnpm run build-napi-release --target armv7-unknown-linux-gnueabihf --use-napi-cross

          - os: ubuntu-latest
            target: x86_64-unknown-linux-musl
            build: pnpm run build-napi-release --target x86_64-unknown-linux-musl -x

          - os: ubuntu-latest
            target: aarch64-unknown-linux-musl
            build: pnpm run build-napi-release --target aarch64-unknown-linux-musl -x

          - os: ubuntu-latest
            target: armv7-unknown-linux-musleabihf
            build: pnpm run build-napi-release --target armv7-unknown-linux-musleabihf -x

          - os: macos-latest
            target: x86_64-apple-darwin
            build: pnpm run build-napi-release --target x86_64-apple-darwin

          - os: macos-latest
            target: aarch64-apple-darwin
            build: pnpm run build-napi-release --target aarch64-apple-darwin

          - os: ubuntu-latest
            target: aarch64-linux-android
            build: pnpm run build-napi-release --target aarch64-linux-android

          - os: ubuntu-latest
            target: armv7-linux-androideabi
            build: pnpm run build-napi-release --target armv7-linux-androideabi

          - os: ubuntu-latest
            target: aarch64-unknown-linux-ohos
            build: pnpm run build-napi-release --target aarch64-unknown-linux-ohos

          - os: ubuntu-latest
            target: powerpc64le-unknown-linux-gnu
            build: pnpm run build-napi-release --target powerpc64le-unknown-linux-gnu --use-napi-cross

          - os: ubuntu-latest
            target: riscv64gc-unknown-linux-gnu
            build: |
              sudo apt-get update
              sudo apt-get install gcc-riscv64-linux-gnu g++-riscv64-linux-gnu -y
              export TARGET_CC=riscv64-linux-gnu-gcc
              export CXX=riscv64-linux-gnu-g++
              pnpm run build-napi-release --target riscv64gc-unknown-linux-gnu

          - os: ubuntu-latest
            target: riscv64gc-unknown-linux-musl
            build: pnpm run build-napi-release --target riscv64gc-unknown-linux-musl -x

          - os: ubuntu-latest
            target: s390x-unknown-linux-gnu
            build: export CFLAGS="-fuse-ld=lld" && pnpm run build-napi-release --target s390x-unknown-linux-gnu --use-napi-cross

    name: Build Oxfmt ${{ matrix.target }}
    runs-on: ${{ matrix.os }}
    env:
      TARGET_CC: clang # for mimalloc
    defaults:
      run:
        shell: bash
    steps:
      - if: ${{ contains(matrix.os, 'windows') }}
        run: git config --system core.longpaths true

      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - name: Install cross
        uses: taiki-e/install-action@06203676c62f0d3c765be3f2fcfbebbcb02d09f5 # v2.69.6
        with:
          tool: cross # cross installs the latest rust toolchain

      # No Rust cache is provided, to avoid cache poisoning attack.

      - name: Add Rust Target
        run: rustup target add ${{ matrix.target }}

      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0

      # For cargo-zigbuild in musl builds.
      - uses: goto-bus-stop/setup-zig@abea47f85e598557f500fa1fd2ab7464fcb39406 # v2.2.1
        if: ${{ contains(matrix.target, 'musl') }}
        with:
          version: 0.13.0

      - name: Setup OpenHarmony SDK
        if: ${{ contains(matrix.target, 'ohos') }}
        uses: Boshen/setup-ohos-sdk@edb865a89a712f1f15dbad932dfa9cfce849d95c # v1.0.0

      - name: Build oxfmt for node.js
        working-directory: apps/oxfmt
        run: ${{ matrix.build }}

      - name: Build Rust binary
        if: ${{ !contains(matrix.target, 'wasm') && !contains(matrix.target, 'android') && !contains(matrix.target, 'ohos') && !contains(matrix.target, 'riscv64gc-unknown-linux-musl') }}
        run: cross build --release -p oxfmt --no-default-features --features allocator --target=${{ matrix.target }}

      - name: Build Rust binary (zigbuild)
        if: ${{ contains(matrix.target, 'riscv64gc-unknown-linux-musl') }}
        run: |
          pip3 install cargo-zigbuild
          cargo zigbuild --release -p oxfmt --no-default-features --features allocator --target=${{ matrix.target }}

      - name: Upload NAPI artifact
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          if-no-files-found: error
          name: oxfmt-bindings-${{ matrix.target }}
          path: |
            apps/oxfmt/src-js/*.node
            apps/oxfmt/src-js/*.wasm

      # The binaries are zipped to fix permission loss https://github.com/actions/upload-artifact#permission-loss
      - name: Archive Rust binary
        if: ${{ !contains(matrix.target, 'wasm') && !contains(matrix.target, 'android') && !contains(matrix.target, 'ohos') }}
        uses: ./.github/actions/archive-binary
        with:
          source_path: target/${{ matrix.target }}/release/oxfmt${{ runner.os == 'Windows' && '.exe' || '' }}
          binary_name: oxfmt-${{ matrix.target }}${{ runner.os == 'Windows' && '.exe' || '' }}
          archive_name: rust-oxfmt-${{ matrix.target }}

      # For github release
      - name: Upload Rust binary
        if: ${{ !contains(matrix.target, 'wasm') && !contains(matrix.target, 'android') && !contains(matrix.target, 'ohos') }}
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          if-no-files-found: error
          name: rust-oxfmt-${{ matrix.target }}
          path: |
            rust-oxfmt-**.zip
            rust-oxfmt-**.tar.gz

  build-oxfmt-freebsd:
    needs: check
    if: needs.check.outputs.version_changed == 'true'
    name: Build Oxfmt FreeBSD
    runs-on: ubuntu-latest
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - name: Build
        id: build
        uses: cross-platform-actions/action@492b0c80085400348c599edace11141a4ee73524 # v0.32.0
        env:
          DEBUG: napi:*
          RUSTUP_IO_THREADS: 1
        with:
          operating_system: freebsd
          version: "14.2"
          memory: 8G
          cpu_count: 3
          environment_variables: "DEBUG RUSTUP_IO_THREADS"
          shell: bash
          run: |
            sudo pkg install -y -f curl libnghttp2 node22 npm cmake ca_root_nss
            curl https://sh.rustup.rs -sSf --output rustup.sh
            sh rustup.sh -y --profile minimal --default-toolchain stable
            source "$HOME/.cargo/env"
            echo "~~~~ rustc --version ~~~~"
            rustc --version
            echo "~~~~ node -v ~~~~"
            node -v
            pwd
            ls -lah
            whoami
            env
            export COREPACK_INTEGRITY_KEYS=0
            sudo corepack enable
            pnpm install --ignore-scripts # postinstall: The current platform (freebsd) and architecture (x64) is not supported.
            cd apps/oxfmt
            pnpm run build-napi-release --target x86_64-unknown-freebsd
            cd ../..
            cargo build --release -p oxfmt --no-default-features --features allocator --target=x86_64-unknown-freebsd
            rm -rf node_modules
            rm -rf target/x86_64-unknown-freebsd/release/build
            rm -rf target/x86_64-unknown-freebsd/release/deps
            rm -rf target/x86_64-unknown-freebsd/release/incremental

      - name: Upload NAPI artifact
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          if-no-files-found: error
          name: oxfmt-bindings-x86_64-unknown-freebsd
          path: apps/oxfmt/src-js/*.node

      - name: Archive Rust binary
        uses: ./.github/actions/archive-binary
        with:
          source_path: target/x86_64-unknown-freebsd/release/oxfmt
          binary_name: oxfmt-x86_64-unknown-freebsd
          archive_name: rust-oxfmt-x86_64-unknown-freebsd

      - name: Upload Rust binary
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          if-no-files-found: error
          name: rust-oxfmt-x86_64-unknown-freebsd
          path: |
            rust-oxfmt-**.zip
            rust-oxfmt-**.tar.gz

  publish-oxfmt:
    name: Publish Oxfmt
    needs: [check, build-oxfmt, build-oxfmt-freebsd]
    runs-on: ubuntu-slim
    permissions:
      id-token: write # for `pnpm publish --provenance`
    env:
      package_path: npm/oxfmt
      npm_dir: npm/oxfmt-release
      PUBLISH_FLAGS: "--provenance --access public --no-git-checks"
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
        with:
          path: artifacts
          pattern: oxfmt-bindings-*

      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0

      - name: Generate oxfmt JS build
        working-directory: apps/oxfmt
        run: pnpm run build-js

      - run: mkdir -p ${npm_dir}

      - run: pnpm napi create-npm-dirs --package-json-path ${package_path}/package.json --npm-dir ${npm_dir}

      - run: pnpm napi artifacts --package-json-path ${package_path}/package.json --build-output-dir apps/oxfmt/src-js --npm-dir ${npm_dir}

      - name: Copy dist files to npm package
        run: cp -r apps/oxfmt/dist npm/oxfmt/dist

      - run: npm install -g npm@latest # For trusted publishing support

      - name: Check Publish
        run: node .github/scripts/check-npm-packages.js "${npm_dir}/*" "${package_path}"

      - name: Trusted Publish
        run: |
          # Trusted publishing is configured, publish token is not required.
          # Publish sub-packages and adds `optionalDependencies` to main package.
          pnpm napi pre-publish --no-gh-release -t npm --package-json-path ${package_path}/package.json --npm-dir ${npm_dir}
          bash .github/scripts/publish-if-needed.sh ${package_path} ${PUBLISH_FLAGS}

  github-release:
    name: GitHub Release
    needs:
      [
        check,
        build-oxlint,
        build-oxlint-freebsd,
        build-oxfmt,
        build-oxfmt-freebsd,
        publish-oxlint,
        publish-oxfmt,
      ]
    permissions:
      contents: write # for `gh release create`
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          token: ${{ secrets.OXC_BOT_PAT }}
          fetch-depth: 0 # for changelog
          persist-credentials: true

      - uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
        with:
          restore-cache: false
          tools: cargo-release-oxc

      - name: Generate changelog
        id: run
        run: |
          mkdir -p target
          cargo release-oxc changelog --release oxfmt --release oxlint
          {
            echo "## Table of Contents"
            echo ""
            echo "- [Oxlint v${NEEDS_CHECK_OUTPUTS_OXLINT_VERSION}](#oxlint-v${NEEDS_CHECK_OUTPUTS_OXLINT_VERSION})"
            echo "- [Oxfmt v${NEEDS_CHECK_OUTPUTS_OXFMT_VERSION}](#oxfmt-v${NEEDS_CHECK_OUTPUTS_OXFMT_VERSION})"
            echo ""
            echo "## Oxlint v${NEEDS_CHECK_OUTPUTS_OXLINT_VERSION}"
            cat ./target/OXLINT_CHANGELOG
            echo ""
            echo ""
            echo "## Oxfmt v${NEEDS_CHECK_OUTPUTS_OXFMT_VERSION}"
            cat ./target/OXFMT_CHANGELOG
          } > ./target/RELEASE_BODY.md
        env:
          NEEDS_CHECK_OUTPUTS_OXLINT_VERSION: ${{ needs.check.outputs.oxlint_version }}
          NEEDS_CHECK_OUTPUTS_OXFMT_VERSION: ${{ needs.check.outputs.oxfmt_version }}

      - name: tag oxlint and oxfmt
        env:
          NEEDS_CHECK_OUTPUTS_OXFMT_VERSION: ${{ needs.check.outputs.oxfmt_version }}
          NEEDS_CHECK_OUTPUTS_OXLINT_VERSION: ${{ needs.check.outputs.oxlint_version }}
        run: |
          git tag oxfmt_v${NEEDS_CHECK_OUTPUTS_OXFMT_VERSION} ${{ github.sha }}
          git tag oxlint_v${NEEDS_CHECK_OUTPUTS_OXLINT_VERSION} ${{ github.sha }}
          git push origin oxlint_v${NEEDS_CHECK_OUTPUTS_OXLINT_VERSION} oxfmt_v${NEEDS_CHECK_OUTPUTS_OXFMT_VERSION}

      - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
        with:
          path: ./release-artifacts
          pattern: rust-*
          merge-multiple: true

      - name: Remove rust- prefix from filenames
        run: |
          cd release-artifacts
          for file in rust-*; do
            mv "$file" "${file#rust-}"
          done
          ls

      - name: Create GitHub Release
        id: release
        env:
          GH_TOKEN: ${{ github.token }}
          GIT_TAG: apps_v${{ needs.check.outputs.oxlint_version }}
          GIT_TARGET: ${{ github.sha }}
          TITLE: "oxlint v${{ needs.check.outputs.oxlint_version }} & oxfmt v${{ needs.check.outputs.oxfmt_version }}"
        run: gh release create ${GIT_TAG} ./release-artifacts/* --title "${TITLE}" --notes-file ./target/RELEASE_BODY.md --target ${GIT_TARGET}

      - uses: tsickert/discord-webhook@b217a69502f52803de774ded2b1ab7c282e99645 # v7.0.0
        with:
          webhook-url: ${{ secrets.DISCORD_OXC_RELEASES_CHANNEL }}
          embed-title: oxlint v${{ needs.check.outputs.oxlint_version }} & oxfmt v${{ needs.check.outputs.oxfmt_version }}
          embed-description: A new release is available! Check the changelog for details.
          embed-url: https://github.com/${{ github.repository }}/releases/tag/apps_v${{ needs.check.outputs.oxlint_version }}

      - name: wait 3 minutes for smoke test
        run: sleep 180s

  smoke:
    needs: [check, github-release]
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: windows-latest
          - os: ubuntu-latest
          - os: ubuntu-latest
            container: node:24-alpine # musl
          - os: macos-latest
    name: Smoke Test ${{ matrix.os }} ${{ matrix.container }}
    runs-on: ${{ matrix.os }}
    container: ${{ matrix.container }}
    steps:
      - name: Test
        # These commands should be run on these defaults:
        # - windows: pwsh
        # - ubuntu: bash
        # - alpine: sh
        # - macos: bash
        run: | # zizmor: ignore[template-injection]
          echo "" > test.js
          ldd --version || true
          npx oxfmt@${{ needs.check.outputs.oxfmt_version }} ./test.js
          npx oxlint@${{ needs.check.outputs.oxlint_version }} ./test.js

  bump:
    needs: [check, smoke]
    name: Bump oxlint dependents
    runs-on: ubuntu-slim
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - name: Bump oxc-project/eslint-plugin-oxlint
        uses: benc-uk/workflow-dispatch@7a027648b88c2413826b6ddd6c76114894dc5ec4 # v1.3.1
        with:
          repo: oxc-project/eslint-plugin-oxlint
          workflow: bump_oxlint.yml
          token: ${{ secrets.OXC_BOT_PAT }}
          ref: main
          inputs: '{ "version": "${{ needs.check.outputs.oxlint_version }}" }'

      - name: Bump oxc-project/oxlint-migrate
        uses: benc-uk/workflow-dispatch@7a027648b88c2413826b6ddd6c76114894dc5ec4 # v1.3.1
        with:
          repo: oxc-project/oxlint-migrate
          workflow: bump_oxlint.yml
          token: ${{ secrets.OXC_BOT_PAT }}
          ref: main
          inputs: '{ "version": "${{ needs.check.outputs.oxlint_version }}" }'

      - name: Bump oxc-project/mirrors-oxlint
        uses: benc-uk/workflow-dispatch@7a027648b88c2413826b6ddd6c76114894dc5ec4 # v1.3.1
        with:
          repo: oxc-project/mirrors-oxlint
          workflow: main.yml
          token: ${{ secrets.OXC_BOT_PAT }}
          ref: main

      - name: Bump oxc-project/mirrors-oxfmt
        uses: benc-uk/workflow-dispatch@7a027648b88c2413826b6ddd6c76114894dc5ec4 # v1.3.1
        with:
          repo: oxc-project/mirrors-oxfmt
          workflow: main.yml
          token: ${{ secrets.OXC_BOT_PAT }}
          ref: main
release_crates perms .github/workflows/release_crates.yml
Triggers
workflow_dispatch, push
Runs on
ubuntu-latest
Jobs
release
Actions
oxc-project/setup-rust, rust-lang/crates-io-auth-action
Commands
  • cargo ck
  • mkdir -p target cargo release-oxc changelog --release crates
  • cargo release-oxc publish --release crates echo "TAG=$(cat ./target/CRATES_VERSION)" >> $GITHUB_OUTPUT
  • gh release create ${GIT_TAG} --latest=false --title "${TITLE}" --notes-file ./target/CRATES_CHANGELOG --target ${GIT_TARGET}
View raw YAML
name: Release Crates

permissions: {}

on:
  workflow_dispatch:
  push:
    branches:
      - main
    paths:
      - crates/oxc/Cargo.toml

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  release:
    if: github.repository == 'oxc-project/oxc'
    name: Release crates
    runs-on: ubuntu-latest
    permissions:
      contents: write # For git tag push
      id-token: write # Required for OIDC token exchange
    steps:
      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          token: ${{ secrets.OXC_BOT_PAT }}
          fetch-depth: 0 # for changelog
          persist-credentials: true

      - uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
        with:
          cache-key: warm
          tools: cargo-release-oxc

      - run: cargo ck

      - name: Generate changelog
        run: |
          mkdir -p target
          cargo release-oxc changelog --release crates

      - uses: rust-lang/crates-io-auth-action@b7e9a28eded4986ec6b1fa40eeee8f8f165559ec # v1.0.3
        id: auth

      - name: Run
        id: run
        env:
          CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
        run: |
          cargo release-oxc publish --release crates
          echo "TAG=$(cat ./target/CRATES_VERSION)" >> $GITHUB_OUTPUT

      - name: Create GitHub Release
        env:
          GH_TOKEN: ${{ github.token }}
          GIT_TAG: ${{ steps.run.outputs.TAG }}
          GIT_TARGET: ${{ github.sha }}
          TITLE: "oxc ${{ steps.run.outputs.TAG }}"
        run: gh release create ${GIT_TAG} --latest=false --title "${TITLE}" --notes-file ./target/CRATES_CHANGELOG --target ${GIT_TARGET}
release_napi_minify perms .github/workflows/release_napi_minify.yml
Triggers
push
Runs on
Jobs
release
View raw YAML
name: Release NAPI Minify

permissions: {}

on:
  push:
    branches:
      - main
    paths:
      - napi/minify/package.json
      - .github/workflows/release_napi_minify.yml
      - .github/workflows/reusable_release_napi.yml

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  release:
    if: github.repository == 'oxc-project/oxc'
    name: Release NAPI Minify
    uses: ./.github/workflows/reusable_release_napi.yml
    with:
      name: minify
    permissions:
      id-token: write # for `pnpm publish --provenance`
release_napi_parser perms .github/workflows/release_napi_parser.yml
Triggers
push
Runs on
Jobs
release
View raw YAML
name: Release NAPI Parser

permissions: {}

on:
  push:
    branches:
      - main
    paths:
      - napi/parser/package.json
      - .github/workflows/release_napi_parser.yml
      - .github/workflows/reusable_release_napi.yml

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  release:
    if: github.repository == 'oxc-project/oxc'
    name: Release NAPI Parser
    uses: ./.github/workflows/reusable_release_napi.yml
    with:
      name: parser
    permissions:
      id-token: write # for `pnpm publish --provenance`
release_napi_transform perms .github/workflows/release_napi_transform.yml
Triggers
push
Runs on
Jobs
release
View raw YAML
name: Release NAPI Transform

permissions: {}

on:
  push:
    branches:
      - main
    paths:
      - napi/transform/package.json
      - .github/workflows/release_napi_transform.yml
      - .github/workflows/reusable_release_napi.yml

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  release:
    if: github.repository == 'oxc-project/oxc'
    name: Release NAPI Transform
    uses: ./.github/workflows/reusable_release_napi.yml
    with:
      name: transform
    permissions:
      id-token: write # for `pnpm publish --provenance`
release_runtime perms .github/workflows/release_runtime.yml
Triggers
workflow_dispatch, push
Runs on
ubuntu-slim, ubuntu-slim
Jobs
check, build
Actions
taiki-e/checkout-action, taiki-e/checkout-action, oxc-project/setup-node
Commands
  • npm install -g npm@latest
  • pnpm publish --provenance --access public --no-git-checks
View raw YAML
name: Release @oxc-project/runtime

permissions: {}

on:
  workflow_dispatch:
  push:
    branches:
      - main
    paths:
      - npm/runtime/package.json
      - .github/workflows/release_runtime.yml

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  check:
    if: github.repository == 'oxc-project/oxc'
    name: Check version
    runs-on: ubuntu-slim
    outputs:
      version: ${{ steps.check.outputs.version }}
      version_changed: ${{ steps.check.outputs.version_changed }}
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: ./.github/actions/check-version
        id: check
        with:
          file-name: npm/runtime/package.json
          file-url: https://unpkg.com/@oxc-project/runtime/package.json

  build:
    needs: check
    if: needs.check.outputs.version_changed == 'true'
    name: Release @oxc-project/runtime
    runs-on: ubuntu-slim
    permissions:
      id-token: write # for `pnpm publish --provenance`
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0

      - run: npm install -g npm@latest # For trusted publishing support

      # Trusted publishing is configured, publish token is not required.
      - name: Trusted Publish
        working-directory: npm/runtime
        run: pnpm publish --provenance --access public --no-git-checks
release_types perms .github/workflows/release_types.yml
Triggers
workflow_dispatch, push
Runs on
ubuntu-slim, ubuntu-slim
Jobs
check, build
Actions
taiki-e/checkout-action, taiki-e/checkout-action, oxc-project/setup-node
Commands
  • npm install -g npm@latest
  • pnpm publish --provenance --access public --no-git-checks
View raw YAML
name: Release @oxc-project/types

permissions: {}

on:
  workflow_dispatch:
  push:
    branches:
      - main
    paths:
      - npm/oxc-types/package.json
      - .github/workflows/release_types.yml

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  check:
    if: github.repository == 'oxc-project/oxc'
    name: Check version
    runs-on: ubuntu-slim
    outputs:
      version: ${{ steps.check.outputs.version }}
      version_changed: ${{ steps.check.outputs.version_changed }}
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: ./.github/actions/check-version
        id: check
        with:
          file-name: npm/oxc-types/package.json
          file-url: https://unpkg.com/@oxc-project/types/package.json

  build:
    needs: check
    if: needs.check.outputs.version_changed == 'true'
    name: Release @oxc-project/types
    runs-on: ubuntu-slim
    permissions:
      id-token: write # for `pnpm publish --provenance`
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0

      - run: npm install -g npm@latest # For trusted publishing support

      # Trusted publishing is configured, publish token is not required.
      - name: Trusted Publish
        working-directory: npm/oxc-types
        run: pnpm publish --provenance --access public --no-git-checks
reusable_release_napi matrix perms .github/workflows/reusable_release_napi.yml
Triggers
workflow_call
Runs on
ubuntu-slim, ${{ matrix.os }}, ubuntu-latest, ubuntu-slim
Jobs
check, build, build-freebsd, publish
Matrix
include, include.build, include.os, include.target→ aarch64-apple-darwin, aarch64-linux-android, aarch64-pc-windows-msvc, aarch64-unknown-linux-gnu, aarch64-unknown-linux-musl, aarch64-unknown-linux-ohos, armv7-linux-androideabi, armv7-unknown-linux-gnueabihf, armv7-unknown-linux-musleabihf, export CFLAGS="-fuse-ld=lld" pnpm build --target s390x-unknown-linux-gnu --use-napi-cross , i686-pc-windows-msvc, macos-latest, pnpm build --target aarch64-apple-darwin, pnpm build --target aarch64-linux-android, pnpm build --target aarch64-pc-windows-msvc, pnpm build --target aarch64-unknown-linux-gnu --use-napi-cross, pnpm build --target aarch64-unknown-linux-musl -x, pnpm build --target aarch64-unknown-linux-ohos, pnpm build --target armv7-linux-androideabi, pnpm build --target armv7-unknown-linux-gnueabihf --use-napi-cross, pnpm build --target armv7-unknown-linux-musleabihf -x, pnpm build --target i686-pc-windows-msvc, pnpm build --target powerpc64le-unknown-linux-gnu --use-napi-cross, pnpm build --target wasm32-wasip1-threads, pnpm build --target x86_64-apple-darwin, pnpm build --target x86_64-pc-windows-msvc, pnpm build --target x86_64-unknown-linux-gnu --use-napi-cross, pnpm build --target x86_64-unknown-linux-musl -x, powerpc64le-unknown-linux-gnu, riscv64gc-unknown-linux-gnu, riscv64gc-unknown-linux-musl, s390x-unknown-linux-gnu, sudo apt-get update sudo apt-get install gcc-riscv64-linux-gnu g++-riscv64-linux-gnu -y export TARGET_CC=riscv64-linux-gnu-gcc export CXX=riscv64-linux-gnu-g++ pnpm build --target riscv64gc-unknown-linux-gnu , sudo apt-get update sudo apt-get install gcc-riscv64-linux-gnu g++-riscv64-linux-gnu -y export TARGET_CC=riscv64-linux-gnu-gcc export CXX=riscv64-linux-gnu-g++ pnpm build --target riscv64gc-unknown-linux-musl -x , ubuntu-latest, wasm32-wasip1-threads, windows-latest, x86_64-apple-darwin, x86_64-pc-windows-msvc, x86_64-unknown-linux-gnu, x86_64-unknown-linux-musl
Actions
taiki-e/checkout-action, taiki-e/checkout-action, oxc-project/setup-node, Boshen/setup-ohos-sdk, goto-bus-stop/setup-zig, taiki-e/checkout-action, cross-platform-actions/action, taiki-e/checkout-action, oxc-project/setup-node
Commands
  • git config --system core.longpaths true
  • rustup target add ${{ matrix.target }}
  • ${{ matrix.build }}
  • mkdir -p ${npm_dir}
  • pnpm napi create-npm-dirs --package-json-path ${package_path}/package.json --npm-dir ${npm_dir}
  • pnpm napi artifacts --package-json-path ${package_path}/package.json --build-output-dir ${package_path}/src-js --npm-dir ${npm_dir}
  • pnpm napi artifacts --package-json-path ${package_path}/package.json --build-output-dir ${package_path} --npm-dir ${npm_dir}
  • pnpm -C ${package_path} build-browser-bundle --npmDir ../../${npm_dir}
View raw YAML
name: Release NAPI

permissions: {}

on:
  workflow_call:
    inputs:
      name:
        required: true
        type: string
        description: "The component name"

jobs:
  check:
    name: Check version
    runs-on: ubuntu-slim
    outputs:
      version_changed: ${{ steps.check.outputs.version_changed }}
    env:
      name: ${{ inputs.name }}
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - uses: ./.github/actions/check-version
        id: check
        with:
          file-name: napi/${{ inputs.name }}/package.json
          file-url: https://unpkg.com/oxc-${{ inputs.name }}@latest/package.json

  build:
    needs: check
    if: needs.check.outputs.version_changed == 'true'
    name: Build ${{ matrix.target }}
    runs-on: ${{ matrix.os }}
    env:
      name: ${{ inputs.name }}
    defaults:
      run:
        shell: bash
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            build: pnpm build --target x86_64-pc-windows-msvc

          - os: windows-latest
            target: aarch64-pc-windows-msvc
            build: pnpm build --target aarch64-pc-windows-msvc

          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            build: pnpm build --target x86_64-unknown-linux-gnu --use-napi-cross

          - os: ubuntu-latest
            target: x86_64-unknown-linux-musl
            build: pnpm build --target x86_64-unknown-linux-musl -x

          - os: ubuntu-latest
            target: aarch64-unknown-linux-gnu
            build: pnpm build --target aarch64-unknown-linux-gnu --use-napi-cross

          - os: ubuntu-latest
            target: aarch64-unknown-linux-musl
            build: pnpm build --target aarch64-unknown-linux-musl -x

          - os: ubuntu-latest
            target: armv7-unknown-linux-gnueabihf
            build: pnpm build --target armv7-unknown-linux-gnueabihf --use-napi-cross

          - os: macos-latest
            target: x86_64-apple-darwin
            build: pnpm build --target x86_64-apple-darwin

          - os: macos-latest
            target: aarch64-apple-darwin
            build: pnpm build --target aarch64-apple-darwin

          - os: ubuntu-latest
            target: wasm32-wasip1-threads
            build: pnpm build --target wasm32-wasip1-threads

          - os: ubuntu-latest
            target: s390x-unknown-linux-gnu
            build: |
              export CFLAGS="-fuse-ld=lld"
              pnpm build --target s390x-unknown-linux-gnu --use-napi-cross

          - os: ubuntu-latest
            target: aarch64-linux-android
            build: pnpm build --target aarch64-linux-android

          - os: ubuntu-latest
            target: riscv64gc-unknown-linux-gnu
            build: |
              sudo apt-get update
              sudo apt-get install gcc-riscv64-linux-gnu g++-riscv64-linux-gnu -y
              export TARGET_CC=riscv64-linux-gnu-gcc
              export CXX=riscv64-linux-gnu-g++
              pnpm build --target riscv64gc-unknown-linux-gnu

          - os: ubuntu-latest
            target: aarch64-unknown-linux-ohos
            build: pnpm build --target aarch64-unknown-linux-ohos

          - os: ubuntu-latest
            target: armv7-linux-androideabi
            build: pnpm build --target armv7-linux-androideabi

          - os: ubuntu-latest
            target: armv7-unknown-linux-musleabihf
            build: pnpm build --target armv7-unknown-linux-musleabihf -x

          - os: windows-latest
            target: i686-pc-windows-msvc
            build: pnpm build --target i686-pc-windows-msvc

          - os: ubuntu-latest
            target: powerpc64le-unknown-linux-gnu
            build: pnpm build --target powerpc64le-unknown-linux-gnu --use-napi-cross

          - os: ubuntu-latest
            target: riscv64gc-unknown-linux-musl
            build: |
              sudo apt-get update
              sudo apt-get install gcc-riscv64-linux-gnu g++-riscv64-linux-gnu -y
              export TARGET_CC=riscv64-linux-gnu-gcc
              export CXX=riscv64-linux-gnu-g++
              pnpm build --target riscv64gc-unknown-linux-musl -x

    steps:
      - if: ${{ contains(matrix.os, 'windows') }}
        run: git config --system core.longpaths true

      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0

      - run: rustup target add ${{ matrix.target }}

      - name: Setup OpenHarmony SDK
        if: ${{ contains(matrix.target, 'ohos') }}
        uses: Boshen/setup-ohos-sdk@edb865a89a712f1f15dbad932dfa9cfce849d95c # v1.0.0

      - uses: goto-bus-stop/setup-zig@abea47f85e598557f500fa1fd2ab7464fcb39406 # v2.2.1
        if: ${{ contains(matrix.target, 'musl') }}
        with:
          version: 0.13.0

      - name: Build
        working-directory: napi/${{ inputs.name }}
        run: ${{ matrix.build }}
        shell: bash
        env:
          TARGET_CC: clang # for mimalloc

      - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          if-no-files-found: error
          name: bindings-${{ matrix.target }}
          # `**/*.node` because in `napi/parser`, binaries are in `src-js` subdirectory
          path: |
            napi/${{ inputs.name }}/**/*.node
            napi/${{ inputs.name }}/**/*.wasm

  build-freebsd:
    needs: check
    if: needs.check.outputs.version_changed == 'true'
    name: Build FreeBSD
    runs-on: ubuntu-latest
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1
      - name: Build
        id: build
        uses: cross-platform-actions/action@492b0c80085400348c599edace11141a4ee73524 # v0.32.0
        env:
          DEBUG: napi:*
          RUSTUP_IO_THREADS: 1
        with:
          operating_system: freebsd
          version: "14.2"
          memory: 8G
          cpu_count: 3
          environment_variables: "DEBUG RUSTUP_IO_THREADS"
          shell: bash
          run: |
            sudo pkg install -y -f curl libnghttp2 node22 npm cmake ca_root_nss
            curl https://sh.rustup.rs -sSf --output rustup.sh
            sh rustup.sh -y --profile minimal --default-toolchain stable
            source "$HOME/.cargo/env"
            echo "~~~~ rustc --version ~~~~"
            rustc --version
            echo "~~~~ node -v ~~~~"
            node -v
            pwd
            ls -lah
            whoami
            env
            cd napi/${{ inputs.name }}
            export COREPACK_INTEGRITY_KEYS=0
            sudo corepack enable
            pnpm install --ignore-scripts # postinstall: The current platform (freebsd) and architecture (x64) is not supported.
            pnpm build --target x86_64-unknown-freebsd
            rm -rf node_modules
            rm -rf target
      - name: Upload artifact
        uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        with:
          if-no-files-found: error
          name: bindings-freebsd
          # `**/*.node` because in `napi/parser`, binary is in `src-js` subdirectory
          path: napi/${{ inputs.name }}/**/*.node

  publish:
    name: Publish NAPI
    needs:
      - build
      - build-freebsd
    runs-on: ubuntu-slim
    permissions:
      id-token: write # for `pnpm publish --provenance`
    env:
      name: ${{ inputs.name }}
      package_path: napi/${{ inputs.name }}
      npm_dir: release-dir
      PUBLISH_FLAGS: "--provenance --access public --no-git-checks"
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0

      - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
        with:
          path: artifacts

      - run: mkdir -p ${npm_dir}

      - run: pnpm napi create-npm-dirs --package-json-path ${package_path}/package.json --npm-dir ${npm_dir}

      - run: pnpm napi artifacts --package-json-path ${package_path}/package.json --build-output-dir ${package_path}/src-js --npm-dir ${npm_dir}
        if: ${{ inputs.name == 'parser' }}

      - run: pnpm napi artifacts --package-json-path ${package_path}/package.json --build-output-dir ${package_path} --npm-dir ${npm_dir}
        if: ${{ inputs.name != 'parser' }}

      - run: pnpm -C ${package_path} build-browser-bundle --npmDir ../../${npm_dir}
        if: ${{ inputs.name == 'parser' }}

      - run: npm install -g npm@latest # For trusted publishing support

      - name: Check Publish
        run: node .github/scripts/check-npm-packages.js "${npm_dir}/*" "${package_path}"

      - name: Trusted Publish
        run: |
          # Trusted publishing is configured, publish token is not required.
          # Publish sub-packages and adds `optionalDependencies` to `package_path`.
          pnpm napi pre-publish --no-gh-release -t npm --package-json-path ${package_path}/package.json --npm-dir ${npm_dir}
          bash .github/scripts/publish-if-needed.sh ${package_path} ${PUBLISH_FLAGS}
update_submodules perms .github/workflows/update_submodules.yml
Triggers
workflow_dispatch, workflow_call
Runs on
ubuntu-latest
Jobs
update
Actions
taiki-e/checkout-action, oxc-project/setup-node, oxc-project/setup-rust, peter-evans/create-pull-request
Commands
  • # Function to fetch latest SHA for a repo fetch_sha() { local name=$1 local repo=$2 local branch=${3:-HEAD} echo "Fetching latest SHA for $repo (branch: $branch)..." # Use GitHub API to get latest commit SHA (much faster than cloning) # Use GITHUB_TOKEN to avoid rate limiting response=$(curl -s -H "Authorization: token ${{ github.token }}" "https://api.github.com/repos/$repo/commits/$branch") sha=$(echo "$response" | jq -r .sha) # Validate SHA is not null or empty if [ "$sha" = "null" ] || [ -z "$sha" ]; then echo "Error: Failed to fetch SHA for $repo (got: '$sha')" echo "API Response: $response" echo "This may be due to GitHub API rate limiting, repository access issues, or branch not found" # Check for specific error messages error_message=$(echo "$response" | jq -r .message 2>/dev/null) if [ "$error_message" != "null" ] && [ -n "$error_message" ]; then echo "GitHub API Error: $error_message" fi exit 1 fi # Output the SHA echo "${name}_LATEST=$sha" >> $GITHUB_OUTPUT echo "$name latest SHA: $sha" } # Use provided SHAs from workflow_call inputs if available, otherwise fetch from GitHub if [ -n "$INPUT_TEST262_SHA" ]; then echo "TEST262_LATEST=$INPUT_TEST262_SHA" >> $GITHUB_OUTPUT echo "TEST262 SHA (from input): $INPUT_TEST262_SHA" else fetch_sha "TEST262" "tc39/test262" fi if [ -n "$INPUT_TYPESCRIPT_SHA" ]; then echo "TYPESCRIPT_LATEST=$INPUT_TYPESCRIPT_SHA" >> $GITHUB_OUTPUT echo "TYPESCRIPT SHA (from input): $INPUT_TYPESCRIPT_SHA" else fetch_sha "TYPESCRIPT" "microsoft/TypeScript" fi if [ -n "$INPUT_ESTREE_CONFORMANCE_SHA" ]; then echo "ESTREE_CONFORMANCE_LATEST=$INPUT_ESTREE_CONFORMANCE_SHA" >> $GITHUB_OUTPUT echo "ESTREE_CONFORMANCE SHA (from input): $INPUT_ESTREE_CONFORMANCE_SHA" else fetch_sha "ESTREE_CONFORMANCE" "oxc-project/estree-conformance" fi # Always fetch BABEL and NODE_COMPAT_TABLE (not provided via inputs) fetch_sha "BABEL" "babel/babel" fetch_sha "NODE_COMPAT_TABLE" "compat-table/node-compat-table" "gh-pages"
  • # Extract current SHAs from the script TEST262_CURRENT=$(grep 'const TEST262_SHA' .github/scripts/clone-parallel.mjs | cut -d'"' -f2) BABEL_CURRENT=$(grep 'const BABEL_SHA' .github/scripts/clone-parallel.mjs | cut -d'"' -f2) TYPESCRIPT_CURRENT=$(grep 'const TYPESCRIPT_SHA' .github/scripts/clone-parallel.mjs | cut -d'"' -f2) # PRETTIER_CURRENT=$(grep 'const PRETTIER_SHA' .github/scripts/clone-parallel.mjs | cut -d'"' -f2) ESTREE_CONFORMANCE_CURRENT=$(grep 'const ESTREE_CONFORMANCE_SHA' .github/scripts/clone-parallel.mjs | cut -d'"' -f2) NODE_COMPAT_TABLE_CURRENT=$(grep 'const NODE_COMPAT_TABLE_SHA' .github/scripts/clone-parallel.mjs | cut -d'"' -f2) echo "TEST262_CURRENT=$TEST262_CURRENT" >> $GITHUB_OUTPUT echo "BABEL_CURRENT=$BABEL_CURRENT" >> $GITHUB_OUTPUT echo "TYPESCRIPT_CURRENT=$TYPESCRIPT_CURRENT" >> $GITHUB_OUTPUT # echo "PRETTIER_CURRENT=$PRETTIER_CURRENT" >> $GITHUB_OUTPUT echo "ESTREE_CONFORMANCE_CURRENT=$ESTREE_CONFORMANCE_CURRENT" >> $GITHUB_OUTPUT echo "NODE_COMPAT_TABLE_CURRENT=$NODE_COMPAT_TABLE_CURRENT" >> $GITHUB_OUTPUT echo "Current SHAs:" echo " TEST262: $TEST262_CURRENT" echo " BABEL: $BABEL_CURRENT" echo " TYPESCRIPT: $TYPESCRIPT_CURRENT" # echo " PRETTIER: $PRETTIER_CURRENT" echo " ESTREE_CONFORMANCE: $ESTREE_CONFORMANCE_CURRENT" echo " NODE_COMPAT_TABLE: $NODE_COMPAT_TABLE_CURRENT"
  • updates_needed=false update_summary="" # Check each submodule if [ "$TEST262_LATEST" != "$TEST262_CURRENT" ]; then updates_needed=true update_summary="${update_summary}- test262: \`${TEST262_CURRENT:0:7}\` → \`${TEST262_LATEST:0:7}\`\n" echo "TEST262 needs update: $TEST262_CURRENT -> $TEST262_LATEST" fi if [ "$BABEL_LATEST" != "$BABEL_CURRENT" ]; then updates_needed=true update_summary="${update_summary}- babel: \`${BABEL_CURRENT:0:7}\` → \`${BABEL_LATEST:0:7}\`\n" echo "BABEL needs update: $BABEL_CURRENT -> $BABEL_LATEST" fi if [ "$TYPESCRIPT_LATEST" != "$TYPESCRIPT_CURRENT" ]; then updates_needed=true update_summary="${update_summary}- TypeScript: \`${TYPESCRIPT_CURRENT:0:7}\` → \`${TYPESCRIPT_LATEST:0:7}\`\n" echo "TYPESCRIPT needs update: $TYPESCRIPT_CURRENT -> $TYPESCRIPT_LATEST" fi # if [ "$PRETTIER_LATEST" != "$PRETTIER_CURRENT" ]; then # updates_needed=true # update_summary="${update_summary}- prettier: \`${PRETTIER_CURRENT:0:7}\` → \`${PRETTIER_LATEST:0:7}\`\n" # echo "PRETTIER needs update: $PRETTIER_CURRENT -> $PRETTIER_LATEST" # fi if [ "$ESTREE_CONFORMANCE_LATEST" != "$ESTREE_CONFORMANCE_CURRENT" ]; then updates_needed=true update_summary="${update_summary}- estree-conformance: \`${ESTREE_CONFORMANCE_CURRENT:0:7}\` → \`${ESTREE_CONFORMANCE_LATEST:0:7}\`\n" echo "ESTREE_CONFORMANCE needs update: $ESTREE_CONFORMANCE_CURRENT -> $ESTREE_CONFORMANCE_LATEST" fi if [ "$NODE_COMPAT_TABLE_LATEST" != "$NODE_COMPAT_TABLE_CURRENT" ]; then updates_needed=true update_summary="${update_summary}- node-compat-table: \`${NODE_COMPAT_TABLE_CURRENT:0:7}\` → \`${NODE_COMPAT_TABLE_LATEST:0:7}\`\n" echo "NODE_COMPAT_TABLE needs update: $NODE_COMPAT_TABLE_CURRENT -> $NODE_COMPAT_TABLE_LATEST" fi if [ "$updates_needed" = true ]; then echo "updates_needed=true" >> $GITHUB_OUTPUT echo "update_summary<<EOF" >> $GITHUB_OUTPUT echo -e "$update_summary" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT echo "Updates needed!" else echo "updates_needed=false" >> $GITHUB_OUTPUT echo "No updates needed, all SHAs are current" fi
  • js_script=".github/scripts/clone-parallel.mjs" # Update each SHA if it changed if [ "$TEST262_LATEST" != "$TEST262_CURRENT" ]; then sed -i "s/const TEST262_SHA = \"$TEST262_CURRENT\";/const TEST262_SHA = \"$TEST262_LATEST\";/g" "$js_script" echo "Updated TEST262_SHA" fi if [ "$BABEL_LATEST" != "$BABEL_CURRENT" ]; then sed -i "s/const BABEL_SHA = \"$BABEL_CURRENT\";/const BABEL_SHA = \"$BABEL_LATEST\";/g" "$js_script" echo "Updated BABEL_SHA" fi if [ "$TYPESCRIPT_LATEST" != "$TYPESCRIPT_CURRENT" ]; then sed -i "s/const TYPESCRIPT_SHA = \"$TYPESCRIPT_CURRENT\";/const TYPESCRIPT_SHA = \"$TYPESCRIPT_LATEST\";/g" "$js_script" echo "Updated TYPESCRIPT_SHA" fi # if [ "$PRETTIER_LATEST" != "$PRETTIER_CURRENT" ]; then # sed -i "s/const PRETTIER_SHA = \"$PRETTIER_CURRENT\";/const PRETTIER_SHA = \"$PRETTIER_LATEST\";/g" "$js_script" # echo "Updated PRETTIER_SHA" # fi if [ "$ESTREE_CONFORMANCE_LATEST" != "$ESTREE_CONFORMANCE_CURRENT" ]; then sed -i "s/const ESTREE_CONFORMANCE_SHA = \"$ESTREE_CONFORMANCE_CURRENT\";/const ESTREE_CONFORMANCE_SHA = \"$ESTREE_CONFORMANCE_LATEST\";/g" "$js_script" echo "Updated ESTREE_CONFORMANCE_SHA" fi if [ "$NODE_COMPAT_TABLE_LATEST" != "$NODE_COMPAT_TABLE_CURRENT" ]; then sed -i "s/const NODE_COMPAT_TABLE_SHA = \"$NODE_COMPAT_TABLE_CURRENT\";/const NODE_COMPAT_TABLE_SHA = \"$NODE_COMPAT_TABLE_LATEST\";/g" "$js_script" echo "Updated NODE_COMPAT_TABLE_SHA" fi echo "Updated clone-parallel.mjs with new SHAs"
  • cargo fmt node --run fmt
  • just submodules
  • just coverage
View raw YAML
# NOTE: Prettier version is now pinned to v3.7.0 (not updated by this workflow)
name: Update Submodules

permissions: {}

on:
  # Triggered by https://github.com/oxc-project/estree-conformance/actions/workflows/trigger-oxc-update.yml
  workflow_dispatch:
    inputs:
      test262_sha:
        description: "Test262 commit SHA (optional - will fetch latest if not provided)"
        required: false
        type: string
      typescript_sha:
        description: "TypeScript commit SHA (optional - will fetch latest if not provided)"
        required: false
        type: string
      estree_conformance_sha:
        description: "estree-conformance commit SHA (includes test262, TypeScript, and acorn-jsx fixtures - optional - will fetch latest if not provided)"
        required: false
        type: string
  workflow_call:
    inputs:
      test262_sha:
        description: "Test262 commit SHA (optional - will fetch latest if not provided)"
        required: false
        type: string
      typescript_sha:
        description: "TypeScript commit SHA (optional - will fetch latest if not provided)"
        required: false
        type: string
      estree_conformance_sha:
        description: "estree-conformance commit SHA (includes test262, TypeScript, and acorn-jsx fixtures - optional - will fetch latest if not provided)"
        required: false
        type: string

concurrency:
  group: ${{ github.workflow }}-${{ github.ref_name }}
  cancel-in-progress: true

jobs:
  update:
    name: Update submodule SHAs
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    steps:
      - uses: taiki-e/checkout-action@83ed61bfbe2b8abbb3c66e8b65b1335484c70009 # v1.4.1

      - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0
      - uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16
        with:
          cache-key: conformance
          tools: just
          components: rustfmt

      - name: Get latest SHAs for all submodules
        id: get-shas
        env:
          INPUT_TEST262_SHA: ${{ inputs.test262_sha }}
          INPUT_TYPESCRIPT_SHA: ${{ inputs.typescript_sha }}
          INPUT_ESTREE_CONFORMANCE_SHA: ${{ inputs.estree_conformance_sha }}
        run: |
          # Function to fetch latest SHA for a repo
          fetch_sha() {
            local name=$1
            local repo=$2
            local branch=${3:-HEAD}

            echo "Fetching latest SHA for $repo (branch: $branch)..."

            # Use GitHub API to get latest commit SHA (much faster than cloning)
            # Use GITHUB_TOKEN to avoid rate limiting
            response=$(curl -s -H "Authorization: token ${{ github.token }}" "https://api.github.com/repos/$repo/commits/$branch")
            sha=$(echo "$response" | jq -r .sha)

            # Validate SHA is not null or empty
            if [ "$sha" = "null" ] || [ -z "$sha" ]; then
              echo "Error: Failed to fetch SHA for $repo (got: '$sha')"
              echo "API Response: $response"
              echo "This may be due to GitHub API rate limiting, repository access issues, or branch not found"

              # Check for specific error messages
              error_message=$(echo "$response" | jq -r .message 2>/dev/null)
              if [ "$error_message" != "null" ] && [ -n "$error_message" ]; then
                echo "GitHub API Error: $error_message"
              fi

              exit 1
            fi

            # Output the SHA
            echo "${name}_LATEST=$sha" >> $GITHUB_OUTPUT
            echo "$name latest SHA: $sha"
          }

          # Use provided SHAs from workflow_call inputs if available, otherwise fetch from GitHub
          if [ -n "$INPUT_TEST262_SHA" ]; then
            echo "TEST262_LATEST=$INPUT_TEST262_SHA" >> $GITHUB_OUTPUT
            echo "TEST262 SHA (from input): $INPUT_TEST262_SHA"
          else
            fetch_sha "TEST262" "tc39/test262"
          fi

          if [ -n "$INPUT_TYPESCRIPT_SHA" ]; then
            echo "TYPESCRIPT_LATEST=$INPUT_TYPESCRIPT_SHA" >> $GITHUB_OUTPUT
            echo "TYPESCRIPT SHA (from input): $INPUT_TYPESCRIPT_SHA"
          else
            fetch_sha "TYPESCRIPT" "microsoft/TypeScript"
          fi

          if [ -n "$INPUT_ESTREE_CONFORMANCE_SHA" ]; then
            echo "ESTREE_CONFORMANCE_LATEST=$INPUT_ESTREE_CONFORMANCE_SHA" >> $GITHUB_OUTPUT
            echo "ESTREE_CONFORMANCE SHA (from input): $INPUT_ESTREE_CONFORMANCE_SHA"
          else
            fetch_sha "ESTREE_CONFORMANCE" "oxc-project/estree-conformance"
          fi

          # Always fetch BABEL and NODE_COMPAT_TABLE (not provided via inputs)
          fetch_sha "BABEL" "babel/babel"
          fetch_sha "NODE_COMPAT_TABLE" "compat-table/node-compat-table" "gh-pages"

      - name: Get current SHAs from clone-parallel.mjs
        id: current-shas
        run: |
          # Extract current SHAs from the script
          TEST262_CURRENT=$(grep 'const TEST262_SHA' .github/scripts/clone-parallel.mjs | cut -d'"' -f2)
          BABEL_CURRENT=$(grep 'const BABEL_SHA' .github/scripts/clone-parallel.mjs | cut -d'"' -f2)
          TYPESCRIPT_CURRENT=$(grep 'const TYPESCRIPT_SHA' .github/scripts/clone-parallel.mjs | cut -d'"' -f2)
          # PRETTIER_CURRENT=$(grep 'const PRETTIER_SHA' .github/scripts/clone-parallel.mjs | cut -d'"' -f2)
          ESTREE_CONFORMANCE_CURRENT=$(grep 'const ESTREE_CONFORMANCE_SHA' .github/scripts/clone-parallel.mjs | cut -d'"' -f2)
          NODE_COMPAT_TABLE_CURRENT=$(grep 'const NODE_COMPAT_TABLE_SHA' .github/scripts/clone-parallel.mjs | cut -d'"' -f2)

          echo "TEST262_CURRENT=$TEST262_CURRENT" >> $GITHUB_OUTPUT
          echo "BABEL_CURRENT=$BABEL_CURRENT" >> $GITHUB_OUTPUT
          echo "TYPESCRIPT_CURRENT=$TYPESCRIPT_CURRENT" >> $GITHUB_OUTPUT
          # echo "PRETTIER_CURRENT=$PRETTIER_CURRENT" >> $GITHUB_OUTPUT
          echo "ESTREE_CONFORMANCE_CURRENT=$ESTREE_CONFORMANCE_CURRENT" >> $GITHUB_OUTPUT
          echo "NODE_COMPAT_TABLE_CURRENT=$NODE_COMPAT_TABLE_CURRENT" >> $GITHUB_OUTPUT

          echo "Current SHAs:"
          echo "  TEST262: $TEST262_CURRENT"
          echo "  BABEL: $BABEL_CURRENT"
          echo "  TYPESCRIPT: $TYPESCRIPT_CURRENT"
          # echo "  PRETTIER: $PRETTIER_CURRENT"
          echo "  ESTREE_CONFORMANCE: $ESTREE_CONFORMANCE_CURRENT"
          echo "  NODE_COMPAT_TABLE: $NODE_COMPAT_TABLE_CURRENT"

      - name: Check if updates are needed
        id: check-updates
        env:
          TEST262_LATEST: ${{ steps.get-shas.outputs.TEST262_LATEST }}
          TEST262_CURRENT: ${{ steps.current-shas.outputs.TEST262_CURRENT }}
          BABEL_LATEST: ${{ steps.get-shas.outputs.BABEL_LATEST }}
          BABEL_CURRENT: ${{ steps.current-shas.outputs.BABEL_CURRENT }}
          TYPESCRIPT_LATEST: ${{ steps.get-shas.outputs.TYPESCRIPT_LATEST }}
          TYPESCRIPT_CURRENT: ${{ steps.current-shas.outputs.TYPESCRIPT_CURRENT }}
          # PRETTIER_LATEST: ${{ steps.get-shas.outputs.PRETTIER_LATEST }}
          # PRETTIER_CURRENT: ${{ steps.current-shas.outputs.PRETTIER_CURRENT }}
          ESTREE_CONFORMANCE_LATEST: ${{ steps.get-shas.outputs.ESTREE_CONFORMANCE_LATEST }}
          ESTREE_CONFORMANCE_CURRENT: ${{ steps.current-shas.outputs.ESTREE_CONFORMANCE_CURRENT }}
          NODE_COMPAT_TABLE_LATEST: ${{ steps.get-shas.outputs.NODE_COMPAT_TABLE_LATEST }}
          NODE_COMPAT_TABLE_CURRENT: ${{ steps.current-shas.outputs.NODE_COMPAT_TABLE_CURRENT }}
        run: |
          updates_needed=false
          update_summary=""

          # Check each submodule
          if [ "$TEST262_LATEST" != "$TEST262_CURRENT" ]; then
            updates_needed=true
            update_summary="${update_summary}- test262: \`${TEST262_CURRENT:0:7}\` → \`${TEST262_LATEST:0:7}\`\n"
            echo "TEST262 needs update: $TEST262_CURRENT -> $TEST262_LATEST"
          fi

          if [ "$BABEL_LATEST" != "$BABEL_CURRENT" ]; then
            updates_needed=true
            update_summary="${update_summary}- babel: \`${BABEL_CURRENT:0:7}\` → \`${BABEL_LATEST:0:7}\`\n"
            echo "BABEL needs update: $BABEL_CURRENT -> $BABEL_LATEST"
          fi

          if [ "$TYPESCRIPT_LATEST" != "$TYPESCRIPT_CURRENT" ]; then
            updates_needed=true
            update_summary="${update_summary}- TypeScript: \`${TYPESCRIPT_CURRENT:0:7}\` → \`${TYPESCRIPT_LATEST:0:7}\`\n"
            echo "TYPESCRIPT needs update: $TYPESCRIPT_CURRENT -> $TYPESCRIPT_LATEST"
          fi

          # if [ "$PRETTIER_LATEST" != "$PRETTIER_CURRENT" ]; then
          #   updates_needed=true
          #   update_summary="${update_summary}- prettier: \`${PRETTIER_CURRENT:0:7}\` → \`${PRETTIER_LATEST:0:7}\`\n"
          #   echo "PRETTIER needs update: $PRETTIER_CURRENT -> $PRETTIER_LATEST"
          # fi

          if [ "$ESTREE_CONFORMANCE_LATEST" != "$ESTREE_CONFORMANCE_CURRENT" ]; then
            updates_needed=true
            update_summary="${update_summary}- estree-conformance: \`${ESTREE_CONFORMANCE_CURRENT:0:7}\` → \`${ESTREE_CONFORMANCE_LATEST:0:7}\`\n"
            echo "ESTREE_CONFORMANCE needs update: $ESTREE_CONFORMANCE_CURRENT -> $ESTREE_CONFORMANCE_LATEST"
          fi

          if [ "$NODE_COMPAT_TABLE_LATEST" != "$NODE_COMPAT_TABLE_CURRENT" ]; then
            updates_needed=true
            update_summary="${update_summary}- node-compat-table: \`${NODE_COMPAT_TABLE_CURRENT:0:7}\` → \`${NODE_COMPAT_TABLE_LATEST:0:7}\`\n"
            echo "NODE_COMPAT_TABLE needs update: $NODE_COMPAT_TABLE_CURRENT -> $NODE_COMPAT_TABLE_LATEST"
          fi

          if [ "$updates_needed" = true ]; then
            echo "updates_needed=true" >> $GITHUB_OUTPUT
            echo "update_summary<<EOF" >> $GITHUB_OUTPUT
            echo -e "$update_summary" >> $GITHUB_OUTPUT
            echo "EOF" >> $GITHUB_OUTPUT
            echo "Updates needed!"
          else
            echo "updates_needed=false" >> $GITHUB_OUTPUT
            echo "No updates needed, all SHAs are current"
          fi

      - name: Update clone-parallel.mjs with new SHAs
        if: steps.check-updates.outputs.updates_needed == 'true'
        env:
          TEST262_LATEST: ${{ steps.get-shas.outputs.TEST262_LATEST }}
          BABEL_LATEST: ${{ steps.get-shas.outputs.BABEL_LATEST }}
          TYPESCRIPT_LATEST: ${{ steps.get-shas.outputs.TYPESCRIPT_LATEST }}
          # PRETTIER_LATEST: ${{ steps.get-shas.outputs.PRETTIER_LATEST }}
          ESTREE_CONFORMANCE_LATEST: ${{ steps.get-shas.outputs.ESTREE_CONFORMANCE_LATEST }}
          NODE_COMPAT_TABLE_LATEST: ${{ steps.get-shas.outputs.NODE_COMPAT_TABLE_LATEST }}
          TEST262_CURRENT: ${{ steps.current-shas.outputs.TEST262_CURRENT }}
          BABEL_CURRENT: ${{ steps.current-shas.outputs.BABEL_CURRENT }}
          TYPESCRIPT_CURRENT: ${{ steps.current-shas.outputs.TYPESCRIPT_CURRENT }}
          # PRETTIER_CURRENT: ${{ steps.current-shas.outputs.PRETTIER_CURRENT }}
          ESTREE_CONFORMANCE_CURRENT: ${{ steps.current-shas.outputs.ESTREE_CONFORMANCE_CURRENT }}
          NODE_COMPAT_TABLE_CURRENT: ${{ steps.current-shas.outputs.NODE_COMPAT_TABLE_CURRENT }}
        run: |
          js_script=".github/scripts/clone-parallel.mjs"

          # Update each SHA if it changed
          if [ "$TEST262_LATEST" != "$TEST262_CURRENT" ]; then
            sed -i "s/const TEST262_SHA = \"$TEST262_CURRENT\";/const TEST262_SHA = \"$TEST262_LATEST\";/g" "$js_script"
            echo "Updated TEST262_SHA"
          fi

          if [ "$BABEL_LATEST" != "$BABEL_CURRENT" ]; then
            sed -i "s/const BABEL_SHA = \"$BABEL_CURRENT\";/const BABEL_SHA = \"$BABEL_LATEST\";/g" "$js_script"
            echo "Updated BABEL_SHA"
          fi

          if [ "$TYPESCRIPT_LATEST" != "$TYPESCRIPT_CURRENT" ]; then
            sed -i "s/const TYPESCRIPT_SHA = \"$TYPESCRIPT_CURRENT\";/const TYPESCRIPT_SHA = \"$TYPESCRIPT_LATEST\";/g" "$js_script"
            echo "Updated TYPESCRIPT_SHA"
          fi

          # if [ "$PRETTIER_LATEST" != "$PRETTIER_CURRENT" ]; then
          #   sed -i "s/const PRETTIER_SHA = \"$PRETTIER_CURRENT\";/const PRETTIER_SHA = \"$PRETTIER_LATEST\";/g" "$js_script"
          #   echo "Updated PRETTIER_SHA"
          # fi

          if [ "$ESTREE_CONFORMANCE_LATEST" != "$ESTREE_CONFORMANCE_CURRENT" ]; then
            sed -i "s/const ESTREE_CONFORMANCE_SHA = \"$ESTREE_CONFORMANCE_CURRENT\";/const ESTREE_CONFORMANCE_SHA = \"$ESTREE_CONFORMANCE_LATEST\";/g" "$js_script"
            echo "Updated ESTREE_CONFORMANCE_SHA"
          fi

          if [ "$NODE_COMPAT_TABLE_LATEST" != "$NODE_COMPAT_TABLE_CURRENT" ]; then
            sed -i "s/const NODE_COMPAT_TABLE_SHA = \"$NODE_COMPAT_TABLE_CURRENT\";/const NODE_COMPAT_TABLE_SHA = \"$NODE_COMPAT_TABLE_LATEST\";/g" "$js_script"
            echo "Updated NODE_COMPAT_TABLE_SHA"
          fi

          echo "Updated clone-parallel.mjs with new SHAs"

      - name: Run format
        if: steps.check-updates.outputs.updates_needed == 'true'
        run: |
          cargo fmt
          node --run fmt

      - name: Clone submodules and update fixtures
        if: steps.check-updates.outputs.updates_needed == 'true'
        run: just submodules

      - name: Run coverage tests
        if: steps.check-updates.outputs.updates_needed == 'true'
        env:
          UPDATE_SNAPSHOT: 1
        run: just coverage

      - name: Create Pull Request
        if: steps.check-updates.outputs.updates_needed == 'true'
        uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
        with:
          token: ${{ secrets.OXC_BOT_PAT }}
          commit-message: "chore(submodules): update submodule SHAs to latest commits"
          branch: update-submodules
          branch-suffix: timestamp
          base: main
          title: "chore(submodules): update submodule SHAs to latest commits"
          assignees: Boshen
          body: |
            Updates submodule dependencies to their latest commits.

            ## Changes

            ${{ steps.check-updates.outputs.update_summary }}

            This PR is automatically generated by the [update_submodules workflow](https://github.com/oxc-project/oxc/blob/main/.github/workflows/update_submodules.yml).