rtk-ai/rtk

Release pipeline should skip binary builds for non-code changes

Open

#189 建立於 2026年2月18日

在 GitHub 查看
 (1 留言) (0 反應) (0 負責人)Rust (48,085 star) (2,914 fork)batch import
P2-importanteffort-mediumenhancementgood first issue

描述

Problem

The release pipeline currently triggers full multi-platform binary builds for every release, even when no Rust source code changed. This wastes CI resources and pollutes the release history with identical binaries.

Example: v0.20.1 (2026-02-17)

PR #161 (fix: install to ~/.local/bin) changed only install.sh + README.mdzero Rust code changes. Yet it triggered:

  • 5 platform builds (macOS Intel/ARM, Linux Intel/ARM, Windows)
  • DEB package build
  • RPM package build
  • Homebrew formula update
  • Version bump in Cargo.toml + Cargo.lock

The resulting binaries are functionally identical to v0.20.0 (only the embedded version string differs).

Impact

On Feb 17 alone, 4 releases were created (v0.19.0 → v0.21.1). At ~35 CI minutes per release (7 build jobs), that's over 2 hours of CI time. At least one release (v0.20.1) was entirely unnecessary.

Root Cause

release-please determines version bumps based on conventional commit prefixes only (fix: → patch, feat: → minor). It has no awareness of which files changed. So fix: install to ~/.local/bin triggers a patch release even though no compiled code was affected.

The build-release job in release-please.yml runs unconditionally whenever release_created == 'true':

build-release:
  needs: release-please
  if: ${{ needs.release-please.outputs.release_created == 'true' }}
  uses: ./.github/workflows/release.yml

Proposed Solution

Add a source-code change detection step between release-please and the build job:

check-source-changes:
  name: Check if source code changed
  needs: release-please
  if: ${{ needs.release-please.outputs.release_created == 'true' }}
  runs-on: ubuntu-latest
  outputs:
    code_changed: ${{ steps.check.outputs.code_changed }}
  steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0
    - name: Check for Rust source changes since last release
      id: check
      run: |
        # Get the previous release tag
        CURRENT_TAG="${{ needs.release-please.outputs.tag_name }}"
        PREV_TAG=$(git tag --sort=-v:refname | grep -v "$CURRENT_TAG" | head -1)
        
        # Check if any Rust source files changed
        CHANGED=$(git diff --name-only "$PREV_TAG"..HEAD -- '*.rs' 'Cargo.toml' 'Cargo.lock' 'build.rs' | head -1)
        
        if [ -n "$CHANGED" ]; then
          echo "code_changed=true" >> $GITHUB_OUTPUT
          echo "Source code changed since $PREV_TAG"
        else
          echo "code_changed=false" >> $GITHUB_OUTPUT
          echo "No source code changes since $PREV_TAG — skipping binary build"
        fi

build-release:
  needs: [release-please, check-source-changes]
  if: ${{ needs.check-source-changes.outputs.code_changed == 'true' }}
  uses: ./.github/workflows/release.yml

This way:

  • Code changes (*.rs, Cargo.toml, build.rs) → full build + release artifacts
  • Non-code changes (README, install.sh, docs, CI config) → release-please still creates the version tag and changelog entry, but no binary build runs

Alternatives Considered

  1. Enforce commit prefix discipline (chore: / docs: for non-code changes) — fragile, relies on contributor discipline
  2. release-please path filtering — not natively supported in v4
  3. Separate release tracks (code vs docs) — over-engineered for this use case

Additional Improvement

Consider also gating the Homebrew formula update behind the same code_changed check, since there's no point updating the tap when binaries haven't changed.

貢獻者指南