rtk-ai/rtk

Release pipeline should skip binary builds for non-code changes

Open

#189 ouverte le 18 févr. 2026

Voir sur GitHub
 (1 commentaire) (0 réactions) (0 assignés)Rust (2 914 forks)batch import
P2-importantarea:cieffort-mediumenhancementgood first issuehelp wantedpriority:medium

Métriques du dépôt

Stars
 (48 085 stars)
Métriques de merge PR
 (Merge moyen 11j 1h) (45 PRs mergées en 30 j)

Description

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.

Guide contributeur