Repository: deepakputhraya/action-pr-title Branch: master Commit: 077bddd7bdab Files: 7 Total size: 8.9 KB Directory structure: gitextract_emneji4x/ ├── .github/ │ └── workflows/ │ └── main.yml ├── .gitignore ├── LICENSE ├── README.md ├── action.yml ├── index.js └── package.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/main.yml ================================================ name: main # This workflow is triggered on pushes to the repository. on: pull_request: types: [opened, edited, synchronize, reopened] jobs: build: # Job name is Greeting name: Check # This job runs on Linux runs-on: 'ubuntu-latest' steps: - uses: actions/checkout@master - uses: actions/setup-node@v1 with: node-version: '20' - run: npm install - name: Validate uses: ./ with: github_token: ${{ github.token }} ================================================ FILE: .gitignore ================================================ .idea/ ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2018 GitHub, Inc. and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # Branch naming rules GitHub Actions status Github action to enforce Pull Request title conventions ## Usage See [action.yml](./action.yml) ```yaml steps: - uses: deepakputhraya/action-pr-title@master with: regex: '([a-z])+\/([a-z])+' # Regex the title should match. allowed_prefixes: 'feature,fix,JIRA' # title should start with the given prefix disallowed_prefixes: 'feat/,hotfix' # title should not start with the given prefix prefix_case_sensitive: false # title prefix are case insensitive min_length: 5 # Min length of the title max_length: 20 # Max length of the title verbal_description: 'Two words with a slash (/) between' # Verbal description of the regex rule github_token: ${{ github.token }} # Default: ${{ github.token }} ``` ### Note: Ensure to add `types` to the Pull requests webhook event as by default workflows are triggered only for `opened`, `synchronize`, or `reopened` pull request events. Read more about it [here](https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows#pull_request). ```yaml on: pull_request: types: [opened, edited, synchronize, reopened] ``` or [here](https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows#pull_request_target). ```yaml on: pull_request_target: types: [opened, edited, synchronize, reopened] ``` Triggering the action on anything other than `pull_request` or `pull_request_target` will cause a failure. ## Permissions In case the action fails with the following error: ``` Event name: pull_request Error: Resource not accessible by integration ``` You can fix this, by adding the following to your workflow: ```yaml permissions: pull-requests: read ``` ## License The scripts and documentation in this project are released under the [MIT License](./LICENSE) ================================================ FILE: action.yml ================================================ name: 'Pull Request title rules' description: 'Github action to enforce Pull Request title conventions' author: 'deepakputhraya' inputs: regex: description: 'Regex to validate the pull request title' required: false default: '.+' allowed_prefixes: description: 'Comma separated list of prefix allowed to be used in title. eg: feature,hotfix,JIRA-' required: false default: '' disallowed_prefixes: description: 'Comma separated list of prefix disallowed to be used in title. eg: feat,fix' required: false default: '' prefix_case_sensitive: description: 'Are the allowed & disallowed prefixes case sensitive?' required: false default: 'false' min_length: description: 'Min length of title' required: false default: '1' max_length: description: 'Max length of title. -1 to ignore the rule' required: false default: '-1' verbal_description: description: 'Description of the title rules to display when the action fails' required: false default: '' github_token: description: > Personal access token (PAT) used to fetch the repository. The PAT is configured with the local git config, which enables your scripts to run authenticated git commands. The post-job step removes the PAT. We recommend using a service account with the least permissions necessary. Also when generating a new PAT, select the least scopes necessary. required: false default: ${{ github.token }} runs: using: 'node20' main: 'index.js' branding: icon: 'alert-triangle' color: 'gray-dark' ================================================ FILE: index.js ================================================ const core = require('@actions/core'); const github = require('@actions/github'); const validEvent = ['pull_request','pull_request_target']; function validateTitlePrefix(title, prefix, caseSensitive) { if (!caseSensitive) { prefix = prefix.toLowerCase(); title = title.toLowerCase(); } return title.startsWith(prefix); } async function run() { try { const verbalDescription = core.getInput('verbal_description') const authToken = core.getInput('github_token', {required: true}) const eventName = github.context.eventName; core.info(`Event name: ${eventName}`); if (validEvent.indexOf(eventName) < 0) { core.setFailed(`Invalid event: ${eventName}`); return; } const owner = github.context.payload.pull_request.base.user.login; const repo = github.context.payload.pull_request.base.repo.name; const client = new github.getOctokit(authToken); // The pull request info on the context isn't up to date. When // the user updates the title and re-runs the workflow, it would // be outdated. Therefore fetch the pull request via the REST API // to ensure we use the current title. const {data: pullRequest} = await client.rest.pulls.get({ owner, repo, pull_number: github.context.payload.pull_request.number }); const title = pullRequest.title; core.info(`Pull Request title: "${title}"`); // Check if title pass regex const regex = RegExp(core.getInput('regex')); if (!regex.test(title)) { const messageSuffix = verbalDescription ? `rule - ${verbalDescription}` : `match regex - ${regex}`; core.setFailed(`Pull Request title "${title}" failed to pass ${messageSuffix}`); return } // Check min length const minLen = parseInt(core.getInput('min_length')); if (title.length < minLen) { core.setFailed(`Pull Request title "${title}" is smaller than min length specified - ${minLen}`); return } // Check max length const maxLen = parseInt(core.getInput('max_length')); if (maxLen > 0 && title.length > maxLen) { core.setFailed(`Pull Request title "${title}" is greater than max length specified - ${maxLen}`); return } // Check if title starts with an allowed prefix let prefixes = core.getInput('allowed_prefixes'); const prefixCaseSensitive = (core.getInput('prefix_case_sensitive') === 'true'); core.info(`Allowed Prefixes: ${prefixes}`); if (prefixes.length > 0 && !prefixes.split(',').some((el) => validateTitlePrefix(title, el, prefixCaseSensitive))) { core.setFailed(`Pull Request title "${title}" did not match any of the prefixes - ${prefixes}`); return } // Check if title starts with a disallowed prefix prefixes = core.getInput('disallowed_prefixes'); core.info(`Disallowed Prefixes: ${prefixes}`); if (prefixes.length > 0 && prefixes.split(',').some((el) => validateTitlePrefix(title, el, prefixCaseSensitive))) { core.setFailed(`Pull Request title "${title}" matched with a disallowed prefix - ${prefixes}`); return } } catch (error) { core.setFailed(error.message); } } run(); ================================================ FILE: package.json ================================================ { "name": "action-pr-title", "version": "1.3.0", "description": "Github action to enforce naming convention on Pull Request titles", "main": "index.js", "scripts": { "start": "node index.js", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [ "github", "actions" ], "author": "deepakputhraya", "license": "MIT", "dependencies": { "@actions/core": "^1.11.1", "@actions/github": "^6.0.0" } }