From 330ac477b63b1b158715074d2999965b84b7745e Mon Sep 17 00:00:00 2001 From: jariwiklund Date: Fri, 27 Feb 2026 08:57:29 +0100 Subject: [PATCH] feat: add check-jira-link workflow from server repo Copied from monta-app/server#21276. Validates that PRs include a Jira ticket link, with opt-out support via "nojira"/"no-jira" and automatic skipping for automated bots. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/check-jira-link.yml | 50 +++++++++++++++++++++++++++ README.md | 3 ++ 2 files changed, 53 insertions(+) create mode 100644 .github/workflows/check-jira-link.yml diff --git a/.github/workflows/check-jira-link.yml b/.github/workflows/check-jira-link.yml new file mode 100644 index 0000000..8f8e391 --- /dev/null +++ b/.github/workflows/check-jira-link.yml @@ -0,0 +1,50 @@ +name: 'Check Jira Link in PR' + +on: + pull_request: + types: [opened, edited, reopened, synchronize] + +jobs: + check_jira_link: + runs-on: linux-arm64 + steps: + - 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+/; + + if (!jiraLinkPattern.test(prBody)) { + 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' + + 'To skip this check, include "nojira" or "no-jira" in the branch name, PR title, or description.'); + } else { + const match = prBody.match(jiraLinkPattern); + core.info(`✅ Found Jira ticket: ${match[0]}`); + } diff --git a/README.md b/README.md index d04f2f4..7256198 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,9 @@ This repository contains several reusable workflows designed to streamline the C ### `sonar-cloud.yml` - **Purpose**: Integrates with SonarCloud for analyzing code quality and vulnerabilities. +### `check-jira-link.yml` +- **Purpose**: Validates that pull requests include a link to a Jira ticket in their description. Skips automated PRs (Renovate, Dependabot) and allows opting out by including `nojira` or `no-jira` in the branch name, PR title, or description. + ### `semgrep-security-scan.yml` - **Purpose**: Runs Semgrep static analysis to detect security vulnerabilities, hardcoded secrets, and unsafe coding patterns. Designed primarily for pull requests (PR commenting, diff-aware scanning), but can be called from other event types via `workflow_call` with limited functionality.