Skip to content

Commit b4f1dee

Browse files
committed
Copying jira release notes script / workflow updates from the ios repo
1 parent e6f0db6 commit b4f1dee

5 files changed

Lines changed: 42 additions & 130 deletions

File tree

.github/scripts/jira-get-release-notes/README.md

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,13 @@ Fetches release notes from Jira issues.
44

55
## Prerequisites
66

7-
- Python dev environment - use [uv](https://github.com/astral-sh/uv)
87
- Jira API token. Generate one at: https://id.atlassian.com/manage-profile/security/api-tokens
9-
- Install dependencies:
10-
11-
```bash
12-
uv pip install -r pyproject.toml
13-
```
8+
- Jira cloud ID. Can be retrieved from the `tenant_info` endpoint, e.g.: `https://<my-site-name>.atlassian.net/_edge/tenant_info`
149

1510
## Usage
1611

1712
```bash
18-
./jira_release_notes.py RELEASE-1762 example@example.com T0k3n123
13+
./jira_release_notes.py RELEASE-1762 jira-cloud-id example@example.com T0k3n123
1914
```
2015

2116
# Output Format

.github/scripts/jira-get-release-notes/jira_release_notes.py

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
#!/usr/bin/env python3
2+
# Requires Python 3.9+
3+
"""Fetch release notes from a Jira issue."""
24

3-
import sys
5+
import argparse
46
import base64
57
import json
6-
import requests
8+
import sys
9+
from pathlib import Path
10+
from urllib.error import HTTPError
11+
from urllib.request import Request, urlopen
712

8-
SCRIPT_NAME = "jira_release_notes.py"
13+
SCRIPT_NAME = Path(__file__).name
914

1015
def extract_text_from_content(content):
1116
if isinstance(content, list):
@@ -63,32 +68,43 @@ def parse_release_notes(response_json):
6368
print(f"[{SCRIPT_NAME}] Error parsing release notes: {str(e)}", file=sys.stderr)
6469
return ''
6570

71+
def parse_args():
72+
parser = argparse.ArgumentParser(
73+
description=__doc__,
74+
)
75+
parser.add_argument("issue_id", help="RELEASE issue ID to fetch release notes from")
76+
parser.add_argument("jira_cloud_id", help="Atlassian Cloud ID - Can be retrieved from the `tenant_info` endpoint, e.g.: `https://<my-site-name>.atlassian.net/_edge/tenant_info`")
77+
parser.add_argument("jira_email", help="Email used to create the API token")
78+
parser.add_argument("jira_api_token", help="Jira API token - Generate one at: https://id.atlassian.com/manage-profile/security/api-tokens")
79+
return parser.parse_args()
80+
6681
def main():
67-
if len(sys.argv) != 4:
68-
print(f"Usage: {sys.argv[0]} <issue_id> <jira_email> <jira_api_token>")
69-
sys.exit(1)
82+
args = parse_args()
7083

71-
jira_issue_id = sys.argv[1]
72-
jira_email = sys.argv[2]
73-
jira_api_token = sys.argv[3]
74-
jira_base_url = "https://bitwarden.atlassian.net"
84+
jira_issue_id = args.issue_id
85+
jira_cloud_id = args.jira_cloud_id
86+
jira_email = args.jira_email
87+
jira_api_token = args.jira_api_token
88+
jira_base_url = "https://api.atlassian.com/ex/jira"
7589

7690
auth = base64.b64encode(f"{jira_email}:{jira_api_token}".encode()).decode()
77-
headers = {
78-
"Authorization": f"Basic {auth}",
79-
"Content-Type": "application/json"
80-
}
81-
82-
response = requests.get(
83-
f"{jira_base_url}/rest/api/3/issue/{jira_issue_id}",
84-
headers=headers
91+
request = Request(
92+
f"{jira_base_url}/{jira_cloud_id}/rest/api/3/issue/{jira_issue_id}",
93+
headers={
94+
"Authorization": f"Basic {auth}",
95+
"Content-Type": "application/json"
96+
}
8597
)
8698

87-
if response.status_code != 200:
88-
print(f"[{SCRIPT_NAME}] Error fetching Jira issue ({jira_issue_id}). Status code: {response.status_code}. Msg: {response.text}", file=sys.stderr)
99+
try:
100+
with urlopen(request) as response:
101+
response_json = json.loads(response.read().decode())
102+
except HTTPError as error:
103+
error_text = error.read().decode().replace(jira_cloud_id, "[REDACTED]")
104+
print(f"[{SCRIPT_NAME}] Error fetching Jira issue ({jira_issue_id}). Status code: {error.code}. Msg: {error_text}", file=sys.stderr)
89105
sys.exit(1)
90106

91-
release_notes = parse_release_notes(response.json())
107+
release_notes = parse_release_notes(response_json)
92108
print(release_notes)
93109

94110
if __name__ == "__main__":

.github/scripts/jira-get-release-notes/pyproject.toml

Lines changed: 0 additions & 9 deletions
This file was deleted.

.github/scripts/jira-get-release-notes/uv.lock

Lines changed: 0 additions & 91 deletions
This file was deleted.

.github/workflows/github-release.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ jobs:
168168
uses: bitwarden/gh-actions/get-keyvault-secrets@main
169169
with:
170170
keyvault: gh-android
171-
secrets: "JIRA-API-EMAIL,JIRA-API-TOKEN"
171+
secrets: "JIRA-API-EMAIL,JIRA-API-TOKEN,JIRA-CLOUD-ID"
172172

173173
- name: Log out from Azure
174174
uses: bitwarden/gh-actions/azure-logout@main
@@ -180,13 +180,14 @@ jobs:
180180
ARTIFACT_RUN_ID: ${{ inputs.artifact-run-id }}
181181
_VERSION_NAME: ${{ steps.get_release_info.outputs.version_name }}
182182
_RELEASE_TICKET_ID: ${{ inputs.release-ticket-id }}
183+
_JIRA_CLOUD_ID: ${{ steps.get-kv-secrets.outputs.JIRA-CLOUD-ID }}
183184
_JIRA_API_EMAIL: ${{ steps.get-kv-secrets.outputs.JIRA-API-EMAIL }}
184185
_JIRA_API_TOKEN: ${{ steps.get-kv-secrets.outputs.JIRA-API-TOKEN }}
185186
run: |
186187
echo "Getting product release notes..."
187188
# capture output and exit code so this step continues even if we can't retrieve release notes.
188189
script_exit_code=0
189-
product_release_notes=$(python .github/scripts/jira-get-release-notes/jira_release_notes.py "$_RELEASE_TICKET_ID" "$_JIRA_API_EMAIL" "$_JIRA_API_TOKEN") || script_exit_code=$?
190+
product_release_notes=$(python3 .github/scripts/jira-get-release-notes/jira_release_notes.py "$_RELEASE_TICKET_ID" "$_JIRA_CLOUD_ID" "$_JIRA_API_EMAIL" "$_JIRA_API_TOKEN") || script_exit_code=$?
190191
echo "--------------------------------"
191192
192193
if [[ $script_exit_code -ne 0 || -z "$product_release_notes" ]]; then

0 commit comments

Comments
 (0)