name: release on: push: tags: ["v*"] workflow_dispatch: inputs: tag: description: The tag to release required: true permissions: contents: read concurrency: group: release env: CARGO_TERM_COLOR: always MISE_TRUSTED_CONFIG_PATHS: ${{ github.workspace }} jobs: cli: timeout-minutes: 30 name: cli ${{ matrix.target }} runs-on: ${{ matrix.os }} strategy: fail-fast: true matrix: include: - { os: macos-latest, target: aarch64-apple-darwin } - { os: macos-latest, target: x86_64-apple-darwin } - { os: ubuntu-latest, target: x86_64-unknown-linux-musl, zig: true } - { os: ubuntu-latest, target: aarch64-unknown-linux-musl, zig: true } - { os: windows-latest, target: x86_64-pc-windows-msvc } - { os: windows-latest, target: aarch64-pc-windows-msvc } defaults: run: shell: bash steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ inputs.tag || github.ref }} - uses: jdx/mise-action@f5be966e4a917d54244728e6a5fdcd1d93a35e6c # v5.2.6 with: install_args: rust cache: false - uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1 if: matrix.zig with: use-cache: false - run: rustup target add ${{ matrix.target }} - name: Build run: | if [ -n "${{ matrix.zig }}" ]; then cargo install cargo-zigbuild --locked cargo zigbuild --release -p tidy_cli --target ${{ matrix.target }} else cargo build --release -p tidy_cli --target ${{ matrix.target }} fi # The archive holds the executable alone, at its root, so that a # consumer reading `bin` from the packslip finds it where it says. - name: Package run: | mkdir -p dist out="target/${{ matrix.target }}/release" case "${{ matrix.target }}" in *windows*) archive="dist/tidy-${{ matrix.target }}.zip" 7z a "$archive" "./$out/tidy.exe" > /dev/null ;; *) archive="dist/tidy-${{ matrix.target }}.tar.gz" tar -czf "$archive" -C "$out" tidy ;; esac if command -v sha256sum > /dev/null; then sha256sum "$archive" | sed "s| .*/| |" > "$archive.sha256" else shasum -a 256 "$archive" | sed "s| .*/| |" > "$archive.sha256" fi - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: cli-${{ matrix.target }} path: dist/* if-no-files-found: error release: timeout-minutes: 15 name: release needs: cli runs-on: ubuntu-latest permissions: contents: write id-token: write attestations: write steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ inputs.tag || github.ref }} - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: pattern: cli-* path: dist merge-multiple: true - name: Publish the release env: GH_TOKEN: ${{ github.token }} TAG: ${{ inputs.tag || github.ref_name }} run: | if ! gh release view "$TAG" > /dev/null 2>&1; then gh release create "$TAG" --title "$TAG" --generate-notes fi gh release upload "$TAG" dist/* --clobber # Signs the archives and their digests with this workflow's identity, so # an installer can verify what it downloads instead of trusting a name. - uses: jdx/packslip@44e50e5f64551234b4a382d991bd7f7f7d021d06 # v1.11.3 with: artifacts: dist/*.tar.gz dist/*.zip bin: tidy tag: ${{ inputs.tag || github.ref_name }} build: timeout-minutes: 30 name: build ${{ matrix.target }} runs-on: ${{ matrix.os }} strategy: fail-fast: true matrix: include: - { os: macos-latest, target: aarch64-apple-darwin, test: true } - { os: macos-latest, target: x86_64-apple-darwin } - { os: ubuntu-latest, target: x86_64-unknown-linux-gnu, flags: --use-napi-cross, test: true, } - { os: ubuntu-latest, target: aarch64-unknown-linux-gnu, flags: --use-napi-cross, } - { os: ubuntu-latest, target: x86_64-unknown-linux-musl, flags: -x } - { os: ubuntu-latest, target: aarch64-unknown-linux-musl, flags: -x } - { os: windows-latest, target: x86_64-pc-windows-msvc, test: true } - { os: windows-latest, target: aarch64-pc-windows-msvc } defaults: run: shell: bash working-directory: crates/tidy_napi steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ inputs.tag || github.ref }} - uses: jdx/mise-action@f5be966e4a917d54244728e6a5fdcd1d93a35e6c # v5.2.6 with: cache: false - uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1 if: contains(matrix.target, 'musl') with: use-cache: false - run: rustup target add ${{ matrix.target }} - run: bun install --frozen-lockfile - run: bunx napi build --platform --release --esm --target ${{ matrix.target }} ${{ matrix.flags }} - run: bun test if: matrix.test - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: addon-${{ matrix.target }} path: crates/tidy_napi/tidyrs.*.node if-no-files-found: error - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 if: matrix.target == 'x86_64-unknown-linux-gnu' with: name: loader path: | crates/tidy_napi/index.js crates/tidy_napi/index.d.ts if-no-files-found: error publish: timeout-minutes: 15 needs: build runs-on: ubuntu-latest permissions: contents: read id-token: write defaults: run: working-directory: crates/tidy_napi steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: ref: ${{ inputs.tag || github.ref }} - uses: jdx/mise-action@f5be966e4a917d54244728e6a5fdcd1d93a35e6c # v5.2.6 with: cache: false - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: 24 registry-url: https://registry.npmjs.org - run: bun install --frozen-lockfile - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: pattern: addon-* path: crates/tidy_napi/artifacts merge-multiple: true - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: name: loader path: crates/tidy_napi - run: bunx napi create-npm-dirs - run: bunx napi artifacts --output-dir artifacts # npm authenticates from the job's OIDC token, so no long-lived secret. # Each platform package has its own trusted publisher, as tidyrs does. - run: bunx napi pre-publish -t npm --no-gh-release - run: npm publish