Skip to content

🤖 ci: gate CI jobs by changed paths#12

Merged
ThomasK33 merged 1 commit into
mainfrom
ci-actions-qjzq
Feb 9, 2026
Merged

🤖 ci: gate CI jobs by changed paths#12
ThomasK33 merged 1 commit into
mainfrom
ci-actions-qjzq

Conversation

@ThomasK33

Copy link
Copy Markdown
Member

Summary

Introduce path-aware CI orchestration so expensive Go jobs only run when Go-relevant files change.

Background

Docs-only pull requests were still triggering full Go lint/test/build workflows. This change preserves CI signal while reducing unnecessary job execution.

Implementation

  • Added a changes job using pinned dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36.
  • Added go, workflows, and publish outputs from that job.
  • Gated lint and test on needs.changes.outputs.go == 'true'.
  • Gated lint-actions on needs.changes.outputs.workflows == 'true'.
  • Updated publish-main to depend on changes and to allow upstream success or skipped outcomes while still requiring publish == 'true'.

Validation

  • make verify-vendor
  • make test
  • make build
  • go run github.com/rhysd/actionlint/cmd/actionlint@v1.7.10

Risks

Low. Scope is limited to workflow orchestration. Main risk is incorrect path classification causing a job to skip unexpectedly; mitigated by explicit filters and preserving required job dependency/result checks for publish.


📋 Implementation Plan

Plan: Option 2 — Per-job path filtering in CI

Context / Why

The current .github/workflows/ci.yaml runs Go-heavy jobs (lint, test) for every pull request, including docs-only changes (for example, markdown edits under .mux/ and AGENTS.md). The goal is to keep CI signal quality while avoiding unnecessary Go setup/lint/test/build work when no Go-relevant files changed.

Evidence

  • .github/workflows/ci.yaml currently has no paths/paths-ignore filters at trigger or job level.
  • lint and test always run on pull_request and push to main.
  • publish-main currently depends on [test, lint, lint-actions], so any job-level skipping logic must avoid accidentally blocking publish when dependencies are skipped by design.

These sources are sufficient to plan the workflow-only change because the optimization is isolated to CI orchestration in .github/workflows/ci.yaml.

Implementation details

  1. Add a changes classifier job in .github/workflows/ci.yaml

    • Insert a first job that computes file-change categories with dorny/paths-filter (SHA-pinned).
    • Emit outputs for at least:
      • go (Go source/build/vendor/tooling inputs)
      • workflows (.github/workflows/**)
      • publish (files that should trigger publish-main, usually superset of go plus container build files)
    jobs:
      changes:
        runs-on: ubuntu-latest
        outputs:
          go: ${{ steps.filter.outputs.go }}
          workflows: ${{ steps.filter.outputs.workflows }}
          publish: ${{ steps.filter.outputs.publish }}
        steps:
          - name: Checkout
            uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
            with:
              persist-credentials: false
    
          - name: Detect changed paths
            id: filter
            uses: dorny/paths-filter@<PINNED_SHA> # v3
            with:
              filters: |
                go:
                  - '**/*.go'
                  - 'go.mod'
                  - 'go.sum'
                  - 'vendor/**'
                  - 'Makefile'
                workflows:
                  - '.github/workflows/**'
                publish:
                  - '**/*.go'
                  - 'go.mod'
                  - 'go.sum'
                  - 'vendor/**'
                  - 'Dockerfile*'
                  - 'Dockerfile.goreleaser'
  2. Gate expensive jobs using needs: changes + if: guards

    • lint and test should run only when needs.changes.outputs.go == 'true'.
    • lint-actions should run only when needs.changes.outputs.workflows == 'true'.
    • Keep codex-comments behavior unchanged (PR-only, cheap, policy-oriented).
    lint:
      needs: changes
      if: needs.changes.outputs.go == 'true'
      ...
    
    test:
      needs: changes
      if: needs.changes.outputs.go == 'true'
      ...
    
    lint-actions:
      needs: changes
      if: needs.changes.outputs.workflows == 'true'
      ...
  3. Update publish-main so intentionally skipped dependencies do not block it

    • Keep existing push/main gating.
    • Add needs: [changes, test, lint, lint-actions].
    • Use an if: expression with always() and explicit dependency result checks (success or skipped) plus publish == 'true'.
    publish-main:
      needs: [changes, test, lint, lint-actions]
      if: |
        always() &&
        github.event_name == 'push' &&
        github.ref == 'refs/heads/main' &&
        needs.changes.outputs.publish == 'true' &&
        (needs.test.result == 'success' || needs.test.result == 'skipped') &&
        (needs.lint.result == 'success' || needs.lint.result == 'skipped') &&
        (needs.lint-actions.result == 'success' || needs.lint-actions.result == 'skipped')
      ...
  4. Validate behavior with targeted scenarios

    • Run go run github.com/rhysd/actionlint/cmd/actionlint@v1.7.10 locally after YAML edits.
    • Open/refresh a PR with markdown-only changes; confirm lint/test are skipped and required checks remain mergeable.
    • Open/refresh a PR with Go file changes; confirm lint/test execute.
    • Confirm push to main with docs-only diff does not publish image (publish == false), while code-related push still publishes.
Why this structure (brief)
  • Job-level filtering (instead of top-level paths-ignore) preserves visibility of all jobs/check names while avoiding unnecessary work.
  • A dedicated changes job centralizes path logic so future categories can be added in one place.
  • Explicit success || skipped checks avoid accidental publish blockage when upstream jobs are intentionally skipped.

Generated with mux • Model: openai:gpt-5.3-codex • Thinking: xhigh • Cost: $0.16

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

Please review the CI path-filtering workflow changes.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e9560070f2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/ci.yaml
Comment thread .github/workflows/ci.yaml
Add a changes-classifier job using dorny/paths-filter and gate lint/test/lint-actions by relevant file changes.

Update publish-main to tolerate intentionally skipped dependencies while still requiring success when jobs do run.

---

_Generated with [`mux`](https://github.com/coder/mux) • Model: `openai:gpt-5.3-codex` • Thinking: `xhigh` • Cost: `$0.16`_

<!-- mux-attribution: model=openai:gpt-5.3-codex thinking=xhigh costs=0.16 -->
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

Addressed the workflow feedback:

  • Added pull-requests: read permission for the changes job
  • Included .golangci.yml/.golangci.yaml in the go change filter

Please take another look.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. You're on a roll.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ThomasK33 ThomasK33 added this pull request to the merge queue Feb 9, 2026
Merged via the queue into main with commit ed06a78 Feb 9, 2026
6 checks passed
@ThomasK33 ThomasK33 deleted the ci-actions-qjzq branch February 9, 2026 13:36
@ThomasK33

Copy link
Copy Markdown
Member Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant