diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..8b2938b --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,94 @@ +name: CI + +on: + push: + branches: ['**'] + pull_request: + branches: ['**'] + +env: + CARGO_TERM_COLOR: always + RUST_BACKTRACE: 1 + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + with: + components: clippy + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: ~/.cargo/registry + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo index + uses: actions/cache@v4 + with: + path: ~/.cargo/git + key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo build + uses: actions/cache@v4 + with: + path: target + key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} + + - name: Run clippy + run: cargo clippy --all-targets --all-features -- -D warnings + + format: + name: Format Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt + + - name: Check formatting + run: cargo fmt --all -- --check + + test: + name: Test + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + rust: [stable] + steps: + - uses: actions/checkout@v4 + + - name: Setup Rust + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: ~/.cargo/registry + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo index + uses: actions/cache@v4 + with: + path: ~/.cargo/git + key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo build + uses: actions/cache@v4 + with: + path: target + key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} + + - name: Run tests + run: cargo test --verbose diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..da0c0c2 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,180 @@ +name: Release + +on: + push: + branches: + - master + +env: + CARGO_TERM_COLOR: always + +jobs: + semantic-release: + name: Semantic Release + runs-on: ubuntu-latest + outputs: + new_release_published: ${{ steps.semantic.outputs.new_release_published }} + new_release_version: ${{ steps.semantic.outputs.new_release_version }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 'lts/*' + + - name: Install semantic-release + run: | + npm install -g semantic-release@23 \ + @semantic-release/git@10 \ + @semantic-release/changelog@6 \ + @semantic-release/exec@6 + + - name: Create semantic-release config + run: | + cat > .releaserc.json << 'EOF' + { + "branches": ["master"], + "plugins": [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + "@semantic-release/changelog", + [ + "@semantic-release/exec", + { + "prepareCmd": "sed -i 's/^version = \".*\"/version = \"${nextRelease.version}\"/' Cargo.toml" + } + ], + [ + "@semantic-release/git", + { + "assets": ["CHANGELOG.md", "Cargo.toml"], + "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" + } + ], + [ + "@semantic-release/github", + { + "assets": [] + } + ] + ] + } + EOF + + - name: Run semantic-release + id: semantic + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: npx semantic-release + + build-binaries: + name: Build ${{ matrix.target }} + needs: semantic-release + if: needs.semantic-release.outputs.new_release_published == 'true' + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: ubuntu-latest + target: x86_64-unknown-linux-gnu + binary_name: soulseek-rs + tarball_name: soulseek-rs-linux-x86_64.tar.gz + - os: macos-latest + target: x86_64-apple-darwin + binary_name: soulseek-rs + tarball_name: soulseek-rs-macos-x86_64.tar.gz + - os: macos-latest + target: aarch64-apple-darwin + binary_name: soulseek-rs + tarball_name: soulseek-rs-macos-aarch64.tar.gz + - os: windows-latest + target: x86_64-pc-windows-msvc + binary_name: soulseek-rs.exe + tarball_name: soulseek-rs-windows-x86_64.zip + steps: + - uses: actions/checkout@v4 + with: + ref: master + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - name: Cache cargo registry + uses: actions/cache@v4 + with: + path: ~/.cargo/registry + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo index + uses: actions/cache@v4 + with: + path: ~/.cargo/git + key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} + + - name: Cache cargo build + uses: actions/cache@v4 + with: + path: target + key: ${{ runner.os }}-${{ matrix.target }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} + + - name: Build release binary + run: cargo build --release --target ${{ matrix.target }} + + - name: Strip binary (Linux) + if: matrix.os == 'ubuntu-latest' + run: strip target/${{ matrix.target }}/release/${{ matrix.binary_name }} + + - name: Strip binary (macOS) + if: matrix.os == 'macos-latest' + run: strip target/${{ matrix.target }}/release/${{ matrix.binary_name }} + + - name: Create tarball (Unix) + if: matrix.os != 'windows-latest' + shell: bash + run: | + cd target/${{ matrix.target }}/release + tar -czf ../../../${{ matrix.tarball_name }} ${{ matrix.binary_name }} + + - name: Create zip (Windows) + if: matrix.os == 'windows-latest' + shell: bash + run: | + cd target/${{ matrix.target }}/release + 7z a -tzip ../../../${{ matrix.tarball_name }} ${{ matrix.binary_name }} + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.tarball_name }} + path: ${{ matrix.tarball_name }} + + upload-release-assets: + name: Upload Release Assets + needs: [semantic-release, build-binaries] + runs-on: ubuntu-latest + steps: + - name: Download all artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Display structure of downloaded files + run: ls -R artifacts + + - name: Upload release assets + uses: softprops/action-gh-release@v1 + with: + tag_name: v${{ needs.semantic-release.outputs.new_release_version }} + files: | + artifacts/soulseek-rs-linux-x86_64.tar.gz/soulseek-rs-linux-x86_64.tar.gz + artifacts/soulseek-rs-macos-x86_64.tar.gz/soulseek-rs-macos-x86_64.tar.gz + artifacts/soulseek-rs-macos-aarch64.tar.gz/soulseek-rs-macos-aarch64.tar.gz + artifacts/soulseek-rs-windows-x86_64.zip/soulseek-rs-windows-x86_64.zip + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}