name: CLI Release on: workflow_dispatch: push: tags: - "v*.*.*" env: CARGO_TERM_COLOR: always CARGO_UNSTABLE_SPARSE_REGISTRY: "true" jobs: info: name: Gather info runs-on: ubuntu-latest outputs: cli_version: ${{ steps.version.outputs.cli_version }} release_notes: ${{ fromJSON(steps.notes.outputs.notes_json || 'null') }} announce: ${{ steps.announce.outputs.announce || '' }} steps: - uses: actions/checkout@v4 - name: Extract version id: version shell: bash run: | set -euxo pipefail version=$(grep -m1 -F 'version =' crates/cli/Cargo.toml | cut -d\" -f2) if [[ -z "$version" ]]; then echo "Error: no version :(" exit 1 fi echo "cli_version=$version" >> $GITHUB_OUTPUT - name: Extract release notes if: github.event.head_commit.message id: notes shell: bash env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_REPO: ${{ github.repository }} release_commit: ${{ github.event.head_commit.message }} run: | set -x set +eo pipefail if [[ -z "$release_commit" ]]; then echo "notes_json=null" >> $GITHUB_OUTPUT exit fi release_pr=$(head -n1 <<< "$release_commit" | grep -oP '(?<=[(]#)\d+(?=[)])') if [[ -z "$release_pr" ]]; then echo "notes_json=null" >> $GITHUB_OUTPUT exit fi gh \ pr --repo "$GITHUB_REPO" \ view "$release_pr" \ --json body \ --jq '"notes_json=\((.body | split("### Release notes")[1] // "") | tojson)"' \ >> $GITHUB_OUTPUT - name: Make a new announcement post id: announce if: endsWith(steps.version.outputs.cli_version, '.0') run: echo "announce=Announcements" >> $GITHUB_OUTPUT build: strategy: matrix: name: - linux-amd64-gnu - linux-amd64-musl - linux-i686-musl - linux-armhf-gnu - linux-arm64-gnu - linux-arm64-musl - linux-s390x-gnu - linux-ppc64le-gnu - mac-x86-64 - mac-arm64 - windows-x86-64 include: - name: linux-amd64-gnu os: ubuntu-latest target: x86_64-unknown-linux-gnu cross: false experimental: false - name: linux-amd64-musl os: ubuntu-latest target: x86_64-unknown-linux-musl cross: true experimental: false - name: linux-i686-musl os: ubuntu-latest target: i686-unknown-linux-musl cross: true experimental: true - name: linux-armhf-gnu os: ubuntu-latest target: armv7-unknown-linux-gnueabihf cross: true experimental: false - name: linux-arm64-gnu os: ubuntu-latest target: aarch64-unknown-linux-gnu cross: true experimental: false - name: linux-arm64-musl os: ubuntu-latest target: aarch64-unknown-linux-musl cross: true experimental: true - name: linux-s390x-gnu os: ubuntu-latest target: s390x-unknown-linux-gnu cross: true experimental: false - name: linux-ppc64le-gnu os: ubuntu-latest target: powerpc64le-unknown-linux-gnu cross: true experimental: false - name: mac-x86-64 os: macos-latest target: x86_64-apple-darwin cross: false experimental: false - name: mac-arm64 os: macos-11.0 target: aarch64-apple-darwin cross: true experimental: true - name: windows-x86-64 os: windows-latest target: x86_64-pc-windows-msvc cross: false experimental: false #- name: windows-arm64 # os: windows-latest # target: aarch64-pc-windows-msvc # cross: true # experimental: true name: Binaries for ${{ matrix.name }} needs: info runs-on: ${{ matrix.os }} continue-on-error: ${{ matrix.experimental }} env: version: ${{ needs.info.outputs.cli_version }} dst: watchexec-${{ needs.info.outputs.cli_version }}-${{ matrix.target }} steps: - uses: actions/checkout@v4 # https://github.com/actions/cache/issues/752 - if: ${{ runner.os == 'Windows' }} name: Use GNU tar shell: cmd run: | echo "Adding GNU tar to PATH" echo C:\Program Files\Git\usr\bin>>"%GITHUB_PATH%" - name: Configure caching uses: actions/cache@v4 with: path: | ~/.cargo/registry/index/ ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ key: ${{ runner.os }}-cargo-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }} restore-keys: | ${{ runner.os }}-cargo-${{ matrix.target }}- ${{ runner.os }}-cargo- - run: sudo apt update if: startsWith(matrix.os, 'ubuntu-') - name: Add musl tools run: sudo apt install -y musl musl-dev musl-tools if: endsWith(matrix.target, '-musl') - name: Add aarch-gnu tools run: sudo apt install -y gcc-aarch64-linux-gnu if: startsWith(matrix.target, 'aarch64-unknown-linux') - name: Add arm7hf-gnu tools run: sudo apt install -y gcc-arm-linux-gnueabihf if: startsWith(matrix.target, 'armv7-unknown-linux-gnueabihf') - name: Add s390x-gnu tools run: sudo apt install -y gcc-s390x-linux-gnu if: startsWith(matrix.target, 's390x-unknown-linux-gnu') - name: Add ppc64le-gnu tools run: sudo apt install -y gcc-powerpc64le-linux-gnu if: startsWith(matrix.target, 'powerpc64le-unknown-linux-gnu') - name: Install cargo-deb if: startsWith(matrix.name, 'linux-') uses: taiki-e/install-action@v2 with: tool: cargo-deb - name: Install cargo-generate-rpm if: startsWith(matrix.name, 'linux-') uses: taiki-e/install-action@v2 with: tool: cargo-generate-rpm - name: Configure toolchain run: | rustup toolchain install --profile minimal --no-self-update stable rustup default stable rustup target add ${{ matrix.target }} - name: Install cross if: matrix.cross uses: taiki-e/install-action@v2 with: tool: cross - name: Build (cargo) if: "!matrix.cross" run: cargo build --package watchexec-cli --release --locked --target ${{ matrix.target }} - name: Build (cross) if: matrix.cross run: cross build --package watchexec-cli --release --locked --target ${{ matrix.target }} - name: Make manpage run: cargo run -p watchexec-cli -- --manual > doc/watchexec.1 - name: Make completions run: bin/completions - name: Package shell: bash run: | set -euxo pipefail ext="" [[ "${{ matrix.name }}" == windows-* ]] && ext=".exe" bin="target/${{ matrix.target }}/release/watchexec${ext}" objcopy --compress-debug-sections "$bin" || true mkdir "$dst" mkdir -p "target/release" cp "$bin" "target/release/" # workaround for cargo-deb silliness with targets cp "$bin" "$dst/" cp -r crates/cli/README.md LICENSE completions doc/{logo.svg,watchexec.1{,.*}} "$dst/" - name: Archive (tar) if: '! startsWith(matrix.name, ''windows-'')' run: tar cavf "$dst.tar.xz" "$dst" - name: Archive (deb) if: startsWith(matrix.name, 'linux-') run: cargo deb -p watchexec-cli --no-build --no-strip --target ${{ matrix.target }} --output "$dst.deb" - name: Archive (rpm) if: startsWith(matrix.name, 'linux-') shell: bash run: | set -euxo pipefail shopt -s globstar cargo generate-rpm -p crates/cli --target "${{ matrix.target }}" --target-dir "target/${{ matrix.target }}" mv target/**/*.rpm "$dst.rpm" - name: Archive (zip) if: startsWith(matrix.name, 'windows-') shell: bash run: 7z a "$dst.zip" "$dst" - uses: actions/upload-artifact@v4 with: name: builds retention-days: 1 path: | watchexec-*.tar.xz watchexec-*.tar.zst watchexec-*.deb watchexec-*.rpm watchexec-*.zip upload: needs: [build, info] name: Checksum and publish runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install b3sum uses: taiki-e/install-action@v2 with: tool: b3sum - uses: actions/download-artifact@v4 with: name: builds - name: Dist manifest run: | jq -ncf .github/workflows/dist-manifest.jq \ --arg version "${{ needs.info.outputs.cli_version }}" \ --arg changelog "${{ needs.info.outputs.release_notes }}" \ --arg files "$(ls watchexec-*)" \ > dist-manifest.json - name: Bulk checksums run: | b3sum watchexec-* | tee B3SUMS sha512sum watchexec-* | tee SHA512SUMS sha256sum watchexec-* | tee SHA256SUMS - name: File checksums run: | for file in watchexec-*; do b3sum --no-names $file > "$file.b3" sha256sum $file | cut -d ' ' -f1 > "$file.sha256" sha512sum $file | cut -d ' ' -f1 > "$file.sha512" done - uses: softprops/action-gh-release@3198ee18f814cdf787321b4a32a26ddbf37acc52 with: tag_name: v${{ needs.info.outputs.cli_version }} name: CLI v${{ needs.info.outputs.cli_version }} body: ${{ needs.info.outputs.release_notes }} append_body: true discussion_category_name: ${{ needs.info.outputs.announce }} files: | dist-manifest.json watchexec-*.tar.xz watchexec-*.tar.zst watchexec-*.deb watchexec-*.rpm watchexec-*.zip *SUMS *.b3 *.sha* env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}