From 01fe2135746ca3a3a9989fa78501ace386788d37 Mon Sep 17 00:00:00 2001 From: faridahsalami-nhs <282581465+faridahsalami-nhs@users.noreply.github.com> Date: Tue, 21 Jul 2026 16:52:44 +0100 Subject: [PATCH 01/12] updated PR workflow --- .github/workflows/pr-lint.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr-lint.yaml b/.github/workflows/pr-lint.yaml index 1e647f9..50dfa01 100644 --- a/.github/workflows/pr-lint.yaml +++ b/.github/workflows/pr-lint.yaml @@ -5,16 +5,16 @@ jobs: runs-on: ubuntu-latest steps: - name: Check ticket name conforms to requirements - run: echo ${{ github.event.pull_request.head.ref }} | grep -i -E -q "(apm-[0-9]+)|(apmspii-[0-9]+)|(adz-[0-9]+)|(amb-[0-9]+)|(amp-[0-9]+)|(dependabot\/)" + run: echo ${{ github.event.pull_request.head.ref }} | grep -i -E -q "(apm-[0-9]+)|(apmspii-[0-9]+)|(adz-[0-9]+)|(amb-[0-9]+)|(amp-[0-9]+)|(wpp-[0-9]+)|(dependabot\/)" - name: Grab ticket name - if: contains(github.event.pull_request.head.ref, 'apm-') || contains(github.event.pull_request.head.ref, 'APM-') || contains(github.event.pull_request.head.ref, 'apmspii-') || contains(github.event.pull_request.head.ref, 'APMSPII-') || contains(github.event.pull_request.head.ref, 'adz-') || contains(github.event.pull_request.head.ref, 'ADZ-') || contains(github.event.pull_request.head.ref, 'amb-') || contains(github.event.pull_request.head.ref, 'AMB-') || contains(github.event.pull_request.head.ref, 'amp-') || contains(github.event.pull_request.head.ref, 'AMP-') - run: echo ::set-env name=TICKET_NAME::$(echo ${{ github.event.pull_request.head.ref }} | grep -i -o '\(apm-[0-9]\+\)\|\(apmspii-[0-9]\+\)\|\(adz-[0-9]\+\)|\(amb-[0-9]\+\)|\(amp-[0-9]\+\)' | tr '[:lower:]' '[:upper:]') + if: contains(github.event.pull_request.head.ref, 'apm-') || contains(github.event.pull_request.head.ref, 'APM-') || contains(github.event.pull_request.head.ref, 'apmspii-') || contains(github.event.pull_request.head.ref, 'APMSPII-') || contains(github.event.pull_request.head.ref, 'adz-') || contains(github.event.pull_request.head.ref, 'ADZ-') || contains(github.event.pull_request.head.ref, 'amb-') || contains(github.event.pull_request.head.ref, 'AMB-') || contains(github.event.pull_request.head.ref, 'amp-') || contains(github.event.pull_request.head.ref, 'AMP-')|| contains(github.event.pull_request.head.ref, 'wpp-') || contains(github.event.pull_request.head.ref, 'WPP-') + run: echo ::set-env name=TICKET_NAME::$(echo ${{ github.event.pull_request.head.ref }} | grep -i -o '\(apm-[0-9]\+\)\|\(apmspii-[0-9]\+\)\|\(adz-[0-9]\+\)|\(amb-[0-9]\+\)|\(amp-[0-9]\+\)|\(wpp-[0-9]\+\)' | tr '[:lower:]' '[:upper:]') env: ACTIONS_ALLOW_UNSECURE_COMMANDS: true - name: Comment on PR with link to JIRA ticket - if: contains(github.event.pull_request.head.ref, 'apm-') || contains(github.event.pull_request.head.ref, 'APM-') || contains(github.event.pull_request.head.ref, 'apmspii-') || contains(github.event.pull_request.head.ref, 'APMSPII-') || contains(github.event.pull_request.head.ref, 'adz-') || contains(github.event.pull_request.head.ref, 'ADZ-') || contains(github.event.pull_request.head.ref, 'amb-') || contains(github.event.pull_request.head.ref, 'AMB-') || contains(github.event.pull_request.head.ref, 'amp-') || contains(github.event.pull_request.head.ref, 'AMP-') + if: contains(github.event.pull_request.head.ref, 'apm-') || contains(github.event.pull_request.head.ref, 'APM-') || contains(github.event.pull_request.head.ref, 'apmspii-') || contains(github.event.pull_request.head.ref, 'APMSPII-') || contains(github.event.pull_request.head.ref, 'adz-') || contains(github.event.pull_request.head.ref, 'ADZ-') || contains(github.event.pull_request.head.ref, 'amb-') || contains(github.event.pull_request.head.ref, 'AMB-') || contains(github.event.pull_request.head.ref, 'amp-') || contains(github.event.pull_request.head.ref, 'AMP-') || contains(github.event.pull_request.head.ref, 'wpp-') || contains(github.event.pull_request.head.ref, 'WPP-') uses: unsplash/comment-on-pr@master env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From c4af4ada3f86859cf78aeaa59b9f73d6a8b8efa8 Mon Sep 17 00:00:00 2001 From: faridahsalami-nhs <282581465+faridahsalami-nhs@users.noreply.github.com> Date: Tue, 21 Jul 2026 17:10:29 +0100 Subject: [PATCH 02/12] updated deprecated env_var and regex for icket name --- .github/workflows/pr-lint.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-lint.yaml b/.github/workflows/pr-lint.yaml index 50dfa01..eda169e 100644 --- a/.github/workflows/pr-lint.yaml +++ b/.github/workflows/pr-lint.yaml @@ -9,9 +9,9 @@ jobs: - name: Grab ticket name if: contains(github.event.pull_request.head.ref, 'apm-') || contains(github.event.pull_request.head.ref, 'APM-') || contains(github.event.pull_request.head.ref, 'apmspii-') || contains(github.event.pull_request.head.ref, 'APMSPII-') || contains(github.event.pull_request.head.ref, 'adz-') || contains(github.event.pull_request.head.ref, 'ADZ-') || contains(github.event.pull_request.head.ref, 'amb-') || contains(github.event.pull_request.head.ref, 'AMB-') || contains(github.event.pull_request.head.ref, 'amp-') || contains(github.event.pull_request.head.ref, 'AMP-')|| contains(github.event.pull_request.head.ref, 'wpp-') || contains(github.event.pull_request.head.ref, 'WPP-') - run: echo ::set-env name=TICKET_NAME::$(echo ${{ github.event.pull_request.head.ref }} | grep -i -o '\(apm-[0-9]\+\)\|\(apmspii-[0-9]\+\)\|\(adz-[0-9]\+\)|\(amb-[0-9]\+\)|\(amp-[0-9]\+\)|\(wpp-[0-9]\+\)' | tr '[:lower:]' '[:upper:]') - env: - ACTIONS_ALLOW_UNSECURE_COMMANDS: true + run: | + TICKET_NAME=$(echo "${{ github.event.pull_request.head.ref }}" | grep -i -E -o '(apm-[0-9]+|apmspii-[0-9]+|adz-[0-9]+|amb-[0-9]+|amp-[0-9]+|wpp-[0-9]+)' | tr '[:lower:]' '[:upper:]') + echo "TICKET_NAME=$TICKET_NAME" >> "$GITHUB_ENV" - name: Comment on PR with link to JIRA ticket if: contains(github.event.pull_request.head.ref, 'apm-') || contains(github.event.pull_request.head.ref, 'APM-') || contains(github.event.pull_request.head.ref, 'apmspii-') || contains(github.event.pull_request.head.ref, 'APMSPII-') || contains(github.event.pull_request.head.ref, 'adz-') || contains(github.event.pull_request.head.ref, 'ADZ-') || contains(github.event.pull_request.head.ref, 'amb-') || contains(github.event.pull_request.head.ref, 'AMB-') || contains(github.event.pull_request.head.ref, 'amp-') || contains(github.event.pull_request.head.ref, 'AMP-') || contains(github.event.pull_request.head.ref, 'wpp-') || contains(github.event.pull_request.head.ref, 'WPP-') From b3ac5d7c5eec6fa67cdb69636a1901c04edf0759 Mon Sep 17 00:00:00 2001 From: Simeon Parris <275962675+simeonparris-nhs@users.noreply.github.com> Date: Wed, 22 Jul 2026 16:48:58 +0100 Subject: [PATCH 03/12] remove unused jira ticket prefixes from the pr-lint workflow --- .github/workflows/pr-lint.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr-lint.yaml b/.github/workflows/pr-lint.yaml index eda169e..d37beab 100644 --- a/.github/workflows/pr-lint.yaml +++ b/.github/workflows/pr-lint.yaml @@ -5,16 +5,16 @@ jobs: runs-on: ubuntu-latest steps: - name: Check ticket name conforms to requirements - run: echo ${{ github.event.pull_request.head.ref }} | grep -i -E -q "(apm-[0-9]+)|(apmspii-[0-9]+)|(adz-[0-9]+)|(amb-[0-9]+)|(amp-[0-9]+)|(wpp-[0-9]+)|(dependabot\/)" + run: echo ${{ github.event.pull_request.head.ref }} | grep -i -E -q "(wpp-[0-9]+)|(dependabot\/)" - name: Grab ticket name - if: contains(github.event.pull_request.head.ref, 'apm-') || contains(github.event.pull_request.head.ref, 'APM-') || contains(github.event.pull_request.head.ref, 'apmspii-') || contains(github.event.pull_request.head.ref, 'APMSPII-') || contains(github.event.pull_request.head.ref, 'adz-') || contains(github.event.pull_request.head.ref, 'ADZ-') || contains(github.event.pull_request.head.ref, 'amb-') || contains(github.event.pull_request.head.ref, 'AMB-') || contains(github.event.pull_request.head.ref, 'amp-') || contains(github.event.pull_request.head.ref, 'AMP-')|| contains(github.event.pull_request.head.ref, 'wpp-') || contains(github.event.pull_request.head.ref, 'WPP-') + if: contains(github.event.pull_request.head.ref, 'wpp-') || contains(github.event.pull_request.head.ref, 'WPP-') run: | - TICKET_NAME=$(echo "${{ github.event.pull_request.head.ref }}" | grep -i -E -o '(apm-[0-9]+|apmspii-[0-9]+|adz-[0-9]+|amb-[0-9]+|amp-[0-9]+|wpp-[0-9]+)' | tr '[:lower:]' '[:upper:]') + TICKET_NAME=$(echo "${{ github.event.pull_request.head.ref }}" | grep -i -E -o '(wpp-[0-9]+)' | tr '[:lower:]' '[:upper:]') echo "TICKET_NAME=$TICKET_NAME" >> "$GITHUB_ENV" - name: Comment on PR with link to JIRA ticket - if: contains(github.event.pull_request.head.ref, 'apm-') || contains(github.event.pull_request.head.ref, 'APM-') || contains(github.event.pull_request.head.ref, 'apmspii-') || contains(github.event.pull_request.head.ref, 'APMSPII-') || contains(github.event.pull_request.head.ref, 'adz-') || contains(github.event.pull_request.head.ref, 'ADZ-') || contains(github.event.pull_request.head.ref, 'amb-') || contains(github.event.pull_request.head.ref, 'AMB-') || contains(github.event.pull_request.head.ref, 'amp-') || contains(github.event.pull_request.head.ref, 'AMP-') || contains(github.event.pull_request.head.ref, 'wpp-') || contains(github.event.pull_request.head.ref, 'WPP-') + if: contains(github.event.pull_request.head.ref, 'wpp-') || contains(github.event.pull_request.head.ref, 'WPP-') uses: unsplash/comment-on-pr@master env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 9c135b6fc2d1ffe83fa9a38e19670241f465f645 Mon Sep 17 00:00:00 2001 From: Simeon Parris <275962675+simeonparris-nhs@users.noreply.github.com> Date: Wed, 22 Jul 2026 17:17:37 +0100 Subject: [PATCH 04/12] combine check ticket and grab ticket steps from the pr-lint workflow --- .github/workflows/pr-lint.yaml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pr-lint.yaml b/.github/workflows/pr-lint.yaml index d37beab..fadfc47 100644 --- a/.github/workflows/pr-lint.yaml +++ b/.github/workflows/pr-lint.yaml @@ -5,13 +5,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Check ticket name conforms to requirements - run: echo ${{ github.event.pull_request.head.ref }} | grep -i -E -q "(wpp-[0-9]+)|(dependabot\/)" - - - name: Grab ticket name - if: contains(github.event.pull_request.head.ref, 'wpp-') || contains(github.event.pull_request.head.ref, 'WPP-') run: | - TICKET_NAME=$(echo "${{ github.event.pull_request.head.ref }}" | grep -i -E -o '(wpp-[0-9]+)' | tr '[:lower:]' '[:upper:]') - echo "TICKET_NAME=$TICKET_NAME" >> "$GITHUB_ENV" + PR_REF=${{ github.event.pull_request.head.ref }} + VALID_TICKET=$(echo "$PR_REF" | grep -i -E -o '(wpp-[0-9]+)' | tr '[:lower:]' '[:upper:]') + if [ -z "$VALID_TICKET" ]; then + echo "TICKET_NAME=$VALID_TICKET" >> "$GITHUB_ENV" + else + # dependabot branches are also valid, but won't have Jira ticket numbers + echo "$PR_REF" | grep -i -E -q "(dependabot\/)" + fi - name: Comment on PR with link to JIRA ticket if: contains(github.event.pull_request.head.ref, 'wpp-') || contains(github.event.pull_request.head.ref, 'WPP-') From 20de07a67963064d6370aec922cb3a8f7684de96 Mon Sep 17 00:00:00 2001 From: Simeon Parris <275962675+simeonparris-nhs@users.noreply.github.com> Date: Wed, 22 Jul 2026 18:04:22 +0100 Subject: [PATCH 05/12] replace unsplash/comment-on-pr with actions/github-script in the pr-lint workflow --- .github/workflows/pr-lint.yaml | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pr-lint.yaml b/.github/workflows/pr-lint.yaml index fadfc47..78feb90 100644 --- a/.github/workflows/pr-lint.yaml +++ b/.github/workflows/pr-lint.yaml @@ -16,12 +16,19 @@ jobs: fi - name: Comment on PR with link to JIRA ticket - if: contains(github.event.pull_request.head.ref, 'wpp-') || contains(github.event.pull_request.head.ref, 'WPP-') - uses: unsplash/comment-on-pr@master - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + if: env.TICKET_NAME != '' + uses: actions/github-script@v7 with: - msg: | - This branch is work on a ticket in the NHS Digital APM JIRA Project. Here's a handy link to the ticket: - # [${{ env.TICKET_NAME }}](https://nhsd-jira.digital.nhs.uk/browse/${{ env.TICKET_NAME}}) + script: | + const ticket = process.env.TICKET_NAME; + const message = ` + This branch is work on a ticket in the NHS Digital WPP JIRA Project. Here's a handy link to the ticket: + # [${ticket}](https://nhsd-jira.digital.nhs.uk/browse/${ticket}) + `; + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + body: message + }); From 4f6adb33ca875c096e1003b5c0600236bf3a2a97 Mon Sep 17 00:00:00 2001 From: Simeon Parris <275962675+simeonparris-nhs@users.noreply.github.com> Date: Thu, 23 Jul 2026 12:19:31 +0100 Subject: [PATCH 06/12] add steps for adding and removing warning comments for use when a Jira ticket number has not been included in the branch --- .github/workflows/pr-lint.yaml | 85 ++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-lint.yaml b/.github/workflows/pr-lint.yaml index 78feb90..e63d842 100644 --- a/.github/workflows/pr-lint.yaml +++ b/.github/workflows/pr-lint.yaml @@ -10,18 +10,58 @@ jobs: VALID_TICKET=$(echo "$PR_REF" | grep -i -E -o '(wpp-[0-9]+)' | tr '[:lower:]' '[:upper:]') if [ -z "$VALID_TICKET" ]; then echo "TICKET_NAME=$VALID_TICKET" >> "$GITHUB_ENV" + echo "$PR_REF" | grep -i -E -q "(dependabot\/)"; then + echo "DEPENDABOT PR - NO JIRA TICKET REQUIRED" else - # dependabot branches are also valid, but won't have Jira ticket numbers - echo "$PR_REF" | grep -i -E -q "(dependabot\/)" + echo "MISSING_JIRA_TICKET=true" >> "$GITHUB_ENV" fi + - name: Check for Existing Jira Ticket Comments + id: find-comments + uses: actions/github-script@v7 + with: + script: | + const comments = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + }); + + const ticketNumberCommentIds = comments.data.filter(comment => comment.body.find('')).map(c => c.id); + const warningCommentIds = comments.data.filter(comment => comment.body.find('')).map(c => c.id); + + core.setOutput('ticket-number-comment-ids', JSON.stringify(ticketNumberCommentIds)); + core.setOutput('warning-comment-ids', JSON.stringify(warningCommentIds)); + + - name: Comment on PR with Warning + if: env.MISSING_JIRA_TICKET == true && fromJSON(steps.find-comments.warning-comment-ids).length < 1 + uses: actions/github-script@v7 + with: + script: | + const message = ` + + ⚠️ This branch is missing its Jira Ticket number. + Please rename the branch to include it. + `; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + body: message + }); + + // fail workflow early when warning comment is posted + core.setFailed('No Jira ticket number found in branch name'); + - name: Comment on PR with link to JIRA ticket - if: env.TICKET_NAME != '' + if: env.TICKET_NAME != '' && fromJSON(steps.find-comments.ticket-number-comment-ids).length < 1 uses: actions/github-script@v7 with: script: | const ticket = process.env.TICKET_NAME; const message = ` + This branch is work on a ticket in the NHS Digital WPP JIRA Project. Here's a handy link to the ticket: # [${ticket}](https://nhsd-jira.digital.nhs.uk/browse/${ticket}) `; @@ -32,3 +72,42 @@ jobs: issue_number: context.payload.pull_request.number, body: message }); + + - name: Remove Unnecessary Warning Comments + uses: actions/github-script@v7 + with: + script: | + const comments = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + }).data; + + const warningComments = comments.filter(comment => comment.body.find('')); + const ticketComments = comments.filter(comment => comment.body.find('')); + + if (warningComments.length > 0 && ticketComments > 0) { + // PR now has a ticket number in its branch name, and a corresponding comment + // so remove any previous warning comments + for (warning in warningComments) { + await github.rest.issues.deleteComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: warning.id + }); + } + } + + if (ticketComments > 1) { + // PR has more than one comment relating to the Jira ticket number + // so remove all but the most recent one + const commentsToDelete = ticketComments.slice(0, -1); + + for (const comment of commentsToDelete) { + await github.rest.issues.deleteComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: comment.id + }); + } + } From a843450745f4e2b35e58b35350ddcaeea2c01d5a Mon Sep 17 00:00:00 2001 From: Simeon Parris <275962675+simeonparris-nhs@users.noreply.github.com> Date: Thu, 23 Jul 2026 13:42:50 +0100 Subject: [PATCH 07/12] correct if else statement logic in check ticket name step --- .github/workflows/pr-lint.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-lint.yaml b/.github/workflows/pr-lint.yaml index e63d842..bea267c 100644 --- a/.github/workflows/pr-lint.yaml +++ b/.github/workflows/pr-lint.yaml @@ -8,9 +8,10 @@ jobs: run: | PR_REF=${{ github.event.pull_request.head.ref }} VALID_TICKET=$(echo "$PR_REF" | grep -i -E -o '(wpp-[0-9]+)' | tr '[:lower:]' '[:upper:]') - if [ -z "$VALID_TICKET" ]; then + DEPENDABOT_PR=$(echo "$PR_REF" | grep -i -E -o '(dependabot\/)'') + if [ -n "$VALID_TICKET" ]; then echo "TICKET_NAME=$VALID_TICKET" >> "$GITHUB_ENV" - echo "$PR_REF" | grep -i -E -q "(dependabot\/)"; then + elif [ -n "$DEPENDABOT_PR" ]; then echo "DEPENDABOT PR - NO JIRA TICKET REQUIRED" else echo "MISSING_JIRA_TICKET=true" >> "$GITHUB_ENV" From 0713eac77d77af2844a3c41d05e6b57ce8507384 Mon Sep 17 00:00:00 2001 From: Simeon Parris <275962675+simeonparris-nhs@users.noreply.github.com> Date: Thu, 23 Jul 2026 13:47:45 +0100 Subject: [PATCH 08/12] simplify steps in pr-lint.yaml --- .github/workflows/pr-lint.yaml | 80 ++++++++-------------------------- 1 file changed, 19 insertions(+), 61 deletions(-) diff --git a/.github/workflows/pr-lint.yaml b/.github/workflows/pr-lint.yaml index bea267c..7c1d8d2 100644 --- a/.github/workflows/pr-lint.yaml +++ b/.github/workflows/pr-lint.yaml @@ -17,32 +17,16 @@ jobs: echo "MISSING_JIRA_TICKET=true" >> "$GITHUB_ENV" fi - - name: Check for Existing Jira Ticket Comments - id: find-comments - uses: actions/github-script@v7 - with: - script: | - const comments = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.payload.pull_request.number, - }); - - const ticketNumberCommentIds = comments.data.filter(comment => comment.body.find('')).map(c => c.id); - const warningCommentIds = comments.data.filter(comment => comment.body.find('')).map(c => c.id); - - core.setOutput('ticket-number-comment-ids', JSON.stringify(ticketNumberCommentIds)); - core.setOutput('warning-comment-ids', JSON.stringify(warningCommentIds)); - - name: Comment on PR with Warning - if: env.MISSING_JIRA_TICKET == true && fromJSON(steps.find-comments.warning-comment-ids).length < 1 + if: env.MISSING_JIRA_TICKET == 'true' uses: actions/github-script@v7 with: script: | const message = ` - - ⚠️ This branch is missing its Jira Ticket number. - Please rename the branch to include it. + ⚠️ This branch name is missing its Jira Ticket number. + Please rename the branch to include the ticket number. + ex. feature/wpp-1234-spec-changes-for-abc + Then close this PR and open a new one from the branch with the corrected name. `; await github.rest.issues.createComment({ @@ -56,10 +40,23 @@ jobs: core.setFailed('No Jira ticket number found in branch name'); - name: Comment on PR with link to JIRA ticket - if: env.TICKET_NAME != '' && fromJSON(steps.find-comments.ticket-number-comment-ids).length < 1 + if: env.TICKET_NAME != '' uses: actions/github-script@v7 with: script: | + const comments = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + }); + + const ticketNumberComments = comments.data.filter(comment => comment.body.find('')) + + if (ticketNumberComments.length > 0) { + // linked ticket comment has already been posted, so exit early + process.exit(0); + } + const ticket = process.env.TICKET_NAME; const message = ` @@ -73,42 +70,3 @@ jobs: issue_number: context.payload.pull_request.number, body: message }); - - - name: Remove Unnecessary Warning Comments - uses: actions/github-script@v7 - with: - script: | - const comments = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.payload.pull_request.number, - }).data; - - const warningComments = comments.filter(comment => comment.body.find('')); - const ticketComments = comments.filter(comment => comment.body.find('')); - - if (warningComments.length > 0 && ticketComments > 0) { - // PR now has a ticket number in its branch name, and a corresponding comment - // so remove any previous warning comments - for (warning in warningComments) { - await github.rest.issues.deleteComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: warning.id - }); - } - } - - if (ticketComments > 1) { - // PR has more than one comment relating to the Jira ticket number - // so remove all but the most recent one - const commentsToDelete = ticketComments.slice(0, -1); - - for (const comment of commentsToDelete) { - await github.rest.issues.deleteComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: comment.id - }); - } - } From e71ac047476cbec6d28b700a47871d43f3b2cd08 Mon Sep 17 00:00:00 2001 From: Simeon Parris <275962675+simeonparris-nhs@users.noreply.github.com> Date: Thu, 23 Jul 2026 14:02:24 +0100 Subject: [PATCH 09/12] correct workflow error caused by extra apostrophe --- .github/workflows/pr-lint.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-lint.yaml b/.github/workflows/pr-lint.yaml index 7c1d8d2..b2efa31 100644 --- a/.github/workflows/pr-lint.yaml +++ b/.github/workflows/pr-lint.yaml @@ -5,10 +5,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Check ticket name conforms to requirements + env: + PR_REF: ${{ github.event.pull_request.head.ref }} run: | - PR_REF=${{ github.event.pull_request.head.ref }} VALID_TICKET=$(echo "$PR_REF" | grep -i -E -o '(wpp-[0-9]+)' | tr '[:lower:]' '[:upper:]') - DEPENDABOT_PR=$(echo "$PR_REF" | grep -i -E -o '(dependabot\/)'') + DEPENDABOT_PR=$(echo "$PR_REF" | grep -i -E -o '(dependabot\/)') if [ -n "$VALID_TICKET" ]; then echo "TICKET_NAME=$VALID_TICKET" >> "$GITHUB_ENV" elif [ -n "$DEPENDABOT_PR" ]; then From 3b9545339cbfd17d3785bca59fec3b506f6ed827 Mon Sep 17 00:00:00 2001 From: Simeon Parris <275962675+simeonparris-nhs@users.noreply.github.com> Date: Thu, 23 Jul 2026 15:53:34 +0100 Subject: [PATCH 10/12] fix issue with comment filtering in the comment on pr with ticket number step --- .github/workflows/pr-lint.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-lint.yaml b/.github/workflows/pr-lint.yaml index b2efa31..e319a9c 100644 --- a/.github/workflows/pr-lint.yaml +++ b/.github/workflows/pr-lint.yaml @@ -51,7 +51,7 @@ jobs: issue_number: context.payload.pull_request.number, }); - const ticketNumberComments = comments.data.filter(comment => comment.body.find('')) + const ticketNumberComments = comments.data.filter(comment => (comment.body || '').includes('')) if (ticketNumberComments.length > 0) { // linked ticket comment has already been posted, so exit early From 074d477eacbd94edc80cbb90cebd84ecaa2d49d5 Mon Sep 17 00:00:00 2001 From: Simeon Parris <275962675+simeonparris-nhs@users.noreply.github.com> Date: Thu, 23 Jul 2026 16:32:01 +0100 Subject: [PATCH 11/12] refactor check ticket name step to use built-in bash commands rather than grep for pattern matching --- .github/workflows/pr-lint.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr-lint.yaml b/.github/workflows/pr-lint.yaml index e319a9c..21c3832 100644 --- a/.github/workflows/pr-lint.yaml +++ b/.github/workflows/pr-lint.yaml @@ -8,11 +8,12 @@ jobs: env: PR_REF: ${{ github.event.pull_request.head.ref }} run: | - VALID_TICKET=$(echo "$PR_REF" | grep -i -E -o '(wpp-[0-9]+)' | tr '[:lower:]' '[:upper:]') - DEPENDABOT_PR=$(echo "$PR_REF" | grep -i -E -o '(dependabot\/)') - if [ -n "$VALID_TICKET" ]; then - echo "TICKET_NAME=$VALID_TICKET" >> "$GITHUB_ENV" - elif [ -n "$DEPENDABOT_PR" ]; then + PR_REF_LC="${PR_REF,,}" # lowercase copy for case-insensitive matching + + if [[ "$PR_REF_LC" =~ (wpp-[0-9]+) ]]; then + TICKET_NAME="${BASH_REMATCH[1]^^}" # convert matched ticket to uppercase + echo "TICKET_NAME=$TICKET_NAME" >> "$GITHUB_ENV" + elif [[ "$PR_REF_LC" == dependabot/* ]]; then echo "DEPENDABOT PR - NO JIRA TICKET REQUIRED" else echo "MISSING_JIRA_TICKET=true" >> "$GITHUB_ENV" From 0982727666b1412c5bb702f91c65b6c647721636 Mon Sep 17 00:00:00 2001 From: Simeon Parris <275962675+simeonparris-nhs@users.noreply.github.com> Date: Wed, 29 Jul 2026 18:51:39 +0100 Subject: [PATCH 12/12] update pr-lint workflow to resemble validate-branch-name actions from shared action repo as shared actions cannot currently be used in this repo --- .github/workflows/pr-lint.yaml | 143 +++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 60 deletions(-) diff --git a/.github/workflows/pr-lint.yaml b/.github/workflows/pr-lint.yaml index 21c3832..725c196 100644 --- a/.github/workflows/pr-lint.yaml +++ b/.github/workflows/pr-lint.yaml @@ -4,71 +4,94 @@ jobs: link-ticket: runs-on: ubuntu-latest steps: - - name: Check ticket name conforms to requirements + - name: Validate branch name + id: validate env: - PR_REF: ${{ github.event.pull_request.head.ref }} + BRANCH_NAME: ${{ github.head_ref }} + ALLOWED_BRANCH_REGEX: '^(feat|feature|chore|spike|bugfix)\/[A-Z][A-Z0-9]+-[0-9]+(-[a-zA-Z0-9]+)*$|^(release|hotfix|revert|dependabot)\/.+$' run: | - PR_REF_LC="${PR_REF,,}" # lowercase copy for case-insensitive matching - - if [[ "$PR_REF_LC" =~ (wpp-[0-9]+) ]]; then - TICKET_NAME="${BASH_REMATCH[1]^^}" # convert matched ticket to uppercase - echo "TICKET_NAME=$TICKET_NAME" >> "$GITHUB_ENV" - elif [[ "$PR_REF_LC" == dependabot/* ]]; then - echo "DEPENDABOT PR - NO JIRA TICKET REQUIRED" + if [[ "$BRANCH_NAME" =~ $ALLOWED_BRANCH_REGEX ]]; then + echo "passed=true" >> "$GITHUB_OUTPUT" else - echo "MISSING_JIRA_TICKET=true" >> "$GITHUB_ENV" + echo "passed=false" >> "$GITHUB_OUTPUT" fi - - name: Comment on PR with Warning - if: env.MISSING_JIRA_TICKET == 'true' - uses: actions/github-script@v7 - with: - script: | - const message = ` - ⚠️ This branch name is missing its Jira Ticket number. - Please rename the branch to include the ticket number. - ex. feature/wpp-1234-spec-changes-for-abc - Then close this PR and open a new one from the branch with the corrected name. - `; - - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.payload.pull_request.number, - body: message - }); - - // fail workflow early when warning comment is posted - core.setFailed('No Jira ticket number found in branch name'); - - - name: Comment on PR with link to JIRA ticket - if: env.TICKET_NAME != '' - uses: actions/github-script@v7 - with: - script: | - const comments = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.payload.pull_request.number, - }); - - const ticketNumberComments = comments.data.filter(comment => (comment.body || '').includes('')) + - name: Extract Jira ticket + id: jira + if: ${{ steps.validate.outputs.passed == 'true' }} + env: + BRANCH_NAME: ${{ github.head_ref }} + TICKET_REGEX: ([Ww][Pp][Pp]-[0-9]+) + run: | + if [[ "$BRANCH_NAME" =~ $TICKET_REGEX ]]; then + TICKET="${BASH_REMATCH[1]^^}" # convert matched ticket to uppercase + echo "ticket=$TICKET" >> "$GITHUB_OUTPUT" + else + echo "ticket='" >> "$GITHUB_OUTPUT" + fi - if (ticketNumberComments.length > 0) { - // linked ticket comment has already been posted, so exit early - process.exit(0); - } + - name: Manage PR Comment + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + PR_NUMBER: ${{ github.event.pull_request.number }} + BRANCH_NAME: ${{ github.head_ref }} + PASSED: ${{ steps.validate.outputs.passed }} + REASON: ${{ steps.validate.outputs.reason }} + JIRA_TICKET: ${{ steps.jira.outputs.ticket }} + run: | + if [[ -z "$PR_NUMBER" ]]; then exit 0; fi + + MARKER="" + + # create a Jira ticket link to add to the comment when one matching the regex is present in the branch name + if [[ -n "$JIRA_TICKET" ]]; then + JIRA_LINK="Jira ticket: [${JIRA_TICKET}](https://nhsd-jira.digital.nhs.uk/browse/${JIRA_TICKET})" + else + JIRA_LINK="" + fi + + if [[ "$PASSED" == "true" ]]; then + # read line is correctly indented; it needs to be one tab ahead of the rest of the heredoc lines + read -r -d '' BODY </-\` + + Ensure JIRA ticket key is included. Allowed prefixes: feat, feature, chore, spike, hotfix, bugfix, release, revert + + \`\`\` + ${BRANCH_NAME} + \`\`\` + EOF + fi + + # Find and delete existing comment with marker + COMMENT_ID=$(gh api "repos/$GH_REPO/issues/$PR_NUMBER/comments" --jq ".[] | select(.body | contains(\"${MARKER}\")) | .id" | head -1) + if [[ -n "$COMMENT_ID" ]]; then + gh api -X DELETE "repos/$GH_REPO/issues/comments/$COMMENT_ID" + fi - const ticket = process.env.TICKET_NAME; - const message = ` - - This branch is work on a ticket in the NHS Digital WPP JIRA Project. Here's a handy link to the ticket: - # [${ticket}](https://nhsd-jira.digital.nhs.uk/browse/${ticket}) - `; + # Post new comment + gh pr comment "$PR_NUMBER" --body "$BODY" - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.payload.pull_request.number, - body: message - }); + - name: Fail if validation failed + if: steps.validate.outputs.passed == 'false' + shell: bash + run: exit 1