diff --git a/.github/workflows/pr-lint.yml b/.github/workflows/pr-lint.yml index 820c168f..d705d577 100644 --- a/.github/workflows/pr-lint.yml +++ b/.github/workflows/pr-lint.yml @@ -14,5 +14,9 @@ jobs: steps: - uses: morrisoncole/pr-lint-action@main with: - title-regex: "#[eE][xX]-[0-9]+" + title-regex: "#EX-[0-9]+" + on-failed-regex-fail-action: false + on-failed-regex-create-review: true + on-failed-regex-comment: + "This is just an example. Failed regex: `%regex%`!" repo-token: "${{ secrets.GITHUB_TOKEN }}" diff --git a/README.md b/README.md index 4ddae821..da3eef42 100644 --- a/README.md +++ b/README.md @@ -22,9 +22,11 @@ jobs: pr-lint: runs-on: ubuntu-latest steps: - - uses: morrisoncole/pr-lint-action@v1.2.3 + - uses: morrisoncole/pr-lint-action@v1.3.0 with: - title-regex: "#EX-[0-9]+" + title-regex: "#[eE][xX]-[0-9]+" + on-failed-regex-fail-action: false + on-failed-regex-create-review: true on-failed-regex-comment: "This is just an example. Failed regex: `%regex%`!" repo-token: "${{ secrets.GITHUB_TOKEN }}" @@ -32,6 +34,17 @@ jobs: ## Changelog +### v1.3.0 + +- Adds [#111](https://github.com/MorrisonCole/pr-lint-action/issues/111), the + ability to specify whether to create a review and whether to fail the action + on a regex mismatch independently with `on-failed-regex-fail-action` & + `on-failed-regex-create-review`. +- `on-failed-regex-comment` is no longer a required input. + +_Note:_ existing behaviour from previous releases is preserved without +additional configuration 🙏. + ### v1.2.3 Internal refactoring only: diff --git a/action.yml b/action.yml index 34f058c3..7334568f 100644 --- a/action.yml +++ b/action.yml @@ -1,5 +1,5 @@ name: "Pull Request Linter" -description: "Ensures your PR title matches a given regex" +description: "Ensure your PR titles match a given regex." author: "MorrisonCole" branding: icon: "check" @@ -9,12 +9,22 @@ inputs: description: "Regex to ensure PR title matches. Allows anything by default." required: true default: ".*" + on-failed-regex-create-review: + description: + "Whether the action should create a PR review & comment when the regex + doesn't match." + required: false + default: true on-failed-regex-comment: description: "Comment for the bot to post on PRs that fail the regex. Use %regex% to reference regex." - required: true + required: false default: "PR title failed to match %regex%." + on-failed-regex-fail-action: + description: "Whether the action should fail when the regex doesn't match." + required: false + default: false repo-token: description: "Github token with access to the repository (secrets.GITHUB_TOKEN)." diff --git a/dist/main.js b/dist/main.js index 394cfac0..2c3459ae 100644 --- a/dist/main.js +++ b/dist/main.js @@ -22,47 +22,64 @@ Object.defineProperty(exports, "__esModule", { value: true }); const github_1 = require("@actions/github/lib/github"); const core = __importStar(require("@actions/core")); const github = __importStar(require("@actions/github")); +const repoTokenInput = core.getInput("repo-token", { required: true }); +const githubClient = github_1.getOctokit(repoTokenInput); +const titleRegexInput = core.getInput("title-regex", { + required: true, +}); +const onFailedRegexCreateReviewInput = core.getInput("on-failed-regex-create-review") == "true"; +const onFailedRegexCommentInput = core.getInput("on-failed-regex-comment"); +const onFailedRegexFailActionInput = core.getInput("on-failed-regex-fail-action") == "true"; async function run() { const githubContext = github.context; - const githubToken = core.getInput("repo-token"); - const githubClient = github_1.getOctokit(githubToken); - const pr = githubContext.issue; - const titleRegex = new RegExp(core.getInput("title-regex")); + const pullRequest = githubContext.issue; + const titleRegex = new RegExp(titleRegexInput); const title = githubContext.payload.pull_request?.title ?? ""; - const onFailedRegexComment = core - .getInput("on-failed-regex-comment") - .replace("%regex%", titleRegex.source); + const comment = onFailedRegexCommentInput.replace("%regex%", titleRegex.source); core.debug(`Title Regex: ${titleRegex.source}`); core.debug(`Title: ${title}`); const titleMatchesRegex = titleRegex.test(title); if (!titleMatchesRegex) { - void githubClient.pulls.createReview({ - owner: pr.owner, - repo: pr.repo, - pull_number: pr.number, - body: onFailedRegexComment, - event: "REQUEST_CHANGES", - }); + if (onFailedRegexCreateReviewInput) { + createReview(comment, pullRequest); + } + if (onFailedRegexFailActionInput) { + core.setFailed(comment); + } } else { - const reviews = await githubClient.pulls.listReviews({ - owner: pr.owner, - repo: pr.repo, - pull_number: pr.number, - }); - reviews.data.forEach((review) => { - if (review.user.login == "github-actions[bot]") { - void githubClient.pulls.dismissReview({ - owner: pr.owner, - repo: pr.repo, - pull_number: pr.number, - review_id: review.id, - message: "All good!", - }); - } - }); + if (onFailedRegexCreateReviewInput) { + await dismissReview(pullRequest); + } } } +function createReview(comment, pullRequest) { + void githubClient.pulls.createReview({ + owner: pullRequest.owner, + repo: pullRequest.repo, + pull_number: pullRequest.number, + body: comment, + event: "REQUEST_CHANGES", + }); +} +async function dismissReview(pullRequest) { + const reviews = await githubClient.pulls.listReviews({ + owner: pullRequest.owner, + repo: pullRequest.repo, + pull_number: pullRequest.number, + }); + reviews.data.forEach((review) => { + if (review.user.login == "github-actions[bot]") { + void githubClient.pulls.dismissReview({ + owner: pullRequest.owner, + repo: pullRequest.repo, + pull_number: pullRequest.number, + review_id: review.id, + message: "All good!", + }); + } + }); +} run().catch((error) => { core.setFailed(error); }); diff --git a/src/main.ts b/src/main.ts index 2996b70d..fea35ab9 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2,54 +2,87 @@ import { getOctokit } from "@actions/github/lib/github"; import * as core from "@actions/core"; import * as github from "@actions/github"; +const repoTokenInput = core.getInput("repo-token", { required: true }); +const githubClient = getOctokit(repoTokenInput); + +const titleRegexInput: string = core.getInput("title-regex", { + required: true, +}); +const onFailedRegexCreateReviewInput: boolean = + core.getInput("on-failed-regex-create-review") == "true"; +const onFailedRegexCommentInput: string = core.getInput( + "on-failed-regex-comment" +); +const onFailedRegexFailActionInput: boolean = + core.getInput("on-failed-regex-fail-action") == "true"; + async function run(): Promise { const githubContext = github.context; - const githubToken = core.getInput("repo-token"); - const githubClient = getOctokit(githubToken); + const pullRequest = githubContext.issue; - const pr = githubContext.issue; - - const titleRegex = new RegExp(core.getInput("title-regex")); + const titleRegex = new RegExp(titleRegexInput); const title: string = (githubContext.payload.pull_request?.title as string) ?? ""; - - const onFailedRegexComment = core - .getInput("on-failed-regex-comment") - .replace("%regex%", titleRegex.source); + const comment = onFailedRegexCommentInput.replace( + "%regex%", + titleRegex.source + ); core.debug(`Title Regex: ${titleRegex.source}`); core.debug(`Title: ${title}`); const titleMatchesRegex: boolean = titleRegex.test(title); if (!titleMatchesRegex) { - void githubClient.pulls.createReview({ - owner: pr.owner, - repo: pr.repo, - pull_number: pr.number, - body: onFailedRegexComment, - event: "REQUEST_CHANGES", - }); + if (onFailedRegexCreateReviewInput) { + createReview(comment, pullRequest); + } + if (onFailedRegexFailActionInput) { + core.setFailed(comment); + } } else { - const reviews = await githubClient.pulls.listReviews({ - owner: pr.owner, - repo: pr.repo, - pull_number: pr.number, - }); - - reviews.data.forEach((review) => { - if (review.user.login == "github-actions[bot]") { - void githubClient.pulls.dismissReview({ - owner: pr.owner, - repo: pr.repo, - pull_number: pr.number, - review_id: review.id, - message: "All good!", - }); - } - }); + if (onFailedRegexCreateReviewInput) { + await dismissReview(pullRequest); + } } } +function createReview( + comment: string, + pullRequest: { owner: string; repo: string; number: number } +) { + void githubClient.pulls.createReview({ + owner: pullRequest.owner, + repo: pullRequest.repo, + pull_number: pullRequest.number, + body: comment, + event: "REQUEST_CHANGES", + }); +} + +async function dismissReview(pullRequest: { + owner: string; + repo: string; + number: number; +}) { + const reviews = await githubClient.pulls.listReviews({ + owner: pullRequest.owner, + repo: pullRequest.repo, + pull_number: pullRequest.number, + }); + + reviews.data.forEach((review) => { + if (review.user.login == "github-actions[bot]") { + void githubClient.pulls.dismissReview({ + owner: pullRequest.owner, + repo: pullRequest.repo, + pull_number: pullRequest.number, + review_id: review.id, + message: "All good!", + }); + } + }); +} + run().catch((error) => { core.setFailed(error); });