name: Release on: push: tags: - 'v*' permissions: contents: write jobs: build: strategy: matrix: include: - target: x86_64-apple-darwin os: macos-latest name: numa-macos-x86_64 - target: aarch64-apple-darwin os: macos-latest name: numa-macos-aarch64 - target: x86_64-unknown-linux-musl os: ubuntu-latest name: numa-linux-x86_64 - target: aarch64-unknown-linux-musl os: ubuntu-latest name: numa-linux-aarch64 - target: x86_64-pc-windows-msvc os: windows-latest name: numa-windows-x86_64 runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - name: Install Rust uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.target }} - name: Install musl tools (x86_64) if: matrix.target == 'x86_64-unknown-linux-musl' run: sudo apt-get update && sudo apt-get install -y musl-tools - name: Install cross (aarch64) if: matrix.target == 'aarch64-unknown-linux-musl' run: cargo install cross - name: Build (native) if: matrix.target != 'aarch64-unknown-linux-musl' run: cargo build --release --target ${{ matrix.target }} - name: Build (cross) if: matrix.target == 'aarch64-unknown-linux-musl' run: cross build --release --target ${{ matrix.target }} - name: Package (Unix) if: runner.os != 'Windows' run: | cd target/${{ matrix.target }}/release tar czf ../../../${{ matrix.name }}.tar.gz numa cd ../../.. sha256sum ${{ matrix.name }}.tar.gz > ${{ matrix.name }}.tar.gz.sha256 || shasum -a 256 ${{ matrix.name }}.tar.gz > ${{ matrix.name }}.tar.gz.sha256 - name: Package (Windows) if: runner.os == 'Windows' shell: pwsh run: | Compress-Archive -Path "target/${{ matrix.target }}/release/numa.exe" -DestinationPath "${{ matrix.name }}.zip" (Get-FileHash "${{ matrix.name }}.zip" -Algorithm SHA256).Hash.ToLower() + " ${{ matrix.name }}.zip" | Out-File "${{ matrix.name }}.zip.sha256" -Encoding ascii - name: Upload artifact uses: actions/upload-artifact@v4 with: name: ${{ matrix.name }} path: | ${{ matrix.name }}.tar.gz ${{ matrix.name }}.tar.gz.sha256 ${{ matrix.name }}.zip ${{ matrix.name }}.zip.sha256 publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install Rust uses: dtolnay/rust-toolchain@stable - name: Publish to crates.io run: cargo publish env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} release: needs: [build, publish] runs-on: ubuntu-latest steps: - uses: actions/download-artifact@v4 with: merge-multiple: true - name: Create Release uses: softprops/action-gh-release@v2 with: generate_release_notes: true files: | *.tar.gz *.zip *.sha256 update-homebrew: needs: release runs-on: ubuntu-latest steps: - name: Get version from tag id: version run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" - name: Download SHA256 files uses: actions/download-artifact@v4 with: merge-multiple: true - name: Extract checksums id: sha run: | echo "macos_arm=$(awk '{print $1}' numa-macos-aarch64.tar.gz.sha256)" >> "$GITHUB_OUTPUT" echo "macos_x86=$(awk '{print $1}' numa-macos-x86_64.tar.gz.sha256)" >> "$GITHUB_OUTPUT" echo "linux_arm=$(awk '{print $1}' numa-linux-aarch64.tar.gz.sha256)" >> "$GITHUB_OUTPUT" echo "linux_x86=$(awk '{print $1}' numa-linux-x86_64.tar.gz.sha256)" >> "$GITHUB_OUTPUT" - name: Update Homebrew formula uses: actions/github-script@v7 with: github-token: ${{ secrets.HOMEBREW_TAP_TOKEN }} script: | const version = '${{ steps.version.outputs.version }}'; const base = `https://github.com/razvandimescu/numa/releases/download/v${version}`; const formula = `class Numa < Formula desc "Portable DNS resolver with ad blocking, .numa local service proxy, and developer overrides" homepage "https://github.com/razvandimescu/numa" license "MIT" version "${version}" on_macos do if Hardware::CPU.arm? url "${base}/numa-macos-aarch64.tar.gz" sha256 "${{ steps.sha.outputs.macos_arm }}" else url "${base}/numa-macos-x86_64.tar.gz" sha256 "${{ steps.sha.outputs.macos_x86 }}" end end on_linux do if Hardware::CPU.arm? url "${base}/numa-linux-aarch64.tar.gz" sha256 "${{ steps.sha.outputs.linux_arm }}" else url "${base}/numa-linux-x86_64.tar.gz" sha256 "${{ steps.sha.outputs.linux_x86 }}" end end def install bin.install "numa" end def caveats <<~EOS Numa requires root to bind port 53: sudo numa # start the DNS server sudo numa install # set as system DNS sudo numa service start # run as persistent service Dashboard: http://localhost:5380 EOS end test do assert_match "numa", shell_output("#{bin}/numa --version") end end `.replace(/^ /gm, ''); const { data: existing } = await github.rest.repos.getContent({ owner: 'razvandimescu', repo: 'homebrew-tap', path: 'numa.rb', }); await github.rest.repos.createOrUpdateFileContents({ owner: 'razvandimescu', repo: 'homebrew-tap', path: 'numa.rb', message: `numa ${version}`, content: Buffer.from(formula).toString('base64'), sha: existing.sha, });