Release #90
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| permissions: | |
| contents: write | |
| on: | |
| workflow_run: | |
| workflows: ["CI"] | |
| types: | |
| - completed | |
| branches: [main] | |
| jobs: | |
| check_release: | |
| runs-on: ubuntu-latest | |
| if: github.event.workflow_run.conclusion == 'success' | |
| outputs: | |
| releaseExists: ${{ steps.check_release.outputs.releaseExists }} | |
| version: ${{ steps.check_release.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| # Build exactly the commit CI validated, not whatever main moved to. | |
| ref: ${{ github.event.workflow_run.head_sha }} | |
| - name: Check if release exists | |
| id: check_release | |
| uses: actions/github-script@v9 | |
| with: | |
| script: | | |
| const { owner, repo } = context.repo; | |
| const fs = require("fs"); | |
| const content = fs.readFileSync("Cargo.toml", "utf8"); | |
| const match = content.match(/^version = "(.*?)"/m); | |
| const version = match ? match[1] : ""; | |
| const tag = `v${version}`; | |
| console.log("Extracted version:", tag); | |
| core.setOutput("version", version); | |
| let releaseExists = false; | |
| try { | |
| await github.rest.repos.getReleaseByTag({ owner, repo, tag }); | |
| releaseExists = true; | |
| } catch (error) { | |
| if (error.status !== 404) throw error; | |
| } | |
| console.log("Release exists:", releaseExists); | |
| core.setOutput("releaseExists", releaseExists); | |
| extract_changelog: | |
| needs: check_release | |
| if: needs.check_release.outputs.releaseExists == 'false' | |
| runs-on: ubuntu-latest | |
| outputs: | |
| changelog: ${{ steps.changelog.outputs.changelog }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| # Build exactly the commit CI validated, not whatever main moved to. | |
| ref: ${{ github.event.workflow_run.head_sha }} | |
| - name: Extract changelog for version | |
| id: changelog | |
| run: | | |
| VERSION="${{ needs.check_release.outputs.version }}" | |
| # Extract content between [X.Y.Z] header and next ## header | |
| CHANGELOG=$(awk "/^## \\[${VERSION}\\]/{found=1; next} /^## \\[/{if(found) exit} found{print}" CHANGELOG.md) | |
| # If no versioned section found, try [Unreleased] | |
| if [ -z "$CHANGELOG" ]; then | |
| CHANGELOG=$(awk '/^## \[Unreleased\]/{found=1; next} /^## \[/{if(found) exit} found{print}' CHANGELOG.md) | |
| fi | |
| echo "changelog<<CHANGELOG_EOF" >> "$GITHUB_OUTPUT" | |
| echo "$CHANGELOG" >> "$GITHUB_OUTPUT" | |
| echo "CHANGELOG_EOF" >> "$GITHUB_OUTPUT" | |
| release: | |
| needs: [check_release, extract_changelog] | |
| if: needs.check_release.outputs.releaseExists == 'false' | |
| strategy: | |
| matrix: | |
| target: | |
| - x86_64-unknown-linux-gnu | |
| - i686-unknown-linux-gnu | |
| - aarch64-unknown-linux-gnu | |
| - armv7-unknown-linux-gnueabihf | |
| - arm-unknown-linux-gnueabihf | |
| - powerpc64le-unknown-linux-gnu | |
| - s390x-unknown-linux-gnu | |
| - aarch64-apple-darwin | |
| - x86_64-apple-darwin | |
| - x86_64-pc-windows-gnu | |
| runs-on: ${{ (matrix.target == 'aarch64-apple-darwin' || matrix.target == 'x86_64-apple-darwin') && 'macos-latest' || 'ubuntu-latest' }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| # Build exactly the commit CI validated, not whatever main moved to. | |
| ref: ${{ github.event.workflow_run.head_sha }} | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.target }} | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| key: release-${{ matrix.target }} | |
| - name: Install cross | |
| run: cargo install cross --git https://github.com/cross-rs/cross | |
| if: runner.os == 'Linux' | |
| - name: Install mingw-w64 | |
| run: sudo apt install -y mingw-w64 | |
| if: matrix.target == 'x86_64-pc-windows-gnu' | |
| - name: Build (cross) | |
| run: cross build --release --target ${{ matrix.target }} | |
| if: runner.os == 'Linux' | |
| - name: Build (native) | |
| run: cargo build --release --target ${{ matrix.target }} | |
| if: runner.os != 'Linux' | |
| - name: Package | |
| shell: bash | |
| run: | | |
| short_target=$(echo "${{ matrix.target }}" | sed 's/-unknown//') | |
| staging="killport-${short_target}" | |
| mkdir -p "$staging/completions" "$staging/man" | |
| # Binary | |
| if [[ "${{ matrix.target }}" == *"windows"* ]]; then | |
| cp "target/${{ matrix.target }}/release/killport.exe" "$staging/" | |
| else | |
| cp "target/${{ matrix.target }}/release/killport" "$staging/" | |
| fi | |
| # Shell completions and man page from build.rs output | |
| out_dir=$(find "target/${{ matrix.target }}/release/build/killport-"*/out -maxdepth 0 -type d 2>/dev/null | head -1) | |
| if [ -n "$out_dir" ]; then | |
| cp "$out_dir"/completions/* "$staging/completions/" 2>/dev/null || true | |
| cp "$out_dir"/man/* "$staging/man/" 2>/dev/null || true | |
| fi | |
| tar czvf "${staging}.tar.gz" "$staging" | |
| - name: Upload release assets | |
| uses: softprops/action-gh-release@v3 | |
| with: | |
| tag_name: v${{ needs.check_release.outputs.version }} | |
| name: Release v${{ needs.check_release.outputs.version }} | |
| target_commitish: ${{ github.event.workflow_run.head_sha }} | |
| body: ${{ needs.extract_changelog.outputs.changelog }} | |
| files: 'killport-*.tar.gz' | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| publish: | |
| needs: [check_release, release] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| # Build exactly the commit CI validated, not whatever main moved to. | |
| ref: ${{ github.event.workflow_run.head_sha }} | |
| - uses: dtolnay/rust-toolchain@stable | |
| - run: cargo publish --token ${{ secrets.CRATES_IO }} |