Release #28
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 | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| dry-run: | |
| description: 'Dry run (build only, skip publish)' | |
| type: boolean | |
| default: false | |
| permissions: {} | |
| jobs: | |
| version: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.read.outputs.VERSION }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Read version from Cargo.toml | |
| id: read | |
| run: | | |
| VERSION=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/') | |
| echo "VERSION=$VERSION" >> "$GITHUB_OUTPUT" | |
| echo "Release version: $VERSION" | |
| - name: Check tag does not exist | |
| run: | | |
| VERSION="${{ steps.read.outputs.VERSION }}" | |
| if git rev-parse "v${VERSION}" >/dev/null 2>&1; then | |
| echo "::error::Tag v${VERSION} already exists. Bump the version in a PR first." | |
| exit 1 | |
| fi | |
| - name: Check CHANGELOG.md has entry for version | |
| run: | | |
| VERSION="${{ steps.read.outputs.VERSION }}" | |
| if [ ! -f CHANGELOG.md ]; then | |
| echo "::error::CHANGELOG.md does not exist at the repository root." | |
| exit 1 | |
| fi | |
| # Accept either `## [X.Y.Z]` or `## X.Y.Z` headings, with an | |
| # optional trailing space (followed by `— DATE`) or end-of-line. | |
| if ! grep -qE "^## \[?${VERSION}\]?( |$)" CHANGELOG.md; then | |
| echo "::error::CHANGELOG.md is missing an entry for version ${VERSION}." | |
| echo "::error::Add a heading like \`## [${VERSION}] — $(date +%Y-%m-%d)\` describing the release before re-running." | |
| exit 1 | |
| fi | |
| build: | |
| needs: version | |
| strategy: | |
| matrix: | |
| include: | |
| - target: aarch64-apple-darwin | |
| runner: macos-14 | |
| archive: tar.gz | |
| build-tool: cargo | |
| - target: x86_64-apple-darwin | |
| runner: macos-14 | |
| archive: tar.gz | |
| build-tool: cargo | |
| - target: x86_64-unknown-linux-gnu | |
| runner: ubuntu-latest | |
| archive: tar.gz | |
| build-tool: cross | |
| - target: x86_64-unknown-linux-musl | |
| runner: ubuntu-latest | |
| archive: tar.gz | |
| build-tool: cross | |
| - target: aarch64-unknown-linux-gnu | |
| runner: ubuntu-latest | |
| archive: tar.gz | |
| build-tool: cross | |
| - target: aarch64-unknown-linux-musl | |
| runner: ubuntu-latest | |
| archive: tar.gz | |
| build-tool: cross | |
| - target: x86_64-pc-windows-msvc | |
| runner: windows-latest | |
| archive: zip | |
| build-tool: cargo | |
| - target: i686-pc-windows-msvc | |
| runner: windows-latest | |
| archive: zip | |
| build-tool: cargo | |
| - target: aarch64-pc-windows-msvc | |
| runner: windows-latest | |
| archive: zip | |
| build-tool: cargo | |
| - target: aarch64-linux-android | |
| runner: ubuntu-latest | |
| archive: tar.gz | |
| build-tool: cross | |
| - target: arm-unknown-linux-gnueabihf | |
| runner: ubuntu-latest | |
| archive: tar.gz | |
| build-tool: cross | |
| - target: arm-unknown-linux-musleabihf | |
| runner: ubuntu-latest | |
| archive: tar.gz | |
| build-tool: cross | |
| - target: i686-unknown-linux-gnu | |
| runner: ubuntu-latest | |
| archive: tar.gz | |
| build-tool: cross | |
| - target: i686-unknown-linux-musl | |
| runner: ubuntu-latest | |
| archive: tar.gz | |
| build-tool: cross | |
| runs-on: ${{ matrix.runner }} | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Install Rust | |
| # rustup is pre-installed on GitHub-hosted runners. `rustup show` | |
| # reads rust-toolchain.toml in the repo root, then installs the | |
| # pinned channel + listed components if missing. The dtolnay action | |
| # cannot auto-detect the channel when pinned by SHA (it normally | |
| # parses it from the ref name), so we go through rustup directly. | |
| run: | | |
| rustup show | |
| rustup target add ${{ matrix.target }} | |
| - name: Install cross | |
| if: matrix.build-tool == 'cross' | |
| run: cargo install --locked --version =0.2.5 cross | |
| - name: Build (cargo) | |
| if: matrix.build-tool == 'cargo' | |
| run: cargo build --release --target ${{ matrix.target }} | |
| - name: Build (cross) | |
| if: matrix.build-tool == 'cross' | |
| run: cross build --release --target ${{ matrix.target }} | |
| - name: Package (unix) | |
| if: matrix.archive == 'tar.gz' | |
| run: | | |
| cd target/${{ matrix.target }}/release | |
| tar czf ../../../socket-patch-${{ matrix.target }}.tar.gz socket-patch | |
| cd ../../.. | |
| - name: Package (windows) | |
| if: matrix.archive == 'zip' | |
| shell: pwsh | |
| run: | | |
| Compress-Archive -Path "target/${{ matrix.target }}/release/socket-patch.exe" -DestinationPath "socket-patch-${{ matrix.target }}.zip" | |
| - name: Upload artifact (tar.gz) | |
| if: matrix.archive == 'tar.gz' | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: socket-patch-${{ matrix.target }} | |
| path: socket-patch-${{ matrix.target }}.tar.gz | |
| - name: Upload artifact (zip) | |
| if: matrix.archive == 'zip' | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: socket-patch-${{ matrix.target }} | |
| path: socket-patch-${{ matrix.target }}.zip | |
| tag: | |
| needs: [version, build] | |
| if: ${{ !inputs.dry-run }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| - name: Create and push tag | |
| run: | | |
| TAG="v${{ needs.version.outputs.version }}" | |
| git tag "$TAG" | |
| git push origin "$TAG" | |
| github-release: | |
| needs: [version, build, tag] | |
| if: ${{ !inputs.dry-run }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: | |
| path: artifacts | |
| merge-multiple: true | |
| - name: Generate SHA256SUMS | |
| run: | | |
| cd artifacts | |
| # Hash every release artifact (tar.gz + zip) so install.sh can verify | |
| # the binary before extraction. Sorted output keeps the file stable. | |
| sha256sum *.tar.gz *.zip 2>/dev/null | sort > SHA256SUMS | |
| cat SHA256SUMS | |
| - name: Create GitHub Release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| TAG="v${{ needs.version.outputs.version }}" | |
| gh release create "$TAG" \ | |
| --repo "$GITHUB_REPOSITORY" \ | |
| --generate-notes \ | |
| artifacts/* | |
| cargo-publish: | |
| needs: [version, build, tag] | |
| if: ${{ !inputs.dry-run }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| id-token: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Install Rust | |
| # rustup is pre-installed on GitHub-hosted runners. `rustup show` | |
| # reads rust-toolchain.toml in the repo root, then installs the | |
| # pinned channel + listed components if missing. | |
| run: rustup show | |
| - name: Authenticate with crates.io | |
| id: crates-io-auth | |
| uses: rust-lang/crates-io-auth-action@b7e9a28eded4986ec6b1fa40eeee8f8f165559ec # v1.0.3 | |
| - name: Publish socket-patch-core | |
| run: cargo publish -p socket-patch-core | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ steps.crates-io-auth.outputs.token }} | |
| - name: Wait for crates.io index update | |
| run: sleep 30 | |
| - name: Copy README for CLI crate | |
| run: cp README.md crates/socket-patch-cli/README.md | |
| - name: Publish socket-patch-cli | |
| run: cargo publish -p socket-patch-cli | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ steps.crates-io-auth.outputs.token }} | |
| npm-publish: | |
| needs: [version, build, tag] | |
| if: ${{ !inputs.dry-run }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| id-token: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Configure git for HTTPS | |
| run: git config --global url."https://github.com/".insteadOf "ssh://git@github.com/" | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: | |
| path: artifacts | |
| merge-multiple: true | |
| - name: Setup Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: '22.22.1' | |
| registry-url: 'https://registry.npmjs.org' | |
| - name: Update npm for trusted publishing | |
| run: npm install -g npm@11.15.0 | |
| - name: Stage binaries into platform packages | |
| run: | | |
| # Unix platforms: extract binary into each platform package directory | |
| stage_unix() { | |
| local artifact="$1" pkg_dir="$2" | |
| tar xzf "artifacts/${artifact}.tar.gz" -C "${pkg_dir}/" | |
| } | |
| # Windows platforms: extract .exe into each platform package directory | |
| stage_win() { | |
| local artifact="$1" pkg_dir="$2" | |
| unzip -o "artifacts/${artifact}.zip" -d "${pkg_dir}/" | |
| } | |
| stage_unix socket-patch-aarch64-apple-darwin npm/socket-patch-darwin-arm64 | |
| stage_unix socket-patch-x86_64-apple-darwin npm/socket-patch-darwin-x64 | |
| stage_unix socket-patch-x86_64-unknown-linux-gnu npm/socket-patch-linux-x64-gnu | |
| stage_unix socket-patch-x86_64-unknown-linux-musl npm/socket-patch-linux-x64-musl | |
| stage_unix socket-patch-aarch64-unknown-linux-gnu npm/socket-patch-linux-arm64-gnu | |
| stage_unix socket-patch-aarch64-unknown-linux-musl npm/socket-patch-linux-arm64-musl | |
| stage_unix socket-patch-arm-unknown-linux-gnueabihf npm/socket-patch-linux-arm-gnu | |
| stage_unix socket-patch-arm-unknown-linux-musleabihf npm/socket-patch-linux-arm-musl | |
| stage_unix socket-patch-i686-unknown-linux-gnu npm/socket-patch-linux-ia32-gnu | |
| stage_unix socket-patch-i686-unknown-linux-musl npm/socket-patch-linux-ia32-musl | |
| stage_unix socket-patch-aarch64-linux-android npm/socket-patch-android-arm64 | |
| stage_win socket-patch-x86_64-pc-windows-msvc npm/socket-patch-win32-x64 | |
| stage_win socket-patch-i686-pc-windows-msvc npm/socket-patch-win32-ia32 | |
| stage_win socket-patch-aarch64-pc-windows-msvc npm/socket-patch-win32-arm64 | |
| - name: Publish platform packages | |
| run: | | |
| for pkg_dir in npm/socket-patch-*/; do | |
| echo "Publishing ${pkg_dir}..." | |
| npm publish "./${pkg_dir}" --provenance --access public || { | |
| if npm view "@socketsecurity/$(basename "$pkg_dir")@${{ needs.version.outputs.version }}" version >/dev/null 2>&1; then | |
| echo "Already published, skipping." | |
| else | |
| exit 1 | |
| fi | |
| } | |
| done | |
| - name: Wait for npm registry propagation | |
| run: sleep 30 | |
| - name: Copy README for npm package | |
| run: cp README.md npm/socket-patch/README.md | |
| - name: Publish main package | |
| run: | | |
| npm publish ./npm/socket-patch --provenance --access public || { | |
| if npm view "@socketsecurity/socket-patch@${{ needs.version.outputs.version }}" version >/dev/null 2>&1; then | |
| echo "Already published, skipping." | |
| else | |
| exit 1 | |
| fi | |
| } | |
| pypi-publish: | |
| needs: [version, build, tag] | |
| if: ${{ !inputs.dry-run }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| id-token: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: | |
| path: artifacts | |
| merge-multiple: true | |
| - name: Setup Python | |
| uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: '3.12.13' | |
| - name: Copy README for PyPI package | |
| run: cp README.md pypi/socket-patch/README.md | |
| - name: Build platform wheels | |
| run: | | |
| VERSION="${{ needs.version.outputs.version }}" | |
| python scripts/build-pypi-wheels.py --version "$VERSION" --artifacts artifacts --dist dist | |
| - name: Publish to PyPI | |
| uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 | |
| with: | |
| packages-dir: dist/ |