Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
28 changes: 28 additions & 0 deletions .github/workflows/tag-release-devcontainer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ on:
required: false
type: string
default: "main"
update_jira:
description: "Whether to update Jira issues during semantic-release"
required: false
type: boolean
default: false
jira_release_prefix:
description: "Release prefix sent to Jira release tagging"
required: false
type: string
default: ""
extra_artifact_name:
description: "An extra artifact to include in the release"
required: false
Expand Down Expand Up @@ -58,6 +68,9 @@ on:
NPM_TOKEN:
required: false
description: "NPM token to publish packages"
EXECUTE_JIRA_LAMBDA_ROLE:
required: false
description: "ARN of the role to assume when executing the Jira update lambda"
jobs:
tag_release:
runs-on: ubuntu-22.04
Expand All @@ -75,6 +88,16 @@ jobs:
- name: copy .tool-versions
run: |
cp /home/vscode/.tool-versions "$HOME/.tool-versions"

- name: connect to dev account to run release notes lambda
uses: aws-actions/configure-aws-credentials@00943011d9042930efac3dcd3a170e4273319bc8
if: ${{ inputs.update_jira == 'true' }}
with:
aws-region: eu-west-2
role-to-assume: ${{ secrets.EXECUTE_JIRA_LAMBDA_ROLE }}
role-session-name: execute-jira-lambda-session
unset-current-credentials: true
Comment thread
anthony-nhs marked this conversation as resolved.

- name: Clone calling repo
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
Expand All @@ -86,6 +109,7 @@ jobs:
with:
repository: NHSDigital/eps-common-workflows
sparse-checkout-cone-mode: false
ref: update_jira
Comment thread
anthony-nhs marked this conversation as resolved.
Outdated
path: common_workflow_config
sparse-checkout: |
package.json
Expand Down Expand Up @@ -191,6 +215,8 @@ jobs:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
MAIN_BRANCH: ${{ inputs.main_branch }}
EXTRA_ASSET: ${{ inputs.extra_artifact_name }}
UPDATE_JIRA: ${{ inputs.update_jira }}
JIRA_RELEASE_PREFIX: ${{ inputs.jira_release_prefix }}

- name: Create semantic release tag
if: ${{ !inputs.dry_run }}
Expand All @@ -201,6 +227,8 @@ jobs:
TAG_FORMAT: ${{ inputs.tag_format }}
MAIN_BRANCH: ${{ inputs.main_branch }}
EXTRA_ASSET: ${{ inputs.extra_artifact_name }}
UPDATE_JIRA: ${{ inputs.update_jira }}
JIRA_RELEASE_PREFIX: ${{ inputs.jira_release_prefix }}
run: |
npx semantic-release --tag-format "${TAG_FORMAT}"

Expand Down
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
},
"author": "NHS Digital",
"license": "MIT",
"dependencies": {
"@aws-sdk/client-cloudformation": "^3.877.0",
"@aws-sdk/client-lambda": "^3.877.0"
},
"devDependencies": {
Comment thread
anthony-nhs marked this conversation as resolved.
Outdated
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/commit-analyzer": "^13.0.1",
Expand Down
76 changes: 76 additions & 0 deletions packages/semantic_release_jira/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
const {
CloudFormationClient,
ListExportsCommand
} = require("@aws-sdk/client-cloudformation")
const { LambdaClient, InvokeCommand } = require("@aws-sdk/client-lambda")

async function createAndTagJiraIssues(version, releasePrefix, jiraTickets) {
try {
const exportName = "release-notes:ReleaseCutLambdaName"
const cloudFormationClient = new CloudFormationClient({})
const lambdaClient = new LambdaClient({})

let functionName
let nextToken

do {
const exportsResponse = await cloudFormationClient.send(
new ListExportsCommand({ NextToken: nextToken })
)

functionName = exportsResponse.Exports?.find(
exportItem => exportItem.Name === exportName
)?.Value

nextToken = exportsResponse.NextToken
} while (!functionName && nextToken)

if (!functionName) {
throw new Error(`Could not resolve CloudFormation export '${exportName}'`)
}

const payload = {
releaseTag: version,
releasePrefix,
tickets: jiraTickets
}

await lambdaClient.send(
new InvokeCommand({
FunctionName: functionName,
Payload: Buffer.from(JSON.stringify(payload))
})
)
} catch (error) {
console.error("Failed to create and tag Jira issues:", error)
}

return { success: true }
Comment thread
anthony-nhs marked this conversation as resolved.
}

module.exports = {
createAndTagJiraIssues,
async success(pluginConfig, context) {
const { nextRelease, commits } = context

const version = nextRelease.version

// Extract Jira tickets from commit messages
const jiraTickets = new Set()

const jiraRegex = /([A-Z]+-\d+)/g

for (const commit of commits) {
const matches = commit.message.match(jiraRegex)
if (matches) {
matches.forEach(t => jiraTickets.add(t))
}
}

const releasePrefix = pluginConfig?.releasePrefix
if (!releasePrefix) {
console.warn("JIRA_RELEASE_PREFIX is not set; invoking release-notes lambda with undefined releasePrefix.")
}
await createAndTagJiraIssues(version, releasePrefix, [...jiraTickets])
}
}
17 changes: 16 additions & 1 deletion release.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ const mainBranch = process.env.MAIN_BRANCH || "main"

const pypiPublish = process.env.PYPI_PUBLISH?.toLowerCase() === 'true' || false
const pypiToken = process.env.PYPI_TOKEN
const updateJira = process.env.UPDATE_JIRA?.toLowerCase() === "true"
const jiraReleasePrefix = process.env.JIRA_RELEASE_PREFIX

if (updateJira && !jiraReleasePrefix) {
// eslint-disable-next-line no-console
console.warn("UPDATE_JIRA is true but JIRA_RELEASE_PREFIX is not set; releasePrefix will be undefined.")
}

module.exports = {
branches: [
Expand Down Expand Up @@ -103,6 +110,14 @@ module.exports = {
failComment: false,
failTitle: false
}
]
],
...(updateJira ? [
[
"./packages/semantic_release_jira",
{
releasePrefix: jiraReleasePrefix
}
]
] : [])
]
}
Loading