-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
breaking(sync_issue_to_jira.yaml): Comment Jira issue URL on GitHub i…
…ssue (#15) * Comment Jira issue URL on GitHub issue * Use Jira API instead of Jira automation * Add support for multiple Jira components
- Loading branch information
1 parent
dedec33
commit 650c704
Showing
3 changed files
with
181 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
Workflow file: [sync_issue_to_jira.yaml](sync_issue_to_jira.yaml) | ||
|
||
## Usage | ||
Add `.yaml` file to `.github/workflows/` | ||
```yaml | ||
# Copyright 2023 Canonical Ltd. | ||
# See LICENSE file for licensing details. | ||
name: Sync issue to Jira | ||
|
||
on: | ||
issues: | ||
types: [opened, reopened, closed] | ||
|
||
jobs: | ||
sync: | ||
name: Sync GitHub issue to Jira | ||
uses: canonical/data-platform-workflows/.github/workflows/sync_issue_to_jira.yaml@v2 | ||
with: | ||
jira-base-url: https://warthogs.atlassian.net | ||
jira-project-key: DPE | ||
jira-component-names: mysql-k8s,mysql-router-k8s | ||
secrets: | ||
jira-api-token: ${{ secrets.JIRA_API_TOKEN }} | ||
jira-user-email: ${{ secrets.JIRA_USER_EMAIL }} | ||
permissions: | ||
issues: write # Needed to create GitHub issue comment | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,54 +1,175 @@ | ||
# Copyright 2022 Canonical Ltd. | ||
# Copyright 2023 Canonical Ltd. | ||
# See LICENSE file for licensing details. | ||
|
||
# Context: https://support.atlassian.com/cloud-automation/docs/jira-automation-triggers/#Incoming-webhook | ||
# Source: https://github.com/beliaev-maksim/github-to-jira-automation | ||
# Usage documentation: sync_issue_to_jira.md | ||
|
||
on: | ||
workflow_call: | ||
inputs: | ||
jira-component-name: | ||
description: Name of Jira component (e.g. mysql-k8s) | ||
jira-base-url: | ||
description: URL of Jira instance (e.g. "https://warthogs.atlassian.net"). Do not include trailing slash | ||
required: true | ||
type: string | ||
jira-project-key: | ||
description: Jira project key (e.g. "DPE") | ||
required: true | ||
type: string | ||
jira-component-names: | ||
description: Comma separated list of Jira component names (e.g. "mysql-k8s,mysql-router-k8s") | ||
required: false | ||
type: string | ||
secrets: | ||
jira-webhook-url: | ||
description: Jira webhook URL | ||
jira-api-token: | ||
# https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/ | ||
description: Jira API token | ||
required: true | ||
jira-user-email: | ||
description: User email address for Jira API token | ||
required: true | ||
|
||
|
||
jobs: | ||
sync: | ||
name: Sync issue | ||
create-jira-issue: | ||
name: Create Jira issue | ||
if: ${{ github.event.action == 'opened' }} | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Update Jira ticket | ||
- name: Login to Jira API | ||
uses: atlassian/gajira-login@v3 | ||
env: | ||
# put into env vars to properly escape special bash chars | ||
ISSUE_TITLE: ${{ github.event.issue.title }} | ||
ISSUE_DESCRIPTION: ${{ github.event.issue.body }} | ||
JIRA_BASE_URL: ${{ inputs.jira-base-url }} | ||
JIRA_USER_EMAIL: ${{ secrets.jira-user-email }} | ||
JIRA_API_TOKEN: ${{ secrets.jira-api-token }} | ||
- name: Determine Jira issue type | ||
id: issue-type | ||
run: | | ||
if ${{ contains(github.event.issue.labels.*.name, 'bug') }}; then | ||
ISSUE_TYPE=bug | ||
if ${{ contains(github.event.issue.labels.*.name, 'bug') }} | ||
then | ||
echo "type=Bug" >> $GITHUB_OUTPUT | ||
else | ||
ISSUE_TYPE=story | ||
echo "type=Story" >> $GITHUB_OUTPUT | ||
fi | ||
- name: Create components JSON | ||
id: components | ||
shell: python | ||
run: | | ||
import json | ||
import os | ||
components = [ | ||
{"name": component} | ||
for component in "${{ inputs.jira-component-names }}".split(",") | ||
if component | ||
] | ||
output = f"components={json.dumps(components)}" | ||
print(output) | ||
output_file = os.environ["GITHUB_OUTPUT"] | ||
with open(output_file, "a") as file: | ||
file.write(output) | ||
- name: Create Jira issue | ||
id: create | ||
uses: atlassian/gajira-create@v3 | ||
with: | ||
project: ${{ inputs.jira-project-key }} | ||
issuetype: ${{ steps.issue-type.outputs.type }} | ||
summary: ${{ github.event.issue.title }} | ||
fields: '{"components": ${{ steps.components.outputs.components }}, "assignee": null}' | ||
- name: Add GitHub issue URL to Jira issue | ||
run: | | ||
curl --request POST \ | ||
--url "${{ inputs.jira-base-url }}/rest/api/3/issue/${{ steps.create.outputs.issue }}/remotelink" \ | ||
--user "${{ secrets.jira-user-email }}:${{ secrets.jira-api-token }}" \ | ||
--header "Accept: application/json" \ | ||
--header "Content-Type: application/json" \ | ||
--data '{"object": {"url": "${{ github.event.issue.html_url }}", "title": "Issue #${{ github.event.issue.number }} · ${{ github.repository }}"}}' | ||
- name: Comment Jira issue URL on GitHub issue | ||
run: gh issue comment ${{ github.event.issue.number }} --body "${{ inputs.jira-base-url }}/browse/${{ steps.create.outputs.issue }}" --repo ${{ github.repository }} | ||
env: | ||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
|
||
# send Jira request | ||
update-jira-issue: | ||
name: Update Jira issue | ||
if: ${{ github.event.action != 'opened' }} | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Get Jira issue key | ||
id: get-jira-issue-key | ||
shell: python | ||
run: | | ||
import json | ||
import os | ||
import subprocess | ||
# Canonical doesn't encourage discussions in Jira on public project issues. | ||
# Thus, it is NOT recommended to put description in Jira in order to push conversation to GitHub | ||
# if strongly required, then replace '--arg body ""' with the next line | ||
# --arg body "$ISSUE_DESCRIPTION" | ||
data=$( jq -n \ | ||
--arg title "$ISSUE_TITLE" \ | ||
--arg url '${{ github.event.issue.html_url }}' \ | ||
--arg submitter '${{ github.event.issue.user.login }}' \ | ||
--arg body "" \ | ||
--arg type "$ISSUE_TYPE" \ | ||
--arg action '${{ github.event.action }}' \ | ||
--arg component '${{ inputs.jira-component-name }}' \ | ||
'{title: $title, url: $url, submitter: $submitter, body: $body, type: $type, action: $action, component: $component}' ) | ||
def run_gh_cli(*args): | ||
"""Run command with GitHub CLI""" | ||
output = subprocess.check_output( | ||
[ | ||
"gh", | ||
"api", | ||
"-H", | ||
"Accept: application/vnd.github+json", | ||
"-H", | ||
"X-GitHub-Api-Version: 2022-11-28", | ||
*args, | ||
] | ||
) | ||
return json.loads(output) | ||
curl -X POST -H 'Content-type: application/json' --data "${data}" "${{ secrets.jira-webhook-url }}" | ||
# First five issue comments | ||
github_issue_comments = run_gh_cli( | ||
"${{ github.event.issue.comments_url }}", | ||
"--method", | ||
"GET", | ||
"--raw-field", | ||
"per_page=5", | ||
) | ||
for comment in github_issue_comments: | ||
user = comment["user"] | ||
if user["login"] == "github-actions[bot]": | ||
assert user["id"] == 41898282 | ||
assert user["type"] == "Bot" | ||
# Example: https://warthogs.atlassian.net/browse/DPE-994 | ||
jira_issue_link = comment["body"] | ||
if not jira_issue_link.startswith("${{ inputs.jira-base-url }}"): | ||
continue | ||
# Example: DPE-994 | ||
jira_issue_key = jira_issue_link.split("/")[-1] | ||
output_file = os.environ["GITHUB_OUTPUT"] | ||
with open(output_file, "a") as file: | ||
file.write(f"jira_issue_key={jira_issue_key}") | ||
break | ||
else: | ||
print("Jira issue not found") | ||
exit(1) | ||
env: | ||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
- name: Determine Jira issue transition ID | ||
id: transition-id | ||
run: | | ||
if ${{ github.event.action == 'closed' && github.event.issue.state_reason == 'completed' }} | ||
then | ||
echo "name=Done" >> $GITHUB_OUTPUT | ||
echo "id=61" >> $GITHUB_OUTPUT | ||
elif ${{ github.event.action == 'closed' && github.event.issue.state_reason == 'not_planned' }} | ||
then | ||
echo "name=Rejected" >> $GITHUB_OUTPUT | ||
echo "id=71" >> $GITHUB_OUTPUT | ||
elif ${{ github.event.action == 'reopened'}} | ||
then | ||
echo "name=Untriaged" >> $GITHUB_OUTPUT | ||
echo "id=81" >> $GITHUB_OUTPUT | ||
else | ||
echo "github.event.action=${{ github.event.action }}" | ||
echo "github.event.issue.state_reason=${{ github.event.issue.state_reason }}" | ||
echo "Unknown transition" | ||
exit 1 | ||
fi | ||
- name: Transition issue to ${{ steps.transition-id.outputs.name }} | ||
run: | | ||
curl --request POST \ | ||
--url "${{ inputs.jira-base-url }}/rest/api/3/issue/${{ steps.get-jira-issue-key.outputs.jira_issue_key }}/transitions" \ | ||
--user "${{ secrets.jira-user-email }}:${{ secrets.jira-api-token }}" \ | ||
--header "Accept: application/json" \ | ||
--header "Content-Type: application/json" \ | ||
--data '{"transition": {"id": "${{ steps.transition-id.outputs.id }}"}}' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters