Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions .github/actions/pr-title-check/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# PR Title Check Action

A composite action that validates pull request titles against conventional commit standards.
A composite action that validates pull request titles against conventional commit standards and ensures a Jira ticket is referenced.

## Usage

Expand All @@ -11,7 +11,14 @@ A composite action that validates pull request titles against conventional commi

## How it Works

This action uses [Slashgear/action-check-pr-title](https://github.com/Slashgear/action-check-pr-title) to validate PR titles against a conventional commit pattern.
This action runs two checks:

1. **Title format**: Uses [Slashgear/action-check-pr-title](https://github.com/Slashgear/action-check-pr-title) to validate PR titles against a conventional commit pattern.
2. **Jira reference**: Ensures every PR links to a Jira ticket, either via a full URL in the description (`https://montaapp.atlassian.net/browse/PROJECT-123`) or a ticket reference in the title (`[FOO-123]`).

### Skipping the Jira check

Include `nojira` or `no-jira` in the branch name, PR title, or description to skip the Jira check. Automated PRs from Renovate and Dependabot are skipped automatically.

## Title Format

Expand Down
45 changes: 45 additions & 0 deletions .github/actions/pr-title-check/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,48 @@ runs:
with:
regexp: '^(\[(develop|development|staging)\]\s)?(build|chore|ci|docs|feat|feature|fix|perf|refactor|revert|style|test|release|ignore)(\([\w\- ]+\))?!?: (.+)'
helpMessage: "Example: 'feat(app-ui): Add new dashboard component (WEB-123)'"
- name: Check for Jira link in PR description
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const prBody = context.payload.pull_request.body || '';
const prTitle = context.payload.pull_request.title || '';
const branchName = context.payload.pull_request.head.ref || '';
const prAuthor = context.payload.pull_request.user.login || '';

// Skip validation for automated PRs (Renovate, Dependabot, etc.)
const automatedBots = ['renovate[bot]', 'dependabot[bot]'];
if (automatedBots.includes(prAuthor)) {
core.info(`✅ Automated PR from ${prAuthor} - skipping Jira link validation`);
return;
}

// Check if "nojira" or "no-jira" is present in branch name, title, or description (case-insensitive)
const noJiraPattern = /no-?jira/i;
const hasNoJira = noJiraPattern.test(branchName) ||
noJiraPattern.test(prTitle) ||
noJiraPattern.test(prBody);

if (hasNoJira) {
core.info('✅ "nojira"/"no-jira" found - skipping Jira link validation');
return;
}

// Check for Jira link
const jiraLinkPattern = /https:\/\/montaapp\.atlassian\.net\/browse\/[A-Z]+-\d+/;
const jiraTitleRefPattern = /\[[A-Z]+-\d+\]/;

if (jiraLinkPattern.test(prBody)) {
const match = prBody.match(jiraLinkPattern);
core.info(`✅ Found Jira ticket: ${match[0]}`);
} else if (jiraTitleRefPattern.test(prTitle)) {
const match = prTitle.match(jiraTitleRefPattern);
core.info(`✅ Found Jira ticket reference in PR title: ${match[0]}`);
} else {
core.setFailed('❌ No Jira ticket link found in PR description.\n\n' +
'Please add a link to your Jira ticket in the format:\n' +
'https://montaapp.atlassian.net/browse/PROJECT-123\n\n' +
'Example: https://montaapp.atlassian.net/browse/CPONETOPS-568\n\n' +
'Or include a ticket reference in the PR title, e.g. [FOO-123]\n\n' +
'To skip this check, include "nojira" or "no-jira" in the branch name, PR title, or description.');
}
Loading