Skip to content

Add path filter to Auto-Release workflow to only trigger on significant file changes #282

@MariusStorhaug

Description

Describe the change

The Release.yml workflow (previously Auto-Release.yml) currently has no paths filter, meaning every PR merged to main triggers a release — even for changes to documentation, tests, media, or editor configuration. This creates unnecessary releases that provide no value to consumers of the reusable workflows.

All action repos (e.g., Build-PSModule, GitHub-Script, Publish-PSModule) already use a paths filter on their Release.yml workflow:

paths:
  - 'action.yml'
  - 'src/**'

The Process-PSModule repo should follow the same pattern, but with paths appropriate for a reusable workflow repository rather than an action repository. The workflow should also be renamed from Auto-Release.yml to Release.yml to align with the convention used across all action repos.

Problem Statement

Currently, every merged PR triggers a release, even when:

  • Only CI/CD configuration files are changed (e.g., internal workflow files)
  • Only repository metadata files are changed (e.g., README badges, CODEOWNERS)
  • Changes are made to unrelated parts of the repository (tests, media, editor config)
  • Whitespace-only or formatting-only changes occur in non-source files

This results in:

  • Version number inflation without meaningful changes for consumers
  • Unnecessary churn for users pinning to release tags
  • Confusion for users tracking workflow updates
  • Increased noise in release notifications

Analysis of the repository

The repo has the following structure:

Process-PSModule/
├── .github/
│   ├── workflows/                                # 20 workflow files (16 reusable + 4 internal)
│   │   ├── workflow.yml                          # Main entry point (reusable)
│   │   ├── Build-Module.yml                      # Reusable
│   │   ├── Build-Docs.yml                        # Reusable
│   │   ├── Build-Site.yml                        # Reusable
│   │   ├── Get-Settings.yml                      # Reusable
│   │   ├── Get-TestResults.yml                   # Reusable
│   │   ├── Get-CodeCoverage.yml                  # Reusable
│   │   ├── Lint-Repository.yml                   # Reusable
│   │   ├── Lint-SourceCode.yml                   # Reusable
│   │   ├── Test-SourceCode.yml                   # Reusable
│   │   ├── Test-Module.yml                       # Reusable
│   │   ├── Test-ModuleLocal.yml                  # Reusable
│   │   ├── BeforeAll-ModuleLocal.yml             # Reusable
│   │   ├── AfterAll-ModuleLocal.yml              # Reusable
│   │   ├── Publish-Module.yml                    # Reusable
│   │   ├── Publish-Site.yml                      # Reusable
│   │   ├── Release.yml                           # Internal: release pipeline
│   │   ├── Linter.yml                            # Internal: self-linting
│   │   ├── Workflow-Test-Default.yml             # Internal: test harness
│   │   └── Workflow-Test-WithManifest.yml        # Internal: test harness
│   ├── linters/                                  # Linter configs (internal only, NOT consumed by callers)
│   │   ├── .markdown-lint.yml
│   │   ├── .powershell-psscriptanalyzer.psd1
│   │   └── .textlintrc
│   ├── instructions/                             # Copilot instructions (not consumed by users)
│   ├── CODEOWNERS
│   └── dependabot.yml
├── tests/                                        # Test data repos
├── media/                                        # Media assets
├── README.md
├── LICENSE
├── .gitignore
├── .gitattributes
└── .vscode/

Clarification: .github/linters/** does NOT affect consumers

Important: The .github/linters/ files in this repository are not consumed by callers of the reusable workflow.

Reusable workflows run in the context of the calling repository. When Lint-Repository.yml runs:

  1. It performs actions/checkout without an explicit repository: parameter — so it checks out the caller's repo (e.g., PSModule/GitHub), not Process-PSModule.
  2. Super-linter then discovers linter configs from .github/linters/ in the checked-out (calling) repo.
  3. The .github/linters/ files in Process-PSModule are only consumed by its own internal Linter.yml workflow (self-linting).

This is confirmed by comparing the linter configs — e.g., PSModule/GitHub/.github/linters/ has 4 files (incl. .codespellrc) with different markdown-lint rules, while Process-PSModule/.github/linters/ has 3 files with its own rules. Each calling repo maintains its own linter configuration independently.

Proposed path filter

Files that SHOULD trigger releases (consumed by workflow callers):

  • .github/workflows/** — All reusable workflow definitions (16 files)

Files that SHOULD NOT trigger releases:

  • .github/workflows/Release.yml — Internal release pipeline
  • .github/workflows/Linter.yml — Internal self-linting
  • .github/workflows/Workflow-Test-* — Internal test harnesses
  • .github/linters/** — Linter configs (internal only, consumed by calling repos' own configs)
  • .github/instructions/** — Copilot instructions
  • .github/CODEOWNERS — GitHub ownership config
  • .github/dependabot.yml — Dependabot config
  • tests/** — Test data/repos
  • README.md — Documentation
  • LICENSE — License
  • media/** — Media assets
  • .gitignore / .gitattributes — Git configuration
  • .vscode/** — Editor settings

Version bump behavior

When a release IS triggered, the existing version bump behavior should remain as-is:

  • Patch label or default → Patch version bump
  • Minor label → Minor version bump
  • Major label → Major version bump

Edge cases

  • First release: If no previous release exists, any change should trigger a release
  • Force release: Consider supporting a mechanism to force a release via PR label (e.g., force-release) even when no significant files changed — useful for cases where a rebuild with identical workflow content is needed

Implementation

  1. Rename Auto-Release.yml to Release.yml to align with the naming convention used across all action repos.

  2. Align structure with the action repo Release.yml pattern (workflow name, run-name, job name, step names, permission comments).

  3. Add paths filter with negation patterns to include all workflow files while excluding internal workflows:

paths:
  - '.github/workflows/**'
  - '!.github/workflows/Release.yml'
  - '!.github/workflows/Linter.yml'
  - '!.github/workflows/Workflow-Test-*'
  1. Remove IncrementalPrerelease: false — use the default from Release-GHRepository action, consistent with action repos.

User scenarios

  1. Workflow file change — A PR modifies .github/workflows/Build-Module.yml → Release SHOULD be created ✅
  2. Internal workflow change — A PR only modifies .github/workflows/Linter.yml → NO release created ✅
  3. Linter config change — A PR only modifies .github/linters/.textlintrc → NO release created ✅
  4. README-only change — A PR only updates README.md → NO release created ✅
  5. Test data change — A PR only modifies files in tests/ → NO release created ✅
  6. Mixed change — A PR modifies both README.md and .github/workflows/workflow.yml → Release SHOULD be created ✅

Supersedes

Metadata

Metadata

Labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions