unluac 1.1.1

Multi-dialect Lua decompiler written in Rust.
Documentation
name: Release

on:
  push:
    tags:
      - "v*.*.*"

permissions:
  contents: read

env:
  NODE_VERSION: "24"
  WASM_PACK_VERSION: "0.14.0"
  WASM_BINDGEN_CLI_VERSION: "0.2.115"

jobs:
  prepare:
    name: Prepare Release Metadata
    runs-on: ubuntu-24.04
    outputs:
      version: ${{ steps.version.outputs.version }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}

      - name: Verify tag version
        id: version
        shell: bash
        run: |
          VERSION="$(node .github/scripts/sync_versions.mjs --print-version)"
          TAG_VERSION="${GITHUB_REF_NAME#v}"

          if [[ "$TAG_VERSION" != "$VERSION" ]]; then
            echo "Release tag version ${TAG_VERSION} does not match workspace version ${VERSION}" >&2
            exit 1
          fi

          echo "version=${VERSION}" >> "$GITHUB_OUTPUT"

  preflight:
    name: Release Preflight
    runs-on: ubuntu-24.04
    needs: prepare
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: npm
          cache-dependency-path: packages/unluac-js/package-lock.json

      - name: Setup Rust
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: wasm32-unknown-unknown

      - name: Install Linux Lua build dependencies
        if: runner.os == 'Linux'
        run: |
          sudo apt-get update
          sudo apt-get install -y build-essential cmake libreadline-dev

      - name: Restore vendored Lua toolchain cache
        id: lua-toolchain-cache
        uses: actions/cache@v4
        with:
          path: |
            lua/sources
            lua/build
          key: ${{ runner.os }}-lua-toolchains-${{ hashFiles('xtask/Cargo.toml', 'xtask/src/toolchain.rs', '.cargo/config.toml') }}

      - name: Build vendored Lua toolchains
        if: steps.lua-toolchain-cache.outputs.cache-hit != 'true'
        run: cargo lua init all

      - name: Restore wasm tool cache
        id: wasm-tool-cache
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/bin/wasm-pack
            ~/.cargo/bin/wasm-bindgen
            ~/.cargo/bin/wasm-bindgen-test-runner
            ~/.cargo/bin/wasm2es6js
            ~/.cargo/.crates2.json
            ~/.cargo/.crates.toml
          key: ${{ runner.os }}-wasm-tools-wasm-pack-${{ env.WASM_PACK_VERSION }}-wasm-bindgen-${{ env.WASM_BINDGEN_CLI_VERSION }}

      - name: Install wasm-pack
        if: steps.wasm-tool-cache.outputs.cache-hit != 'true'
        run: cargo install wasm-pack --version ${{ env.WASM_PACK_VERSION }} --locked

      - name: Install wasm-bindgen CLI
        if: steps.wasm-tool-cache.outputs.cache-hit != 'true'
        run: cargo install wasm-bindgen-cli --version ${{ env.WASM_BINDGEN_CLI_VERSION }} --locked

      - name: Check synced package versions
        run: node .github/scripts/sync_versions.mjs --check

      - name: Run Rust lint and tests
        run: |
          cargo clippy --workspace --all-targets --all-features --locked -- -D warnings
          cargo unit-test --jobs 8

      - name: Dry-run crate publish
        run: cargo publish -p unluac --locked --dry-run

      - name: Dry-run npm pack
        working-directory: packages/unluac-js
        run: |
          npm install
          npm run build
          cd dist
          npm pack --pack-destination "${RUNNER_TEMP}"

  build-cli:
    name: Build CLI (${{ matrix.platform }})
    runs-on: ${{ matrix.os }}
    needs:
      - prepare
      - preflight
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-24.04
            platform: linux-x86_64
            binary_path: target/release/unluac-cli
            extension: ""
          - os: windows-2025
            platform: windows-x86_64
            binary_path: target/release/unluac-cli.exe
            extension: ".exe"
          - os: macos-15-intel
            platform: macos-x86_64
            binary_path: target/release/unluac-cli
            extension: ""
          - os: macos-15
            platform: macos-aarch64
            binary_path: target/release/unluac-cli
            extension: ""
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Rust
        uses: dtolnay/rust-toolchain@stable

      - name: Build release binary
        run: cargo build -p unluac-cli --release --locked

      - name: Rename release binary
        shell: bash
        env:
          VERSION: ${{ needs.prepare.outputs.version }}
        run: |
          mkdir -p release-assets
          cp "${{ matrix.binary_path }}" "release-assets/unluac-${VERSION}-${{ matrix.platform }}${{ matrix.extension }}"

      - name: Upload CLI artifact
        uses: actions/upload-artifact@v4
        with:
          name: cli-${{ matrix.platform }}
          path: release-assets/*

  publish-and-release:
    name: Publish crate, npm and Create Release
    runs-on: ubuntu-24.04
    needs:
      - prepare
      - preflight
      - build-cli
    permissions:
      contents: write
      id-token: write
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          registry-url: https://registry.npmjs.org
          cache: npm
          cache-dependency-path: packages/unluac-js/package-lock.json

      - name: Setup Rust
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: wasm32-unknown-unknown

      - name: Restore wasm tool cache
        id: wasm-tool-cache
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/bin/wasm-pack
            ~/.cargo/bin/wasm-bindgen
            ~/.cargo/bin/wasm-bindgen-test-runner
            ~/.cargo/bin/wasm2es6js
            ~/.cargo/.crates2.json
            ~/.cargo/.crates.toml
          key: ${{ runner.os }}-wasm-tools-wasm-pack-${{ env.WASM_PACK_VERSION }}-wasm-bindgen-${{ env.WASM_BINDGEN_CLI_VERSION }}

      - name: Install wasm-pack
        if: steps.wasm-tool-cache.outputs.cache-hit != 'true'
        run: cargo install wasm-pack --version ${{ env.WASM_PACK_VERSION }} --locked

      - name: Install wasm-bindgen CLI
        if: steps.wasm-tool-cache.outputs.cache-hit != 'true'
        run: cargo install wasm-bindgen-cli --version ${{ env.WASM_BINDGEN_CLI_VERSION }} --locked

      - name: Check synced package versions
        run: node .github/scripts/sync_versions.mjs --check

      - name: Inspect release registry state
        id: release-state
        shell: bash
        env:
          VERSION: ${{ needs.prepare.outputs.version }}
        run: |
          if npm view "unluac-js@${VERSION}" version >/dev/null 2>&1; then
            echo "npm_published=true" >> "$GITHUB_OUTPUT"
            echo "npm package unluac-js@${VERSION} is already published"
          else
            echo "npm_published=false" >> "$GITHUB_OUTPUT"
          fi

          if curl --silent --fail "https://crates.io/api/v1/crates/unluac/${VERSION}" >/dev/null; then
            echo "crate_published=true" >> "$GITHUB_OUTPUT"
            echo "crate unluac ${VERSION} is already published on crates.io"
          else
            echo "crate_published=false" >> "$GITHUB_OUTPUT"
          fi

      - name: Install npm dependencies
        working-directory: packages/unluac-js
        run: npm install

      - name: Build npm package
        working-directory: packages/unluac-js
        run: npm run build

      - name: Publish npm package
        if: steps.release-state.outputs.npm_published != 'true'
        working-directory: packages/unluac-js
        run: npm publish ./dist --access public

      - name: Publish Rust crate
        if: steps.release-state.outputs.crate_published != 'true'
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
          VERSION: ${{ needs.prepare.outputs.version }}
        shell: bash
        run: |
          set +e
          OUTPUT="$(cargo publish -p unluac --locked 2>&1)"
          STATUS=$?
          set -e

          if [[ $STATUS -eq 0 ]]; then
            printf '%s\n' "$OUTPUT"
            exit 0
          fi

          printf '%s\n' "$OUTPUT"

          if grep -Fq "crate unluac@${VERSION} already exists on crates.io index" <<<"$OUTPUT"; then
            echo "crate unluac ${VERSION} was already published while this workflow was running; continuing"
            exit 0
          fi

          exit "$STATUS"

      - name: Download CLI artifacts
        uses: actions/download-artifact@v4
        with:
          pattern: cli-*
          merge-multiple: true
          path: ${{ runner.temp }}/release-assets

      - name: Add wasm release asset
        shell: bash
        run: |
          cp packages/unluac-js/.wasm-build/unluac_wasm_bg.wasm "${{ runner.temp }}/release-assets/unluac_wasm_bg.wasm"

      - name: Create or update GitHub release
        env:
          GH_TOKEN: ${{ github.token }}
        run: |
          TAG="${GITHUB_REF_NAME}"

          if ! gh release view "$TAG" >/dev/null 2>&1; then
            gh release create "$TAG" --title "$TAG" --generate-notes
          fi

          gh release upload "$TAG" "${{ runner.temp }}/release-assets"/* --clobber