diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a060ddf..22b0d20 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,8 +7,28 @@ on: workflow_dispatch: inputs: tag: - description: "Tag to build and upload assets for (e.g. v0.6.5)" + description: "Tag (or branch) to build" required: true + run_notes: + description: "Generate release notes" + type: boolean + default: true + run_linux: + description: "Build Linux (x86_64 + aarch64 + musl)" + type: boolean + default: true + run_macos: + description: "Build macOS (x86_64 + aarch64)" + type: boolean + default: true + run_windows: + description: "Build Windows (MSVC + GNU)" + type: boolean + default: true + run_publish: + description: "Publish to crates.io" + type: boolean + default: false permissions: contents: write @@ -19,14 +39,12 @@ jobs: steps: - uses: actions/checkout@v4 with: - # При ручном запуске чекаутим нужный тег ref: ${{ github.event.inputs.tag || github.ref }} - name: Prepare Release Notes shell: bash run: | set -euo pipefail - # При ручном запуске берём версию из инпута, иначе из тега if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then tag="${{ github.event.inputs.tag }}" tag="${tag#v}" @@ -51,56 +69,19 @@ jobs: name: release-notes path: .github/release-notes.md - build: + # ── Linux ────────────────────────────────────────────────────────────────── + build-linux: + if: ${{ github.event_name == 'push' || github.event.inputs.run_linux == 'true' }} + needs: notes + runs-on: ubuntu-latest strategy: fail-fast: false matrix: include: - # ── Linux GNU ────────────────────────────────────────────────────── - - os: ubuntu-latest - target: x86_64-unknown-linux-gnu - - - os: ubuntu-latest - target: aarch64-unknown-linux-gnu - apt: gcc-aarch64-linux-gnu g++-aarch64-linux-gnu - env_cc: CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc - env_linker: CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc - - # ── Linux Musl ───────────────────────────────────────────────────── - - os: ubuntu-latest - target: x86_64-unknown-linux-musl - apt: musl-tools - env_cc: CC_x86_64_unknown_linux_musl=musl-gcc - env_linker: CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=musl-gcc - - - os: ubuntu-latest - target: aarch64-unknown-linux-musl - musl_cross: aarch64-linux-musl-cross - env_cc: CC_aarch64_unknown_linux_musl=aarch64-linux-musl-gcc - env_linker: CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER=aarch64-linux-musl-gcc - - # ── macOS ────────────────────────────────────────────────────────── - - os: macos-15-intel - target: x86_64-apple-darwin - - - os: macos-latest - target: aarch64-apple-darwin - - # ── Windows MSVC ─────────────────────────────────────────────────── - - os: windows-latest - target: x86_64-pc-windows-msvc - - - os: windows-latest - target: aarch64-pc-windows-msvc - - # ── Windows GNU ──────────────────────────────────────────────────── - - os: windows-latest - target: x86_64-pc-windows-gnu - - # gnullvm исключён: LLVM MinGW не предустановлен на GitHub Actions - - runs-on: ${{ matrix.os }} - needs: notes + - target: x86_64-unknown-linux-gnu + - target: aarch64-unknown-linux-gnu + - target: x86_64-unknown-linux-musl + - target: aarch64-unknown-linux-musl steps: - uses: actions/checkout@v4 with: @@ -112,63 +93,133 @@ jobs: name: release-notes path: .github - - name: Install cargo-zigbuild (Linux cross-compilation) - if: runner.os == 'Linux' + - name: Install cargo-zigbuild run: | pip install cargo-zigbuild echo "$HOME/.local/bin" >> $GITHUB_PATH - - name: Setup LLVM + MinGW (gnullvm) - if: contains(matrix.target, 'gnullvm') - shell: pwsh - run: | - choco install llvm mingw -y --no-progress - echo "C:\Program Files\LLVM\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - name: Setup Rust uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.target }} - name: Build - shell: bash run: | - if [ "${{ runner.os }}" = "Linux" ] && [ "${{ matrix.target }}" != "x86_64-unknown-linux-gnu" ]; then + if [ "${{ matrix.target }}" != "x86_64-unknown-linux-gnu" ]; then cargo zigbuild --release --target ${{ matrix.target }} else cargo build --release --target ${{ matrix.target }} fi - - name: Derive version string - shell: bash + - name: Derive version & asset name run: | - if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - RAW_TAG="${{ github.event.inputs.tag }}" - else - RAW_TAG="${GITHUB_REF_NAME}" - fi + RAW_TAG="${{ github.event.inputs.tag || github.ref_name }}" echo "RELEASE_TAG=${RAW_TAG}" >> "$GITHUB_ENV" echo "RELEASE_VERSION=${RAW_TAG#v}" >> "$GITHUB_ENV" + echo "ASSET_NAME=dcr-${{ matrix.target }}-${RAW_TAG#v}" >> "$GITHUB_ENV" - - name: Derive asset name (Unix) - if: runner.os != 'Windows' - shell: bash - run: | - echo "ASSET_NAME=dcr-${{ matrix.target }}-${RELEASE_VERSION}" >> "$GITHUB_ENV" - - - name: Derive asset name (Windows) - if: runner.os == 'Windows' - shell: pwsh - run: | - "ASSET_NAME=dcr-${{ matrix.target }}-$($env:RELEASE_VERSION).exe" >> $env:GITHUB_ENV - - - name: Prepare Artifact (Unix) - if: runner.os != 'Windows' - shell: bash + - name: Prepare Artifact run: cp target/${{ matrix.target }}/release/dcr "$ASSET_NAME" - - name: Prepare Artifact (Windows) - if: runner.os == 'Windows' + - name: Upload Release Asset + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ env.RELEASE_TAG }} + files: ${{ env.ASSET_NAME }} + body_path: .github/release-notes.md + prerelease: ${{ contains(env.RELEASE_TAG, '-') }} + + # ── macOS ────────────────────────────────────────────────────────────────── + build-macos: + if: ${{ github.event_name == 'push' || github.event.inputs.run_macos == 'true' }} + needs: notes + strategy: + fail-fast: false + matrix: + include: + - os: macos-15-intel + target: x86_64-apple-darwin + - os: macos-latest + target: aarch64-apple-darwin + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.tag || github.ref }} + + - name: Download Release Notes + uses: actions/download-artifact@v4 + with: + name: release-notes + path: .github + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - name: Build + run: cargo build --release --target ${{ matrix.target }} + + - name: Derive version & asset name + run: | + RAW_TAG="${{ github.event.inputs.tag || github.ref_name }}" + echo "RELEASE_TAG=${RAW_TAG}" >> "$GITHUB_ENV" + echo "RELEASE_VERSION=${RAW_TAG#v}" >> "$GITHUB_ENV" + echo "ASSET_NAME=dcr-${{ matrix.target }}-${RAW_TAG#v}" >> "$GITHUB_ENV" + + - name: Prepare Artifact + run: cp target/${{ matrix.target }}/release/dcr "$ASSET_NAME" + + - name: Upload Release Asset + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ env.RELEASE_TAG }} + files: ${{ env.ASSET_NAME }} + body_path: .github/release-notes.md + prerelease: ${{ contains(env.RELEASE_TAG, '-') }} + + # ── Windows ──────────────────────────────────────────────────────────────── + build-windows: + if: ${{ github.event_name == 'push' || github.event.inputs.run_windows == 'true' }} + needs: notes + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + include: + - target: x86_64-pc-windows-msvc + - target: aarch64-pc-windows-msvc + - target: x86_64-pc-windows-gnu + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.tag || github.ref }} + + - name: Download Release Notes + uses: actions/download-artifact@v4 + with: + name: release-notes + path: .github + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.target }} + + - name: Build + run: cargo build --release --target ${{ matrix.target }} + + - name: Derive version & asset name + shell: pwsh + run: | + $raw = "${{ github.event.inputs.tag || github.ref_name }}" + $ver = $raw -replace '^v', '' + "RELEASE_TAG=$raw" >> $env:GITHUB_ENV + "RELEASE_VERSION=$ver" >> $env:GITHUB_ENV + "ASSET_NAME=dcr-${{ matrix.target }}-${ver}.exe" >> $env:GITHUB_ENV + + - name: Prepare Artifact shell: pwsh run: Copy-Item "target/${{ matrix.target }}/release/dcr.exe" "$env:ASSET_NAME" @@ -178,4 +229,19 @@ jobs: tag_name: ${{ env.RELEASE_TAG }} files: ${{ env.ASSET_NAME }} body_path: .github/release-notes.md - prerelease: ${{ contains(env.RELEASE_TAG, '-') }} \ No newline at end of file + prerelease: ${{ contains(env.RELEASE_TAG, '-') }} + + # ── crates.io ────────────────────────────────────────────────────────────── + publish-crates: + if: ${{ (github.event_name == 'push' || github.event.inputs.run_publish == 'true') && !contains(github.event.inputs.tag || github.ref_name, '-') }} + needs: notes + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.tag || github.ref }} + + - uses: dtolnay/rust-toolchain@stable + + - name: Publish to crates.io + run: cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }} \ No newline at end of file