diff --git a/dist/helpers/check-merge-safety.js b/dist/helpers/check-merge-safety.js index 0ccae1c6..7a886ca1 100644 --- a/dist/helpers/check-merge-safety.js +++ b/dist/helpers/check-merge-safety.js @@ -40,6 +40,7 @@ var import_bluebird = __toESM(require_bluebird(), 1); var git = simpleGit(); var maxBranchNameLength = 50; var COMMENT_PATHS_MARKER = ""; +var getWorkflowRunUrl = () => `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; class CheckMergeSafety extends HelperInputs { } @@ -74,6 +75,7 @@ var setMergeSafetyStatus = async (pullRequest, { context: context2 = "Merge Safe state, context: context2, description: message, + target_url: getWorkflowRunUrl(), ...context.repo }); } @@ -175,11 +177,9 @@ var getMergeSafetyStateAndMessage = async (pullRequest, { paths, ignore_globs, o const outdatedCommentPaths = commentPaths.filter((commentPath) => fileNamesWhichBranchIsBehindOn.some((file) => file.startsWith(commentPath + "/") || file === commentPath)); if (outdatedCommentPaths.length) { error(buildErrorMessage(outdatedCommentPaths, "comment paths", truncatedBranchName)); - const displayPaths = outdatedCommentPaths.slice(0, 3).join(", "); - const suffix = outdatedCommentPaths.length > 3 ? "..." : ""; return { state: "failure", - message: `Branch is behind on paths from comment: ${displayPaths}${suffix}. Please update with ${default_branch}.` + message: `Branch is behind on ${outdatedCommentPaths.length} path(s) from comment. Please update with ${default_branch}.` }; } } else { @@ -259,4 +259,4 @@ export { CheckMergeSafety }; -//# debugId=F4EC41763AC4ABEC64756E2164756E21 +//# debugId=41C4FA0898BE964F64756E2164756E21 diff --git a/dist/helpers/check-merge-safety.js.map b/dist/helpers/check-merge-safety.js.map index 9ce0614d..c453d55c 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\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 ...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 if (data.state === 'failure') {\n const existingContext = data.statuses.find(status => status.context === context);\n return Boolean(existingContext);\n }\n return false;\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 const displayPaths = outdatedCommentPaths.slice(0, 3).join(', ');\n const suffix = outdatedCommentPaths.length > 3 ? '...' : '';\n return {\n state: 'failure',\n message: `Branch is behind on paths from comment: ${displayPaths}${suffix}. 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}\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 if (data.state === 'failure') {\n const existingContext = data.statuses.find(status => status.context === context);\n return Boolean(existingContext);\n }\n return false;\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": "F4EC41763AC4ABEC64756E2164756E21", + "mappings": "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", + "debugId": "41C4FA0898BE964F64756E2164756E21", "names": [] } \ No newline at end of file diff --git a/src/helpers/check-merge-safety.ts b/src/helpers/check-merge-safety.ts index 771078b2..0d422db2 100644 --- a/src/helpers/check-merge-safety.ts +++ b/src/helpers/check-merge-safety.ts @@ -27,6 +27,9 @@ const git = simpleGit(); const maxBranchNameLength = 50; const COMMENT_PATHS_MARKER = ''; +const getWorkflowRunUrl = () => + `${githubContext.serverUrl}/${githubContext.repo.owner}/${githubContext.repo.repo}/actions/runs/${githubContext.runId}`; + export class CheckMergeSafety extends HelperInputs { declare context?: string; declare paths?: string; @@ -71,6 +74,7 @@ const setMergeSafetyStatus = async (pullRequest: PullRequest, { context = 'Merge state, context, description: message, + target_url: getWorkflowRunUrl(), ...githubContext.repo }); } @@ -194,11 +198,9 @@ const getMergeSafetyStateAndMessage = async ( if (outdatedCommentPaths.length) { core.error(buildErrorMessage(outdatedCommentPaths, 'comment paths', truncatedBranchName)); - const displayPaths = outdatedCommentPaths.slice(0, 3).join(', '); - const suffix = outdatedCommentPaths.length > 3 ? '...' : ''; return { state: 'failure', - message: `Branch is behind on paths from comment: ${displayPaths}${suffix}. Please update with ${default_branch}.` + message: `Branch is behind on ${outdatedCommentPaths.length} path(s) from comment. Please update with ${default_branch}.` } as const; } } else { diff --git a/test/helpers/check-merge-safety.test.ts b/test/helpers/check-merge-safety.test.ts index 935e519e..3884b9fc 100644 --- a/test/helpers/check-merge-safety.test.ts +++ b/test/helpers/check-merge-safety.test.ts @@ -131,6 +131,7 @@ describe('checkMergeSafety', () => { state: 'failure', context: 'Merge Safety', description: 'This branch has one or more outdated projects. Please update with main.', + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -152,6 +153,7 @@ describe('checkMergeSafety', () => { state: 'success', context: 'Merge Safety', description: 'Branch username:some-branch-name is safe to merge!', + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -176,6 +178,7 @@ describe('checkMergeSafety', () => { state: 'success', context: 'Merge Safety', description: 'Branch username:some-branch-name is safe to merge!', + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -197,6 +200,7 @@ describe('checkMergeSafety', () => { state: 'failure', context: 'Merge Safety', description: 'This branch has one or more outdated projects. Please update with main.', + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -230,6 +234,7 @@ describe('checkMergeSafety', () => { state: 'failure', context: 'Merge Safety', description, + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -277,6 +282,7 @@ describe('checkMergeSafety', () => { state: 'failure', context: 'Merge Safety', description, + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -296,6 +302,7 @@ describe('checkMergeSafety', () => { state: 'success', context: 'Merge Safety', description: 'Branch username:some-branch-name is safe to merge!', + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -316,6 +323,7 @@ describe('checkMergeSafety', () => { state: 'success', context: 'Merge Safety', description: 'Branch username:some-branch-name is safe to merge!', + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -352,6 +360,7 @@ describe('checkMergeSafety', () => { state: 'failure', context: 'Merge Safety', description: 'This branch has one or more outdated projects. Please update with main.', + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -372,6 +381,7 @@ describe('checkMergeSafety', () => { state: 'failure', context: 'Merge Safety', description: 'This branch has one or more outdated global files. Please update with main.', + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -391,6 +401,7 @@ describe('checkMergeSafety', () => { state: 'failure', context: 'Merge Safety', description: 'This branch has one or more outdated global files. Please update with main.', + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -410,6 +421,7 @@ describe('checkMergeSafety', () => { state: 'failure', context: 'Merge Safety', description: 'This branch has one or more outdated global files. Please update with main.', + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -429,6 +441,7 @@ describe('checkMergeSafety', () => { state: 'success', context: 'Merge Safety', description: 'Branch username:some-branch-name is safe to merge!', + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -455,6 +468,7 @@ describe('checkMergeSafety', () => { state: 'success', context: 'Merge Safety', description: `Branch username:${'x'.repeat(50)}... is safe to merge!`, + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -498,6 +512,7 @@ describe('checkMergeSafety', () => { state: 'success', context: 'Merge Safety', description: 'Branch username:some-branch-name is safe to merge!', + target_url: 'https://github.com/owner/repo/actions/runs/123', ...context.repo }); expect(octokit.repos.createCommitStatus).toHaveBeenCalledWith({ @@ -505,6 +520,7 @@ describe('checkMergeSafety', () => { state: 'success', context: 'Merge Safety', description: 'Branch username:some-branch-name is safe to merge!', + target_url: 'https://github.com/owner/repo/actions/runs/123', ...context.repo }); expect(octokit.repos.createCommitStatus).not.toHaveBeenCalledWith({ @@ -512,6 +528,7 @@ describe('checkMergeSafety', () => { state: 'success', context: 'Merge Safety', description: 'Branch username:some-branch-name is safe to merge!', + target_url: 'https://github.com/owner/repo/actions/runs/123', ...context.repo }); expect(octokit.repos.createCommitStatus).not.toHaveBeenCalledWith({ @@ -519,6 +536,7 @@ describe('checkMergeSafety', () => { state: 'success', context: 'Merge Safety', description: 'Branch username:some-branch-name is safe to merge!', + target_url: 'https://github.com/owner/repo/actions/runs/123', ...context.repo }); }); @@ -559,8 +577,8 @@ describe('checkMergeSafety', () => { sha, state: 'failure', context: 'Merge Safety', - description: - 'Branch is behind on paths from comment: Modules/EGSharedUI/EGSharedUI_Retail/EGSharedUI_Checkout. Please update with main.', + description: 'Branch is behind on 1 path(s) from comment. Please update with main.', + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -584,6 +602,7 @@ describe('checkMergeSafety', () => { state: 'success', context: 'Merge Safety', description: 'Branch username:some-branch-name is safe to merge!', + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -607,6 +626,7 @@ describe('checkMergeSafety', () => { state: 'success', context: 'Merge Safety', description: 'Branch username:some-branch-name is safe to merge!', + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -629,6 +649,7 @@ describe('checkMergeSafety', () => { state: 'success', context: 'Merge Safety', description: 'Branch username:some-branch-name is safe to merge!', + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -651,6 +672,7 @@ describe('checkMergeSafety', () => { state: 'success', context: 'Merge Safety', description: 'Branch username:some-branch-name is safe to merge!', + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -673,6 +695,7 @@ describe('checkMergeSafety', () => { state: 'failure', context: 'Merge Safety', description: 'This branch has one or more outdated projects. Please update with main.', + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); @@ -705,7 +728,8 @@ describe('checkMergeSafety', () => { sha, state: 'failure', context: 'Merge Safety', - description: expect.stringContaining('...'), + description: 'Branch is behind on 4 path(s) from comment. Please update with main.', + target_url: 'https://github.com/owner/repo/actions/runs/123', repo: 'repo', owner: 'owner' }); diff --git a/test/setup.ts b/test/setup.ts index 0064962b..40709798 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -114,6 +114,7 @@ export const createMockActionsGithub = (mockOctokit: ReturnType