From 8f54c5afcd60f06b30faada319fb4b60c3608610 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 04:44:55 +0000 Subject: [PATCH 1/2] feat: add merge_group event support * Detect commit hashes from merge_group event * Apply suggestion from @masaru-iritani Co-authored-by: Masaru Iritani <25241373+masaru-iritani@users.noreply.github.com> * refactor: update PullRequest type usage in getChangedFilesFromApi and related functions * Run `npm run pack` --------- Co-authored-by: Sascha Bratton --- README.md | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index c344e98..2bbd705 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,11 @@ don't allow this because they don't work on a level of individual jobs or steps. - The `base` input parameter must not be the same as the branch that triggered the workflow - Changes are detected against the merge-base with the configured base branch or the default branch - Uses git commands to detect changes - repository must be already [checked out](https://github.com/actions/checkout) +- **[Merge queue](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue):** + - Workflow triggered by **[merge_group](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#merge_group)** + - The `base` and `ref` input parameters default to commit hashes from the event + unless explicitly specified. + - Uses git commands to detect changes - repository must be already [checked out](https://github.com/actions/checkout) - **Master, Release, or other long-lived branches:** - Workflow triggered by **[push](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#push)** event when `base` input parameter is the same as the branch that triggered the workflow: @@ -104,6 +109,8 @@ For more scenarios see [examples](#examples) section. # Branch, tag, or commit SHA against which the changes will be detected. # If it references the same branch it was pushed to, # changes are detected against the most recent commit before the push. + # If it is empty and action is triggered by merge_group event, + # the base commit in the event will be used. # Otherwise, it uses git merge-base to find the best common ancestor between # current branch (HEAD) and base. # When merge-base is found, it's used for change detection - only changes @@ -117,6 +124,8 @@ For more scenarios see [examples](#examples) section. # Git reference (e.g. branch name) from which the changes will be detected. # Useful when workflow can be triggered only on the default branch (e.g. repository_dispatch event) # but you want to get changes on a different branch. + # If this is empty and action is triggered by merge_group event, + # the head commit in the event will be used. # This option is ignored if action is triggered by pull_request event. # default: ${{ github.ref }} ref: @@ -154,14 +163,14 @@ For more scenarios see [examples](#examples) section. # Default: ${{ github.token }} token: '' - # Optional parameter to override the default behavior of file matching algorithm. + # Optional parameter to override the default behavior of file matching algorithm. # By default files that match at least one pattern defined by the filters will be included. # This parameter allows to override the "at least one pattern" behavior to make it so that - # all of the patterns have to match or otherwise the file is excluded. - # An example scenario where this is useful if you would like to match all - # .ts files in a sub-directory but not .md files. - # The filters below will match markdown files despite the exclusion syntax UNLESS - # you specify 'every' as the predicate-quantifier parameter. When you do that, + # all of the patterns have to match or otherwise the file is excluded. + # An example scenario where this is useful if you would like to match all + # .ts files in a sub-directory but not .md files. + # The filters below will match markdown files despite the exclusion syntax UNLESS + # you specify 'every' as the predicate-quantifier parameter. When you do that, # it will only match the .ts files in the subdirectory as expected. # # backend: @@ -317,6 +326,12 @@ on: branches: # PRs to the following branches will trigger the workflow - master - develop + # Optionally you can use the action in the merge queue + # if your repository enables the feature. + merge_group: + branches: + - master + - develop jobs: build: runs-on: ubuntu-latest @@ -557,4 +572,3 @@ jobs: ``` - From 81a12d9f149949fb66e86c91b2962d85f9299fe6 Mon Sep 17 00:00:00 2001 From: amanstep Date: Fri, 10 Apr 2026 10:36:36 +0530 Subject: [PATCH 2/2] chore: Cherry-picked changes from upstream for conflicting changes --- README.md | 48 ++++++++++++++++++------------------ dist/index.js | 66 ++++++++++++++++++++++++++++++------------------- src/main.ts | 68 ++++++++++++++++++++++++++++++++------------------- 3 files changed, 108 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index 2bbd705..b2b8329 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ don't allow this because they don't work on a level of individual jobs or steps. ## Example ```yaml -- uses: step-security/paths-filter@v3 +- uses: step-security/paths-filter@v4 id: changes with: filters: | @@ -79,7 +79,7 @@ For more scenarios see [examples](#examples) section. ## What's New -- New major release `v3` after update to Node 20 [Breaking change] +- New major release `v4` after update to Node 24 [Breaking change] - Add `ref` input parameter - Add `list-files: csv` format - Configure matrix job to run for each folder with changes using `changes` output @@ -89,7 +89,7 @@ For more scenarios see [examples](#examples) section. ## Usage ```yaml -- uses: step-security/paths-filter@v3 +- uses: step-security/paths-filter@v4 with: # Defines filters applied to detected changed files. # Each filter has a name and a list of rules. @@ -201,8 +201,8 @@ jobs: tests: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: step-security/paths-filter@v3 + - uses: actions/checkout@v6 + - uses: step-security/paths-filter@v4 id: filter with: filters: | @@ -246,7 +246,7 @@ jobs: frontend: ${{ steps.filter.outputs.frontend }} steps: # For pull requests it's not necessary to checkout the code - - uses: step-security/paths-filter@v3 + - uses: step-security/paths-filter@v4 id: filter with: filters: | @@ -261,7 +261,7 @@ jobs: if: ${{ needs.changes.outputs.backend == 'true' }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - ... # JOB to build and test frontend code @@ -270,7 +270,7 @@ jobs: if: ${{ needs.changes.outputs.frontend == 'true' }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - ... ``` @@ -292,7 +292,7 @@ jobs: packages: ${{ steps.filter.outputs.changes }} steps: # For pull requests it's not necessary to checkout the code - - uses: step-security/paths-filter@v3 + - uses: step-security/paths-filter@v4 id: filter with: filters: | @@ -309,7 +309,7 @@ jobs: package: ${{ fromJSON(needs.changes.outputs.packages) }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - ... ``` @@ -339,8 +339,8 @@ jobs: permissions: pull-requests: read steps: - - uses: actions/checkout@v4 - - uses: step-security/paths-filter@v3 + - uses: actions/checkout@v6 + - uses: step-security/paths-filter@v4 id: filter with: filters: ... # Configure your filters @@ -360,12 +360,12 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: # This may save additional git fetch roundtrip if # merge-base is found within latest 20 commits fetch-depth: 20 - - uses: step-security/paths-filter@v3 + - uses: step-security/paths-filter@v4 id: filter with: base: develop # Change detection against merge-base with this branch @@ -388,8 +388,8 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: step-security/paths-filter@v3 + - uses: actions/checkout@v6 + - uses: step-security/paths-filter@v4 id: filter with: # Use context to get the branch where commits were pushed. @@ -416,14 +416,14 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 # Some action that modifies files tracked by git (e.g. code linter) - uses: johndoe/some-action@v1 # Filter to detect which files were modified # Changes could be, for example, automatically committed - - uses: step-security/paths-filter@v3 + - uses: step-security/paths-filter@v4 id: filter with: base: HEAD @@ -438,7 +438,7 @@ jobs: Define filter rules in own file ```yaml -- uses: step-security/paths-filter@v3 +- uses: step-security/paths-filter@v4 id: filter with: # Path to file where filters are defined @@ -451,7 +451,7 @@ jobs: Use YAML anchors to reuse path expression(s) inside another rule ```yaml -- uses: step-security/paths-filter@v3 +- uses: step-security/paths-filter@v4 id: filter with: # &shared is YAML anchor, @@ -472,7 +472,7 @@ jobs: Consider if file was added, modified or deleted ```yaml -- uses: step-security/paths-filter@v3 +- uses: step-security/paths-filter@v4 id: filter with: # Changed file can be 'added', 'modified', or 'deleted'. @@ -498,7 +498,7 @@ jobs: Detect changes in folder only for some file extensions ```yaml -- uses: step-security/paths-filter@v3 +- uses: step-security/paths-filter@v4 id: filter with: # This makes it so that all the patterns have to match a file for it to be @@ -526,7 +526,7 @@ jobs: Passing list of modified files as command line args in Linux shell ```yaml -- uses: step-security/paths-filter@v3 +- uses: step-security/paths-filter@v4 id: filter with: # Enable listing of files matching each filter. @@ -552,7 +552,7 @@ jobs: Passing list of modified files as JSON array to another action ```yaml -- uses: step-security/paths-filter@v3 +- uses: step-security/paths-filter@v4 id: filter with: # Enable listing of files matching each filter. diff --git a/dist/index.js b/dist/index.js index 0c24361..c166525 100644 --- a/dist/index.js +++ b/dist/index.js @@ -635,33 +635,49 @@ async function getChangedFiles(token, base, ref, initialFetchDepth) { } return await git.getChangesOnHead(); } - const prEvents = ['pull_request', 'pull_request_review', 'pull_request_review_comment', 'pull_request_target']; - if (prEvents.includes(github.context.eventName)) { - if (ref) { - core.warning(`'ref' input parameter is ignored when 'base' is set to HEAD`); - } - if (base) { - core.warning(`'base' input parameter is ignored when action is triggered by pull request event`); - } - const pr = github.context.payload.pull_request; - if (token) { - return await getChangedFilesFromApi(token, pr); - } - if (github.context.eventName === 'pull_request_target') { - // pull_request_target is executed in context of base branch and GITHUB_SHA points to last commit in base branch - // Therefor it's not possible to look at changes in last commit - // At the same time we don't want to fetch any code from forked repository - throw new Error(`'token' input parameter is required if action is triggered by 'pull_request_target' event`); + switch (github.context.eventName) { + // To keep backward compatibility, commits in GitHub pull request event + // take precedence over manual inputs. + case 'pull_request': + case 'pull_request_review': + case 'pull_request_review_comment': + case 'pull_request_target': { + if (ref) { + core.warning(`'ref' input parameter is ignored when 'base' is set to HEAD`); + } + if (base) { + core.warning(`'base' input parameter is ignored when action is triggered by pull request event`); + } + const pr = github.context.payload.pull_request; + if (token) { + return await getChangedFilesFromApi(token, pr); + } + if (github.context.eventName === 'pull_request_target') { + // pull_request_target is executed in context of base branch and GITHUB_SHA points to last commit in base branch + // Therefore it's not possible to look at changes in last commit + // At the same time we don't want to fetch any code from forked repository + throw new Error(`'token' input parameter is required if action is triggered by 'pull_request_target' event`); + } + core.info('Github token is not available - changes will be detected using git diff'); + const baseSha = (_a = github.context.payload.pull_request) === null || _a === void 0 ? void 0 : _a.base.sha; + const defaultBranch = (_b = github.context.payload.repository) === null || _b === void 0 ? void 0 : _b.default_branch; + const currentRef = await git.getCurrentRef(); + return await git.getChanges(base || baseSha || defaultBranch, currentRef); + } + // To keep backward compatibility, manual inputs take precedence over + // commits in GitHub merge queue event. + case 'merge_group': { + const mergeGroup = github.context.payload; + if (!base) { + base = mergeGroup.merge_group.base_sha; + } + if (!ref) { + ref = mergeGroup.merge_group.head_sha; + } + break; } - core.info('Github token is not available - changes will be detected using git diff'); - const baseSha = (_a = github.context.payload.pull_request) === null || _a === void 0 ? void 0 : _a.base.sha; - const defaultBranch = (_b = github.context.payload.repository) === null || _b === void 0 ? void 0 : _b.default_branch; - const currentRef = await git.getCurrentRef(); - return await git.getChanges(base || baseSha || defaultBranch, currentRef); - } - else { - return getChangedFilesFromGit(base, ref, initialFetchDepth); } + return getChangedFilesFromGit(base, ref, initialFetchDepth); } async function getChangedFilesFromGit(base, head, initialFetchDepth) { var _a; diff --git a/src/main.ts b/src/main.ts index 2e636a3..60e26e5 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,7 +2,7 @@ import * as fs from 'fs' import * as core from '@actions/core' import * as github from '@actions/github' import {GetResponseDataTypeFromEndpointMethod} from '@octokit/types' -import {PushEvent, PullRequestEvent} from '@octokit/webhooks-types' +import {MergeGroupEvent, PullRequest, PushEvent} from '@octokit/webhooks-types' import axios, {isAxiosError} from 'axios' import { @@ -101,32 +101,50 @@ async function getChangedFiles(token: string, base: string, ref: string, initial return await git.getChangesOnHead() } - const prEvents = ['pull_request', 'pull_request_review', 'pull_request_review_comment', 'pull_request_target'] - if (prEvents.includes(github.context.eventName)) { - if (ref) { - core.warning(`'ref' input parameter is ignored when 'base' is set to HEAD`) - } - if (base) { - core.warning(`'base' input parameter is ignored when action is triggered by pull request event`) - } - const pr = github.context.payload.pull_request as PullRequestEvent - if (token) { - return await getChangedFilesFromApi(token, pr) + switch (github.context.eventName) { + // To keep backward compatibility, commits in GitHub pull request event + // take precedence over manual inputs. + case 'pull_request': + case 'pull_request_review': + case 'pull_request_review_comment': + case 'pull_request_target': { + if (ref) { + core.warning(`'ref' input parameter is ignored when 'base' is set to HEAD`) + } + if (base) { + core.warning(`'base' input parameter is ignored when action is triggered by pull request event`) + } + const pr = github.context.payload.pull_request as PullRequest + if (token) { + return await getChangedFilesFromApi(token, pr) + } + if (github.context.eventName === 'pull_request_target') { + // pull_request_target is executed in context of base branch and GITHUB_SHA points to last commit in base branch + // Therefore it's not possible to look at changes in last commit + // At the same time we don't want to fetch any code from forked repository + throw new Error(`'token' input parameter is required if action is triggered by 'pull_request_target' event`) + } + core.info('Github token is not available - changes will be detected using git diff') + const baseSha = github.context.payload.pull_request?.base.sha + const defaultBranch = github.context.payload.repository?.default_branch + const currentRef = await git.getCurrentRef() + return await git.getChanges(base || baseSha || defaultBranch, currentRef) } - if (github.context.eventName === 'pull_request_target') { - // pull_request_target is executed in context of base branch and GITHUB_SHA points to last commit in base branch - // Therefor it's not possible to look at changes in last commit - // At the same time we don't want to fetch any code from forked repository - throw new Error(`'token' input parameter is required if action is triggered by 'pull_request_target' event`) + // To keep backward compatibility, manual inputs take precedence over + // commits in GitHub merge queue event. + case 'merge_group': { + const mergeGroup = github.context.payload as MergeGroupEvent + if (!base) { + base = mergeGroup.merge_group.base_sha + } + if (!ref) { + ref = mergeGroup.merge_group.head_sha + } + break } - core.info('Github token is not available - changes will be detected using git diff') - const baseSha = github.context.payload.pull_request?.base.sha - const defaultBranch = github.context.payload.repository?.default_branch - const currentRef = await git.getCurrentRef() - return await git.getChanges(base || baseSha || defaultBranch, currentRef) - } else { - return getChangedFilesFromGit(base, ref, initialFetchDepth) } + + return getChangedFilesFromGit(base, ref, initialFetchDepth) } async function getChangedFilesFromGit(base: string, head: string, initialFetchDepth: number): Promise { @@ -192,7 +210,7 @@ async function getChangedFilesFromGit(base: string, head: string, initialFetchDe } // Uses github REST api to get list of files changed in PR -async function getChangedFilesFromApi(token: string, pullRequest: PullRequestEvent): Promise { +async function getChangedFilesFromApi(token: string, pullRequest: PullRequest): Promise { core.startGroup(`Fetching list of changed files for PR#${pullRequest.number} from Github API`) try { const client = github.getOctokit(token)