diff --git a/dist/helpers/check-merge-safety.js b/dist/helpers/check-merge-safety.js index 65854701..a94da3dd 100644 --- a/dist/helpers/check-merge-safety.js +++ b/dist/helpers/check-merge-safety.js @@ -46,11 +46,12 @@ class CheckMergeSafety extends HelperInputs { } var checkMergeSafety = async (inputs) => { warning("check-merge-safety is deprecated. Please use GitHub's native merge queue: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue"); - const isPrWorkflow = Boolean(context.issue.number); + const pullNumber = inputs.pull_number ? Number(inputs.pull_number) : context.issue.number; + const isPrWorkflow = Boolean(pullNumber); if (!isPrWorkflow) { return handlePushWorkflow(inputs); } - const { data: pullRequest } = await octokit.pulls.get({ pull_number: context.issue.number, ...context.repo }); + const { data: pullRequest } = await octokit.pulls.get({ pull_number: pullNumber, ...context.repo }); const { state, message } = await setMergeSafetyStatus(pullRequest, inputs); if (state === "failure") { setFailed(message); @@ -256,4 +257,4 @@ export { CheckMergeSafety }; -//# debugId=7687825B6B00F97364756E2164756E21 +//# debugId=B28E1D4A9818ED4864756E2164756E21 diff --git a/dist/helpers/check-merge-safety.js.map b/dist/helpers/check-merge-safety.js.map index 94a05c2c..155bee25 100644 --- a/dist/helpers/check-merge-safety.js.map +++ b/dist/helpers/check-merge-safety.js.map @@ -2,9 +2,9 @@ "version": 3, "sources": ["../src/helpers/check-merge-safety.ts"], "sourcesContent": [ - "/*\nCopyright 2021 Expedia, Inc.\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n https://www.apache.org/licenses/LICENSE-2.0\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { HelperInputs } from '../types/generated';\nimport { context as githubContext } from '@actions/github';\nimport { simpleGit } from 'simple-git';\nimport { octokit } from '../octokit';\nimport micromatch from 'micromatch';\nimport { GithubError, PullRequest } from '../types/github';\nimport { paginateAllOpenPullRequests } from '../utils/paginate-open-pull-requests';\nimport { map } from 'bluebird';\nimport { setCommitStatus } from './set-commit-status';\nimport * as core from '@actions/core';\n\nconst git = simpleGit();\n\nconst maxBranchNameLength = 50;\nconst COMMENT_PATHS_MARKER = '';\n\nconst getWorkflowRunUrl = () =>\n `${githubContext.serverUrl}/${githubContext.repo.owner}/${githubContext.repo.repo}/actions/runs/${githubContext.runId}`;\n\nexport class CheckMergeSafety extends HelperInputs {\n declare context?: string;\n declare paths?: string;\n declare ignore_globs?: string;\n declare override_filter_paths?: string;\n declare override_filter_globs?: string;\n declare match_comment_paths?: string;\n}\n\nexport const checkMergeSafety = async (inputs: CheckMergeSafety) => {\n core.warning(\n \"check-merge-safety is deprecated. Please use GitHub's native merge queue: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue\"\n );\n const isPrWorkflow = Boolean(githubContext.issue.number);\n if (!isPrWorkflow) {\n return handlePushWorkflow(inputs);\n }\n const { data: pullRequest } = await octokit.pulls.get({ pull_number: githubContext.issue.number, ...githubContext.repo });\n\n const { state, message } = await setMergeSafetyStatus(pullRequest, inputs);\n if (state === 'failure') {\n core.setFailed(message);\n }\n};\n\nconst setMergeSafetyStatus = async (pullRequest: PullRequest, { context = 'Merge Safety', ...inputs }: CheckMergeSafety) => {\n const { state, message } = await getMergeSafetyStateAndMessage(pullRequest, inputs);\n const hasExistingFailureStatus = await checkForExistingFailureStatus(pullRequest, context);\n if (hasExistingFailureStatus && state === 'failure') {\n const {\n head: {\n ref,\n user: { login: username }\n }\n } = pullRequest;\n const truncatedRef = ref.length > maxBranchNameLength ? `${ref.substring(0, maxBranchNameLength)}...` : ref;\n const truncatedBranchName = `${username}:${truncatedRef}`;\n core.info(`Found existing failure status for ${truncatedBranchName}, skipping setting new status`);\n } else {\n await setCommitStatus({\n sha: pullRequest.head.sha,\n state,\n context,\n description: message,\n target_url: getWorkflowRunUrl(),\n ...githubContext.repo\n });\n }\n\n return { state, message };\n};\n\nconst handlePushWorkflow = async (inputs: CheckMergeSafety) => {\n const pullRequests = await paginateAllOpenPullRequests();\n const filteredPullRequests = pullRequests.filter(({ base, draft }) => !draft && base.ref === base.repo.default_branch);\n await map(filteredPullRequests, pullRequest => setMergeSafetyStatus(pullRequest as PullRequest, inputs));\n};\n\nconst checkForExistingFailureStatus = async (pullRequest: PullRequest, context: string) => {\n const { data } = await octokit.repos.getCombinedStatusForRef({\n ...githubContext.repo,\n ref: pullRequest.head.sha\n });\n const existingContext = data.statuses.find(status => status.context === context);\n return existingContext?.state === 'failure';\n};\n\nconst fetchSha = async (repoUrl: string, sha: string) => {\n try {\n await git.fetch(repoUrl, sha, { '--depth': 1 });\n core.info(`Fetched ${sha} from ${repoUrl}`);\n } catch (err) {\n core.info(`Failed to fetch ${sha} from ${repoUrl}: ${(err as GithubError).message}`);\n throw new Error(`Failed to fetch ${sha} from ${repoUrl}: ${(err as GithubError).message}`);\n }\n};\n\nconst getDiffUsingGitCommand = async (repoUrl: string, baseSha: string, headSha: string): Promise => {\n // update local repo copy\n await fetchSha(repoUrl, baseSha);\n await fetchSha(repoUrl, headSha);\n\n try {\n const diff = await git.diff(['--name-only', baseSha, headSha]);\n return (diff ?? '').split('\\n').filter(Boolean);\n } catch (err) {\n core.error(`Failed to run local git diff for ${repoUrl}: ${(err as GithubError).message}`);\n throw new Error(`Failed to run local git diff for ${repoUrl}: ${(err as GithubError).message}`);\n }\n};\n\ntype DiffRefs = PullRequest['base' | 'head'];\nconst getDiff = async (compareBase: DiffRefs, compareHead: DiffRefs, basehead: string) => {\n let changedFileNames: string[] = [];\n try {\n const { data: { files: changedFiles } = {}, status } = await octokit.repos.compareCommitsWithBasehead({\n ...githubContext.repo,\n basehead\n });\n if (status > 400) {\n throw { status };\n }\n changedFileNames = changedFiles?.map(file => file.filename) ?? [];\n } catch (err) {\n core.info(`Failed to fetch diff: ${(err as GithubError).message} Status: ${(err as GithubError).status}`);\n\n // diff too large error\n if ((err as GithubError)?.status === 406 || (err as GithubError)?.message.includes('diff is taking too long to generate')) {\n core.info(`Attempting to generate diff using local git command`);\n if (compareBase.repo?.html_url) {\n changedFileNames = await getDiffUsingGitCommand(compareBase.repo?.html_url, compareBase.sha, compareHead.sha);\n } else {\n core.error(`Could not fetch repo url to run local git diff`);\n throw err;\n }\n } else {\n throw err;\n }\n }\n return changedFileNames;\n};\n\nconst getMergeSafetyStateAndMessage = async (\n pullRequest: PullRequest,\n { paths, ignore_globs, override_filter_paths, override_filter_globs, match_comment_paths }: CheckMergeSafety\n) => {\n const {\n base: {\n repo: {\n default_branch,\n owner: { login: baseOwner }\n }\n },\n head: {\n ref,\n user: { login: username }\n }\n } = pullRequest;\n\n const branchName = `${username}:${ref}`;\n const diffAgainstUserBranch = `${branchName}...${baseOwner}:${default_branch}`;\n let fileNamesWhichBranchIsBehindOn;\n try {\n fileNamesWhichBranchIsBehindOn = await getDiff(pullRequest.head, pullRequest.base, diffAgainstUserBranch);\n } catch (err) {\n const message = diffErrorMessage(diffAgainstUserBranch, (err as GithubError).message);\n core.error(message);\n return { state: 'failure', message } as const;\n }\n\n const truncatedRef = ref.length > maxBranchNameLength ? `${ref.substring(0, maxBranchNameLength)}...` : ref;\n const truncatedBranchName = `${username}:${truncatedRef}`;\n\n if (match_comment_paths === 'true') {\n const commentPaths = await getPathsFromComment(pullRequest.number);\n\n if (commentPaths.length) {\n core.info(`Found ${commentPaths.length} paths from PR comment`);\n\n const outdatedCommentPaths = commentPaths.filter(commentPath =>\n fileNamesWhichBranchIsBehindOn.some(file => file.startsWith(commentPath + '/') || file === commentPath)\n );\n\n if (outdatedCommentPaths.length) {\n core.error(buildErrorMessage(outdatedCommentPaths, 'comment paths', truncatedBranchName));\n return {\n state: 'failure',\n message: `Branch is behind on ${outdatedCommentPaths.length} path(s) from comment. Please update with ${default_branch}.`\n } as const;\n }\n } else {\n core.info('No paths found in PR comment, skipping comment path matching check');\n }\n }\n\n const globalFilesOutdatedOnBranch = override_filter_globs\n ? micromatch(fileNamesWhichBranchIsBehindOn, override_filter_globs.split(/[\\n,]/))\n : override_filter_paths\n ? fileNamesWhichBranchIsBehindOn.filter(changedFile => override_filter_paths.split(/[\\n,]/).includes(changedFile))\n : [];\n\n if (globalFilesOutdatedOnBranch.length) {\n core.error(buildErrorMessage(globalFilesOutdatedOnBranch, 'global files', truncatedBranchName));\n return {\n state: 'failure',\n message: `This branch has one or more outdated global files. Please update with ${default_branch}.`\n } as const;\n }\n\n const diffAgainstDefaultBranch = `${baseOwner}:${default_branch}...${branchName}`;\n let changedFileNames;\n try {\n changedFileNames = await getDiff(pullRequest.base, pullRequest.head, diffAgainstDefaultBranch);\n } catch (err) {\n const message = diffErrorMessage(diffAgainstDefaultBranch, (err as GithubError).message);\n core.error(message);\n return { state: 'failure', message } as const;\n }\n\n const changedFilesToIgnore = changedFileNames && ignore_globs ? micromatch(changedFileNames, ignore_globs.split(/[\\n,]/)) : [];\n const filteredFileNames = changedFileNames?.filter(file => !changedFilesToIgnore.includes(file));\n const allProjectDirectories = paths?.split(/[\\n,]/);\n\n const changedProjectsOutdatedOnBranch = allProjectDirectories?.filter(\n dir => fileNamesWhichBranchIsBehindOn.some(file => file.includes(dir)) && filteredFileNames?.some(file => file.includes(dir))\n );\n\n if (changedProjectsOutdatedOnBranch?.length) {\n core.error(buildErrorMessage(changedProjectsOutdatedOnBranch, 'projects', truncatedBranchName));\n return {\n state: 'failure',\n message: `This branch has one or more outdated projects. Please update with ${default_branch}.`\n } as const;\n }\n\n const safeMessage = buildSuccessMessage(truncatedBranchName);\n core.info(safeMessage);\n return {\n state: 'success',\n message: safeMessage\n } as const;\n};\n\nconst buildErrorMessage = (paths: string[], pathType: 'projects' | 'global files' | 'comment paths', branchName: string) =>\n `\nThe following ${pathType} are outdated on branch ${branchName}\n\n${paths.map(path => `* ${path}`).join('\\n')}\n`;\n\nconst diffErrorMessage = (basehead: string, message = '') =>\n `Failed to generate diff for ${basehead}. Please verify SHAs are valid and try again.${message ? `\\nError: ${message}` : ''}`;\n\nconst buildSuccessMessage = (branchName: string) => `Branch ${branchName} is safe to merge!`;\n\nconst getPathsFromComment = async (pullNumber: number): Promise => {\n const { data: comments } = await octokit.issues.listComments({\n ...githubContext.repo,\n issue_number: pullNumber\n });\n\n const pathsComment = comments.find(c => c.body?.includes(COMMENT_PATHS_MARKER));\n if (!pathsComment?.body) {\n return [];\n }\n\n const jsonMatch = pathsComment.body.match(/```json\\n([\\s\\S]*?)\\n```/);\n if (!jsonMatch?.[1]) {\n return [];\n }\n\n try {\n const parsed: unknown = JSON.parse(jsonMatch[1]);\n if (Array.isArray(parsed) && parsed.every(item => typeof item === 'string')) {\n return parsed;\n }\n return [];\n } catch {\n core.warning(`Failed to parse paths from PR #${pullNumber} comment`);\n return [];\n }\n};\n" + "/*\nCopyright 2021 Expedia, Inc.\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n https://www.apache.org/licenses/LICENSE-2.0\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { HelperInputs } from '../types/generated';\nimport { context as githubContext } from '@actions/github';\nimport { simpleGit } from 'simple-git';\nimport { octokit } from '../octokit';\nimport micromatch from 'micromatch';\nimport { GithubError, PullRequest } from '../types/github';\nimport { paginateAllOpenPullRequests } from '../utils/paginate-open-pull-requests';\nimport { map } from 'bluebird';\nimport { setCommitStatus } from './set-commit-status';\nimport * as core from '@actions/core';\n\nconst git = simpleGit();\n\nconst maxBranchNameLength = 50;\nconst COMMENT_PATHS_MARKER = '';\n\nconst getWorkflowRunUrl = () =>\n `${githubContext.serverUrl}/${githubContext.repo.owner}/${githubContext.repo.repo}/actions/runs/${githubContext.runId}`;\n\nexport class CheckMergeSafety extends HelperInputs {\n declare context?: string;\n declare paths?: string;\n declare ignore_globs?: string;\n declare override_filter_paths?: string;\n declare override_filter_globs?: string;\n declare match_comment_paths?: string;\n declare pull_number?: string;\n}\n\nexport const checkMergeSafety = async (inputs: CheckMergeSafety) => {\n core.warning(\n \"check-merge-safety is deprecated. Please use GitHub's native merge queue: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue\"\n );\n\n const pullNumber = inputs.pull_number ? Number(inputs.pull_number) : githubContext.issue.number;\n const isPrWorkflow = Boolean(pullNumber);\n\n if (!isPrWorkflow) {\n return handlePushWorkflow(inputs);\n }\n const { data: pullRequest } = await octokit.pulls.get({ pull_number: pullNumber, ...githubContext.repo });\n\n const { state, message } = await setMergeSafetyStatus(pullRequest, inputs);\n if (state === 'failure') {\n core.setFailed(message);\n }\n};\n\nconst setMergeSafetyStatus = async (pullRequest: PullRequest, { context = 'Merge Safety', ...inputs }: CheckMergeSafety) => {\n const { state, message } = await getMergeSafetyStateAndMessage(pullRequest, inputs);\n const hasExistingFailureStatus = await checkForExistingFailureStatus(pullRequest, context);\n if (hasExistingFailureStatus && state === 'failure') {\n const {\n head: {\n ref,\n user: { login: username }\n }\n } = pullRequest;\n const truncatedRef = ref.length > maxBranchNameLength ? `${ref.substring(0, maxBranchNameLength)}...` : ref;\n const truncatedBranchName = `${username}:${truncatedRef}`;\n core.info(`Found existing failure status for ${truncatedBranchName}, skipping setting new status`);\n } else {\n await setCommitStatus({\n sha: pullRequest.head.sha,\n state,\n context,\n description: message,\n target_url: getWorkflowRunUrl(),\n ...githubContext.repo\n });\n }\n\n return { state, message };\n};\n\nconst handlePushWorkflow = async (inputs: CheckMergeSafety) => {\n const pullRequests = await paginateAllOpenPullRequests();\n const filteredPullRequests = pullRequests.filter(({ base, draft }) => !draft && base.ref === base.repo.default_branch);\n await map(filteredPullRequests, pullRequest => setMergeSafetyStatus(pullRequest as PullRequest, inputs));\n};\n\nconst checkForExistingFailureStatus = async (pullRequest: PullRequest, context: string) => {\n const { data } = await octokit.repos.getCombinedStatusForRef({\n ...githubContext.repo,\n ref: pullRequest.head.sha\n });\n const existingContext = data.statuses.find(status => status.context === context);\n return existingContext?.state === 'failure';\n};\n\nconst fetchSha = async (repoUrl: string, sha: string) => {\n try {\n await git.fetch(repoUrl, sha, { '--depth': 1 });\n core.info(`Fetched ${sha} from ${repoUrl}`);\n } catch (err) {\n core.info(`Failed to fetch ${sha} from ${repoUrl}: ${(err as GithubError).message}`);\n throw new Error(`Failed to fetch ${sha} from ${repoUrl}: ${(err as GithubError).message}`);\n }\n};\n\nconst getDiffUsingGitCommand = async (repoUrl: string, baseSha: string, headSha: string): Promise => {\n // update local repo copy\n await fetchSha(repoUrl, baseSha);\n await fetchSha(repoUrl, headSha);\n\n try {\n const diff = await git.diff(['--name-only', baseSha, headSha]);\n return (diff ?? '').split('\\n').filter(Boolean);\n } catch (err) {\n core.error(`Failed to run local git diff for ${repoUrl}: ${(err as GithubError).message}`);\n throw new Error(`Failed to run local git diff for ${repoUrl}: ${(err as GithubError).message}`);\n }\n};\n\ntype DiffRefs = PullRequest['base' | 'head'];\nconst getDiff = async (compareBase: DiffRefs, compareHead: DiffRefs, basehead: string) => {\n let changedFileNames: string[] = [];\n try {\n const { data: { files: changedFiles } = {}, status } = await octokit.repos.compareCommitsWithBasehead({\n ...githubContext.repo,\n basehead\n });\n if (status > 400) {\n throw { status };\n }\n changedFileNames = changedFiles?.map(file => file.filename) ?? [];\n } catch (err) {\n core.info(`Failed to fetch diff: ${(err as GithubError).message} Status: ${(err as GithubError).status}`);\n\n // diff too large error\n if ((err as GithubError)?.status === 406 || (err as GithubError)?.message.includes('diff is taking too long to generate')) {\n core.info(`Attempting to generate diff using local git command`);\n if (compareBase.repo?.html_url) {\n changedFileNames = await getDiffUsingGitCommand(compareBase.repo?.html_url, compareBase.sha, compareHead.sha);\n } else {\n core.error(`Could not fetch repo url to run local git diff`);\n throw err;\n }\n } else {\n throw err;\n }\n }\n return changedFileNames;\n};\n\nconst getMergeSafetyStateAndMessage = async (\n pullRequest: PullRequest,\n { paths, ignore_globs, override_filter_paths, override_filter_globs, match_comment_paths }: CheckMergeSafety\n) => {\n const {\n base: {\n repo: {\n default_branch,\n owner: { login: baseOwner }\n }\n },\n head: {\n ref,\n user: { login: username }\n }\n } = pullRequest;\n\n const branchName = `${username}:${ref}`;\n const diffAgainstUserBranch = `${branchName}...${baseOwner}:${default_branch}`;\n let fileNamesWhichBranchIsBehindOn;\n try {\n fileNamesWhichBranchIsBehindOn = await getDiff(pullRequest.head, pullRequest.base, diffAgainstUserBranch);\n } catch (err) {\n const message = diffErrorMessage(diffAgainstUserBranch, (err as GithubError).message);\n core.error(message);\n return { state: 'failure', message } as const;\n }\n\n const truncatedRef = ref.length > maxBranchNameLength ? `${ref.substring(0, maxBranchNameLength)}...` : ref;\n const truncatedBranchName = `${username}:${truncatedRef}`;\n\n if (match_comment_paths === 'true') {\n const commentPaths = await getPathsFromComment(pullRequest.number);\n\n if (commentPaths.length) {\n core.info(`Found ${commentPaths.length} paths from PR comment`);\n\n const outdatedCommentPaths = commentPaths.filter(commentPath =>\n fileNamesWhichBranchIsBehindOn.some(file => file.startsWith(commentPath + '/') || file === commentPath)\n );\n\n if (outdatedCommentPaths.length) {\n core.error(buildErrorMessage(outdatedCommentPaths, 'comment paths', truncatedBranchName));\n return {\n state: 'failure',\n message: `Branch is behind on ${outdatedCommentPaths.length} path(s) from comment. Please update with ${default_branch}.`\n } as const;\n }\n } else {\n core.info('No paths found in PR comment, skipping comment path matching check');\n }\n }\n\n const globalFilesOutdatedOnBranch = override_filter_globs\n ? micromatch(fileNamesWhichBranchIsBehindOn, override_filter_globs.split(/[\\n,]/))\n : override_filter_paths\n ? fileNamesWhichBranchIsBehindOn.filter(changedFile => override_filter_paths.split(/[\\n,]/).includes(changedFile))\n : [];\n\n if (globalFilesOutdatedOnBranch.length) {\n core.error(buildErrorMessage(globalFilesOutdatedOnBranch, 'global files', truncatedBranchName));\n return {\n state: 'failure',\n message: `This branch has one or more outdated global files. Please update with ${default_branch}.`\n } as const;\n }\n\n const diffAgainstDefaultBranch = `${baseOwner}:${default_branch}...${branchName}`;\n let changedFileNames;\n try {\n changedFileNames = await getDiff(pullRequest.base, pullRequest.head, diffAgainstDefaultBranch);\n } catch (err) {\n const message = diffErrorMessage(diffAgainstDefaultBranch, (err as GithubError).message);\n core.error(message);\n return { state: 'failure', message } as const;\n }\n\n const changedFilesToIgnore = changedFileNames && ignore_globs ? micromatch(changedFileNames, ignore_globs.split(/[\\n,]/)) : [];\n const filteredFileNames = changedFileNames?.filter(file => !changedFilesToIgnore.includes(file));\n const allProjectDirectories = paths?.split(/[\\n,]/);\n\n const changedProjectsOutdatedOnBranch = allProjectDirectories?.filter(\n dir => fileNamesWhichBranchIsBehindOn.some(file => file.includes(dir)) && filteredFileNames?.some(file => file.includes(dir))\n );\n\n if (changedProjectsOutdatedOnBranch?.length) {\n core.error(buildErrorMessage(changedProjectsOutdatedOnBranch, 'projects', truncatedBranchName));\n return {\n state: 'failure',\n message: `This branch has one or more outdated projects. Please update with ${default_branch}.`\n } as const;\n }\n\n const safeMessage = buildSuccessMessage(truncatedBranchName);\n core.info(safeMessage);\n return {\n state: 'success',\n message: safeMessage\n } as const;\n};\n\nconst buildErrorMessage = (paths: string[], pathType: 'projects' | 'global files' | 'comment paths', branchName: string) =>\n `\nThe following ${pathType} are outdated on branch ${branchName}\n\n${paths.map(path => `* ${path}`).join('\\n')}\n`;\n\nconst diffErrorMessage = (basehead: string, message = '') =>\n `Failed to generate diff for ${basehead}. Please verify SHAs are valid and try again.${message ? `\\nError: ${message}` : ''}`;\n\nconst buildSuccessMessage = (branchName: string) => `Branch ${branchName} is safe to merge!`;\n\nconst getPathsFromComment = async (pullNumber: number): Promise => {\n const { data: comments } = await octokit.issues.listComments({\n ...githubContext.repo,\n issue_number: pullNumber\n });\n\n const pathsComment = comments.find(c => c.body?.includes(COMMENT_PATHS_MARKER));\n if (!pathsComment?.body) {\n return [];\n }\n\n const jsonMatch = pathsComment.body.match(/```json\\n([\\s\\S]*?)\\n```/);\n if (!jsonMatch?.[1]) {\n return [];\n }\n\n try {\n const parsed: unknown = JSON.parse(jsonMatch[1]);\n if (Array.isArray(parsed) && parsed.every(item => typeof item === 'string')) {\n return parsed;\n }\n return [];\n } catch {\n core.warning(`Failed to parse paths from PR #${pullNumber} comment`);\n return [];\n }\n};\n" ], - "mappings": "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", - "debugId": "7687825B6B00F97364756E2164756E21", + "mappings": "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", + "debugId": "B28E1D4A9818ED4864756E2164756E21", "names": [] } \ No newline at end of file diff --git a/dist/helpers/check-pr-title.js b/dist/helpers/check-pr-title.js index 82614573..d5ffab49 100644 --- a/dist/helpers/check-pr-title.js +++ b/dist/helpers/check-pr-title.js @@ -19,12 +19,13 @@ import"../main-wckvcay0.js"; // src/helpers/check-pr-title.ts class CheckPrTitle extends HelperInputs { } -var checkPrTitle = async ({ pattern = DEFAULT_PR_TITLE_REGEX }) => { +var checkPrTitle = async ({ pattern = DEFAULT_PR_TITLE_REGEX, pull_number }) => { const regex = new RegExp(pattern); + const pullNumber = pull_number ? Number(pull_number) : context.issue.number; const { data: { title } } = await octokit.pulls.get({ - pull_number: context.issue.number, + pull_number: pullNumber, ...context.repo }); if (regex.test(title)) { @@ -38,4 +39,4 @@ export { CheckPrTitle }; -//# debugId=C2025280B7E6F40964756E2164756E21 +//# debugId=9A54DF641B4B9ABB64756E2164756E21 diff --git a/dist/helpers/check-pr-title.js.map b/dist/helpers/check-pr-title.js.map index e40bb331..53a17b82 100644 --- a/dist/helpers/check-pr-title.js.map +++ b/dist/helpers/check-pr-title.js.map @@ -2,9 +2,9 @@ "version": 3, "sources": ["../src/helpers/check-pr-title.ts"], "sourcesContent": [ - "/*\nCopyright 2021 Expedia, Inc.\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n https://www.apache.org/licenses/LICENSE-2.0\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { DEFAULT_PR_TITLE_REGEX } from '../constants';\nimport { HelperInputs } from '../types/generated';\nimport { context } from '@actions/github';\nimport { octokit } from '../octokit';\nimport { setFailed } from '@actions/core';\n\nexport class CheckPrTitle extends HelperInputs {\n declare pattern?: string;\n}\n\nexport const checkPrTitle = async ({ pattern = DEFAULT_PR_TITLE_REGEX }: CheckPrTitle) => {\n const regex = new RegExp(pattern);\n const {\n data: { title }\n } = await octokit.pulls.get({\n pull_number: context.issue.number,\n ...context.repo\n });\n if (regex.test(title)) {\n return true;\n }\n setFailed(`Pull request title does not meet requirements. The title must match the following regex: ${pattern}`);\n return false;\n};\n" + "/*\nCopyright 2021 Expedia, Inc.\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n https://www.apache.org/licenses/LICENSE-2.0\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { DEFAULT_PR_TITLE_REGEX } from '../constants';\nimport { HelperInputs } from '../types/generated';\nimport { context } from '@actions/github';\nimport { octokit } from '../octokit';\nimport { setFailed } from '@actions/core';\n\nexport class CheckPrTitle extends HelperInputs {\n declare pattern?: string;\n declare pull_number?: string;\n}\n\nexport const checkPrTitle = async ({ pattern = DEFAULT_PR_TITLE_REGEX, pull_number }: CheckPrTitle) => {\n const regex = new RegExp(pattern);\n const pullNumber = pull_number ? Number(pull_number) : context.issue.number;\n\n const {\n data: { title }\n } = await octokit.pulls.get({\n pull_number: pullNumber,\n ...context.repo\n });\n\n if (regex.test(title)) {\n return true;\n }\n\n setFailed(`Pull request title does not meet requirements. The title must match the following regex: ${pattern}`);\n\n return false;\n};\n" ], - "mappings": ";;;;;;;;;;;;;;;;;;;AAmBO,MAAM,qBAAqB,aAAa;AAE/C;AAEO,IAAM,eAAe,SAAS,UAAU,6BAA2C;AAAA,EACxF,MAAM,QAAQ,IAAI,OAAO,OAAO;AAAA,EAChC;AAAA,IACE,QAAQ;AAAA,MACN,MAAM,QAAQ,MAAM,IAAI;AAAA,IAC1B,aAAa,QAAQ,MAAM;AAAA,OACxB,QAAQ;AAAA,EACb,CAAC;AAAA,EACD,IAAI,MAAM,KAAK,KAAK,GAAG;AAAA,IACrB,OAAO;AAAA,EACT;AAAA,EACA,UAAU,4FAA4F,SAAS;AAAA,EAC/G,OAAO;AAAA;", - "debugId": "C2025280B7E6F40964756E2164756E21", + "mappings": ";;;;;;;;;;;;;;;;;;;AAmBO,MAAM,qBAAqB,aAAa;AAG/C;AAEO,IAAM,eAAe,SAAS,UAAU,wBAAwB,kBAAgC;AAAA,EACrG,MAAM,QAAQ,IAAI,OAAO,OAAO;AAAA,EAChC,MAAM,aAAa,cAAc,OAAO,WAAW,IAAI,QAAQ,MAAM;AAAA,EAErE;AAAA,IACE,QAAQ;AAAA,MACN,MAAM,QAAQ,MAAM,IAAI;AAAA,IAC1B,aAAa;AAAA,OACV,QAAQ;AAAA,EACb,CAAC;AAAA,EAED,IAAI,MAAM,KAAK,KAAK,GAAG;AAAA,IACrB,OAAO;AAAA,EACT;AAAA,EAEA,UAAU,4FAA4F,SAAS;AAAA,EAE/G,OAAO;AAAA;", + "debugId": "9A54DF641B4B9ABB64756E2164756E21", "names": [] } \ No newline at end of file diff --git a/dist/helpers/get-changed-files.js b/dist/helpers/get-changed-files.js index 47291222..45a262b1 100644 --- a/dist/helpers/get-changed-files.js +++ b/dist/helpers/get-changed-files.js @@ -19,8 +19,8 @@ import"../main-wckvcay0.js"; // src/helpers/get-changed-files.ts class GetChangedFiles extends HelperInputs { } -var getChangedFiles = async ({ pattern, delimiter = ",", ignore_deleted }) => { - const pullNumber = context.eventName === "merge_group" ? getPrNumberFromMergeQueueRef() : context.issue.number; +var getChangedFiles = async ({ pattern, delimiter = ",", ignore_deleted, pull_number }) => { + const pullNumber = pull_number ? Number(pull_number) : context.eventName === "merge_group" ? getPrNumberFromMergeQueueRef() : context.issue.number; const filePaths = await getChangedFilepaths(pullNumber, Boolean(ignore_deleted)); const filteredFilePaths = pattern ? filePaths.filter((fileName) => fileName.match(pattern)) : filePaths; return filteredFilePaths.join(delimiter); @@ -30,4 +30,4 @@ export { GetChangedFiles }; -//# debugId=72308F916186F09B64756E2164756E21 +//# debugId=F2CE773BF74E848A64756E2164756E21 diff --git a/dist/helpers/get-changed-files.js.map b/dist/helpers/get-changed-files.js.map index e185f2d5..ae50391f 100644 --- a/dist/helpers/get-changed-files.js.map +++ b/dist/helpers/get-changed-files.js.map @@ -2,9 +2,9 @@ "version": 3, "sources": ["../src/helpers/get-changed-files.ts"], "sourcesContent": [ - "/*\nCopyright 2021 Expedia, Inc.\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n https://www.apache.org/licenses/LICENSE-2.0\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { HelperInputs } from '../types/generated';\nimport { context } from '@actions/github';\nimport { getChangedFilepaths } from '../utils/get-changed-filepaths';\nimport { getPrNumberFromMergeQueueRef } from '../utils/merge-queue';\n\nexport class GetChangedFiles extends HelperInputs {\n declare pattern?: string;\n declare delimiter?: string;\n declare ignore_deleted?: string;\n}\n\nexport const getChangedFiles = async ({ pattern, delimiter = ',', ignore_deleted }: GetChangedFiles) => {\n const pullNumber = context.eventName === 'merge_group' ? getPrNumberFromMergeQueueRef() : context.issue.number;\n const filePaths = await getChangedFilepaths(pullNumber, Boolean(ignore_deleted));\n const filteredFilePaths = pattern ? filePaths.filter(fileName => fileName.match(pattern)) : filePaths;\n return filteredFilePaths.join(delimiter);\n};\n" + "/*\nCopyright 2021 Expedia, Inc.\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n https://www.apache.org/licenses/LICENSE-2.0\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { HelperInputs } from '../types/generated';\nimport { context } from '@actions/github';\nimport { getChangedFilepaths } from '../utils/get-changed-filepaths';\nimport { getPrNumberFromMergeQueueRef } from '../utils/merge-queue';\n\nexport class GetChangedFiles extends HelperInputs {\n declare pattern?: string;\n declare delimiter?: string;\n declare ignore_deleted?: string;\n declare pull_number?: string;\n}\n\nexport const getChangedFiles = async ({ pattern, delimiter = ',', ignore_deleted, pull_number }: GetChangedFiles) => {\n const pullNumber = pull_number\n ? Number(pull_number)\n : context.eventName === 'merge_group'\n ? getPrNumberFromMergeQueueRef()\n : context.issue.number;\n\n const filePaths = await getChangedFilepaths(pullNumber, Boolean(ignore_deleted));\n const filteredFilePaths = pattern ? filePaths.filter(fileName => fileName.match(pattern)) : filePaths;\n\n return filteredFilePaths.join(delimiter);\n};\n" ], - "mappings": ";;;;;;;;;;;;;;;;;;;AAkBO,MAAM,wBAAwB,aAAa;AAIlD;AAEO,IAAM,kBAAkB,SAAS,SAAS,YAAY,KAAK,qBAAsC;AAAA,EACtG,MAAM,aAAa,QAAQ,cAAc,gBAAgB,6BAA6B,IAAI,QAAQ,MAAM;AAAA,EACxG,MAAM,YAAY,MAAM,oBAAoB,YAAY,QAAQ,cAAc,CAAC;AAAA,EAC/E,MAAM,oBAAoB,UAAU,UAAU,OAAO,cAAY,SAAS,MAAM,OAAO,CAAC,IAAI;AAAA,EAC5F,OAAO,kBAAkB,KAAK,SAAS;AAAA;", - "debugId": "72308F916186F09B64756E2164756E21", + "mappings": ";;;;;;;;;;;;;;;;;;;AAkBO,MAAM,wBAAwB,aAAa;AAKlD;AAEO,IAAM,kBAAkB,SAAS,SAAS,YAAY,KAAK,gBAAgB,kBAAmC;AAAA,EACnH,MAAM,aAAa,cACf,OAAO,WAAW,IAClB,QAAQ,cAAc,gBACpB,6BAA6B,IAC7B,QAAQ,MAAM;AAAA,EAEpB,MAAM,YAAY,MAAM,oBAAoB,YAAY,QAAQ,cAAc,CAAC;AAAA,EAC/E,MAAM,oBAAoB,UAAU,UAAU,OAAO,cAAY,SAAS,MAAM,OAAO,CAAC,IAAI;AAAA,EAE5F,OAAO,kBAAkB,KAAK,SAAS;AAAA;", + "debugId": "F2CE773BF74E848A64756E2164756E21", "names": [] } \ No newline at end of file diff --git a/src/helpers/check-merge-safety.ts b/src/helpers/check-merge-safety.ts index 77d1a48c..147f9f9a 100644 --- a/src/helpers/check-merge-safety.ts +++ b/src/helpers/check-merge-safety.ts @@ -37,17 +37,21 @@ export class CheckMergeSafety extends HelperInputs { declare override_filter_paths?: string; declare override_filter_globs?: string; declare match_comment_paths?: string; + declare pull_number?: string; } export const checkMergeSafety = async (inputs: CheckMergeSafety) => { core.warning( "check-merge-safety is deprecated. Please use GitHub's native merge queue: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue" ); - const isPrWorkflow = Boolean(githubContext.issue.number); + + const pullNumber = inputs.pull_number ? Number(inputs.pull_number) : githubContext.issue.number; + const isPrWorkflow = Boolean(pullNumber); + if (!isPrWorkflow) { return handlePushWorkflow(inputs); } - const { data: pullRequest } = await octokit.pulls.get({ pull_number: githubContext.issue.number, ...githubContext.repo }); + const { data: pullRequest } = await octokit.pulls.get({ pull_number: pullNumber, ...githubContext.repo }); const { state, message } = await setMergeSafetyStatus(pullRequest, inputs); if (state === 'failure') { diff --git a/src/helpers/check-pr-title.ts b/src/helpers/check-pr-title.ts index d7232d3e..5933c911 100644 --- a/src/helpers/check-pr-title.ts +++ b/src/helpers/check-pr-title.ts @@ -19,19 +19,25 @@ import { setFailed } from '@actions/core'; export class CheckPrTitle extends HelperInputs { declare pattern?: string; + declare pull_number?: string; } -export const checkPrTitle = async ({ pattern = DEFAULT_PR_TITLE_REGEX }: CheckPrTitle) => { +export const checkPrTitle = async ({ pattern = DEFAULT_PR_TITLE_REGEX, pull_number }: CheckPrTitle) => { const regex = new RegExp(pattern); + const pullNumber = pull_number ? Number(pull_number) : context.issue.number; + const { data: { title } } = await octokit.pulls.get({ - pull_number: context.issue.number, + pull_number: pullNumber, ...context.repo }); + if (regex.test(title)) { return true; } + setFailed(`Pull request title does not meet requirements. The title must match the following regex: ${pattern}`); + return false; }; diff --git a/src/helpers/get-changed-files.ts b/src/helpers/get-changed-files.ts index 4ff1f520..7ff1209a 100644 --- a/src/helpers/get-changed-files.ts +++ b/src/helpers/get-changed-files.ts @@ -20,11 +20,18 @@ export class GetChangedFiles extends HelperInputs { declare pattern?: string; declare delimiter?: string; declare ignore_deleted?: string; + declare pull_number?: string; } -export const getChangedFiles = async ({ pattern, delimiter = ',', ignore_deleted }: GetChangedFiles) => { - const pullNumber = context.eventName === 'merge_group' ? getPrNumberFromMergeQueueRef() : context.issue.number; +export const getChangedFiles = async ({ pattern, delimiter = ',', ignore_deleted, pull_number }: GetChangedFiles) => { + const pullNumber = pull_number + ? Number(pull_number) + : context.eventName === 'merge_group' + ? getPrNumberFromMergeQueueRef() + : context.issue.number; + const filePaths = await getChangedFilepaths(pullNumber, Boolean(ignore_deleted)); const filteredFilePaths = pattern ? filePaths.filter(fileName => fileName.match(pattern)) : filePaths; + return filteredFilePaths.join(delimiter); }; diff --git a/test/helpers/check-merge-safety.test.ts b/test/helpers/check-merge-safety.test.ts index cd0ddfe7..41ae1354 100644 --- a/test/helpers/check-merge-safety.test.ts +++ b/test/helpers/check-merge-safety.test.ts @@ -329,6 +329,25 @@ describe('checkMergeSafety', () => { }); }); + it('should use pull_number input when issue number is unavailable', async () => { + const filesOutOfDate: string[] = []; + const changedFilesOnPr = ['packages/package-1/src/some-file.ts']; + mockGithubRequests(filesOutOfDate, changedFilesOnPr); + context.issue.number = undefined as unknown as number; + + await checkMergeSafety({ + paths: allProjectPaths, + pull_number: '456', + ...context.repo + }); + + expect(octokit.pulls.get).toHaveBeenCalledWith({ + pull_number: 456, + ...context.repo + }); + expect(octokit.pulls.list).not.toHaveBeenCalled(); + }); + it('should skip setting merge safety commit status when a PR already has the failure context set', async () => { const filesOutOfDate = ['packages/package-1/src/another-file.ts']; const changedFilesOnPr = ['packages/package-1/src/some-file.ts']; diff --git a/test/helpers/check-pr-title.test.ts b/test/helpers/check-pr-title.test.ts index cc10d538..e5835b02 100644 --- a/test/helpers/check-pr-title.test.ts +++ b/test/helpers/check-pr-title.test.ts @@ -18,6 +18,7 @@ setupMocks(); const { checkPrTitle } = await import('../../src/helpers/check-pr-title'); const { octokit } = await import('../../src/octokit'); +const { context } = await import('@actions/github'); describe('checkPrTitle', () => { it('should pass as the PR title conforms to the regex', async () => { @@ -49,4 +50,24 @@ describe('checkPrTitle', () => { expect(result).toBe(false); }); + + it('should use pull_number input when provided', async () => { + (octokit.pulls.get as unknown as Mock).mockImplementation(async () => ({ + data: { + id: 1, + number: 999, + state: 'open', + title: 'feat: added feature to project' + } + })); + + context.issue.number = 123; + const result = await checkPrTitle({ pull_number: '999' }); + + expect(result).toBe(true); + expect(octokit.pulls.get).toHaveBeenCalledWith({ + pull_number: 999, + ...context.repo + }); + }); }); diff --git a/test/helpers/get-changed-files.test.ts b/test/helpers/get-changed-files.test.ts index d3fc9605..56857520 100644 --- a/test/helpers/get-changed-files.test.ts +++ b/test/helpers/get-changed-files.test.ts @@ -166,4 +166,18 @@ describe('getChangedFiles', () => { expect(result).toEqual([mock_data4[0].filename, mock_data4[1].filename, mock_data4[1].previous_filename].join(',')); }); + + it('should use pull_number input over merge queue pull number', async () => { + context.eventName = 'merge_group'; + context.ref = 'refs/heads/gh-readonly-queue/default-branch/pr-12345-f0d9a4cb862b13cdaab6522f72d6dc17e4336b7f'; + (octokit.pulls.listFiles as unknown as Mock).mockImplementation( + async ({ page, pull_number }: { page: number; pull_number: number }) => ({ + data: pull_number === 456 && page === 1 ? mock_data2 : [] + }) + ); + + const result = await getChangedFiles({ pull_number: '456' }); + + expect(result).toEqual(mock_data2[0].filename); + }); });