Skip to content

Commit d20a907

Browse files
GHA-161 Use Ticket Filter Instead of Jira Release for REL Ticket (#76)
Co-authored-by: Yasen Pavlov <yasen.pavlov@sonarsource.com>
1 parent a48ad98 commit d20a907

File tree

7 files changed

+89
-36
lines changed

7 files changed

+89
-36
lines changed

.github/workflows/automated-release.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ jobs:
187187
release-notes: ${{ inputs.release-notes != '' && inputs.release-notes || steps.get-jira-release-notes.outputs.release-notes }}
188188
jira-release-notes: ${{ inputs.release-notes != '' && inputs.release-notes || steps.get-jira-release-notes.outputs.jira-release-notes }}
189189
jira-release-url: ${{ steps.get-jira-release-notes.outputs.jira-release-url }}
190+
jira-release-issue-filter-url: ${{ steps.get-jira-release-notes.outputs.jira-release-issue-filter-url }}
190191
steps:
191192
- name: Get Release Version
192193
id: get-release-version
@@ -251,7 +252,7 @@ jobs:
251252
project-name: ${{ inputs.project-name }}
252253
short-description: ${{ inputs.short-description }}
253254
rule-props-changed: ${{ inputs.rule-props-changed == 'true' && 'Yes' || 'No' }}
254-
jira-release-url: ${{ needs.prepare-release.outputs.jira-release-url }}
255+
jira-release-url: ${{ needs.prepare-release.outputs.jira-release-issue-filter-url }}
255256
start-progress: true
256257
version: ${{ needs.prepare-release.outputs.release-version }}
257258

.github/workflows/cloud-security-automated-release.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ jobs:
139139
release-notes: ${{ inputs.release-notes != '' && inputs.release-notes || steps.get-jira-release-notes.outputs.release-notes }}
140140
jira-release-notes: ${{ inputs.release-notes != '' && inputs.release-notes || steps.get-jira-release-notes.outputs.jira-release-notes }}
141141
jira-release-url: ${{ steps.get-jira-release-notes.outputs.jira-release-url }}
142+
jira-release-issue-filter-url: ${{ steps.get-jira-release-notes.outputs.jira-release-issue-filter-url }}
142143
steps:
143144
- name: Get Release Version
144145
id: get-release-version
@@ -174,7 +175,7 @@ jobs:
174175
project-name: ${{ inputs.project-name }}
175176
short-description: ${{ inputs.short-description }}
176177
rule-props-changed: ${{ inputs.rule-props-changed }}
177-
jira-release-url: ${{ needs.prepare-release.outputs.jira-release-url }}
178+
jira-release-url: ${{ needs.prepare-release.outputs.jira-release-issue-filter-url }}
178179
start-progress: true
179180
version: ${{ needs.prepare-release.outputs.release-version }}
180181

.github/workflows/test-get-jira-release-notes.yml

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,33 +82,41 @@ jobs:
8282
# Create a mock script that simulates the Python output
8383
cat > mock_output.py << 'EOF'
8484
print("jira-release-url=https://test.atlassian.net/projects/TEST/versions/123/tab/release-report-all-issues")
85+
print("jira-release-issue-filter-url=https://test.atlassian.net/issues/?jql=fixVersion%3D123")
8586
print("release-notes<<EOF")
8687
print("# Release notes - Test Project - 1.0.0")
87-
print("")
88+
print("")
8889
print("### Bug")
8990
print("[TEST-1](https://test.atlassian.net/browse/TEST-1) Fix test issue")
9091
print("")
9192
print("EOF")
9293
EOF
93-
94+
9495
# Test the tee + sed pipeline
95-
python mock_output.py | tee test_output.txt | sed 's/^jira-release-url=/JIRA_RELEASE_URL=/' | sed 's/^release-notes<</RELEASE_NOTES<</' > test_env.txt
96-
96+
python mock_output.py | tee test_output.txt | sed 's/^jira-release-url=/JIRA_RELEASE_URL=/' | sed 's/^jira-release-issue-filter-url=/JIRA_RELEASE_ISSUE_FILTER_URL=/' | sed 's/^release-notes<</RELEASE_NOTES<</' > test_env.txt
97+
9798
# Verify outputs were created correctly
9899
echo "=== GitHub Output format ==="
99100
cat test_output.txt
100101
echo ""
101102
echo "=== Environment Variable format ==="
102103
cat test_env.txt
103-
104+
104105
# Verify transformations
105106
if grep -q "JIRA_RELEASE_URL=https://test.atlassian.net" test_env.txt; then
106107
echo "✅ JIRA_RELEASE_URL transformation works"
107108
else
108109
echo "❌ JIRA_RELEASE_URL transformation failed"
109110
exit 1
110111
fi
111-
112+
113+
if grep -q "JIRA_RELEASE_ISSUE_FILTER_URL=https://test.atlassian.net/issues" test_env.txt; then
114+
echo "✅ JIRA_RELEASE_ISSUE_FILTER_URL transformation works"
115+
else
116+
echo "❌ JIRA_RELEASE_ISSUE_FILTER_URL transformation failed"
117+
exit 1
118+
fi
119+
112120
if grep -q "RELEASE_NOTES<<EOF" test_env.txt; then
113121
echo "✅ RELEASE_NOTES transformation works"
114122
else
@@ -141,6 +149,7 @@ jobs:
141149
- name: Output results
142150
run: |
143151
echo "Jira Release URL: ${{ steps.test-sandbox.outputs.jira-release-url }}"
152+
echo "Jira Release Issue Filter URL: ${{ steps.test-sandbox.outputs.jira-release-issue-filter-url }}"
144153
echo "Release Notes:"
145154
echo "${{ steps.test-sandbox.outputs.release-notes }}"
146155
echo "Jira Release Notes:"
@@ -155,6 +164,17 @@ jobs:
155164
echo "✅ Jira Release URL format is correct"
156165
fi
157166
167+
- name: Verify Jira Release Issue Filter URL
168+
run: |
169+
if [[ "${{ steps.test-sandbox.outputs.jira-release-issue-filter-url }}" != https://sonarsource-sandbox-608.atlassian.net/issues/?jql=fixVersion%3D22169 ]]; then
170+
echo "❌ Jira Release Issue Filter URL is incorrect"
171+
echo "Expected: https://sonarsource-sandbox-608.atlassian.net/issues/?jql=fixVersion%3D22169"
172+
echo "Got: ${{ steps.test-sandbox.outputs.jira-release-issue-filter-url }}"
173+
exit 1
174+
else
175+
echo "✅ Jira Release Issue Filter URL is correct"
176+
fi
177+
158178
- name: Verify Release Notes Content
159179
run: |
160180
if grep -q "### Improvement" <<< "${{ steps.test-sandbox.outputs.release-notes }}"; then

get-jira-release-notes/README.md

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,21 @@ This action depends on:
3131

3232
## Outputs
3333

34-
| Output | Description |
35-
|-----------------------|--------------------------------------------------|
36-
| `release-notes` | The formatted release notes as Markdown |
37-
| `jira-release-notes` | The formatted release notes in Jira wiki markup |
38-
| `jira-release-url` | The URL to the Jira release notes page |
34+
| Output | Description |
35+
|---------------------------------|----------------------------------------------------------|
36+
| `release-notes` | The formatted release notes as Markdown |
37+
| `jira-release-notes` | The formatted release notes in Jira wiki markup |
38+
| `jira-release-url` | The URL to the Jira release notes page |
39+
| `jira-release-issue-filter-url` | The URL of the issue filter for the Jira release |
3940

4041
## Environment Variables Set
4142

42-
| Environment Variable | Description |
43-
|----------------------|-----------------------------------------------------------------------------------------------|
44-
| `RELEASE_NOTES` | The formatted release notes as Markdown (same content as `release-notes` output) |
45-
| `JIRA_RELEASE_NOTES` | The formatted release notes in Jira wiki markup (same content as `jira-release-notes` output) |
46-
| `JIRA_RELEASE_URL` | The URL to the Jira release notes page (same content as `jira-release-url` output) |
43+
| Environment Variable | Description |
44+
|---------------------------------|-----------------------------------------------------------------------------------------------------------|
45+
| `RELEASE_NOTES` | The formatted release notes as Markdown (same content as `release-notes` output) |
46+
| `JIRA_RELEASE_NOTES` | The formatted release notes in Jira wiki markup (same content as `jira-release-notes` output) |
47+
| `JIRA_RELEASE_URL` | The URL to the Jira release notes page (same content as `jira-release-url` output) |
48+
| `JIRA_RELEASE_ISSUE_FILTER_URL` | The URL of the issue filter for the Jira release (same content as `jira-release-issue-filter-url` output) |
4749

4850
## Usage
4951

@@ -60,6 +62,7 @@ This action depends on:
6062
- name: Use the outputs
6163
run: |
6264
echo "Release Notes URL: ${{ steps.jira-notes.outputs.jira-release-url }}"
65+
echo "Issue Filter URL: ${{ steps.jira-notes.outputs.jira-release-issue-filter-url }}"
6366
echo "Release Notes (Markdown):"
6467
echo "${{ steps.jira-notes.outputs.release-notes }}"
6568
echo "Release Notes (Jira Format):"

get-jira-release-notes/action.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ outputs:
2323
jira-release-url:
2424
description: 'The URL to the Jira release notes page.'
2525
value: ${{ steps.get_notes.outputs.jira-release-url }}
26+
jira-release-issue-filter-url:
27+
description: 'The URL of the issue filter for the Jira release.'
28+
value: ${{ steps.get_notes.outputs.jira-release-issue-filter-url }}
2629

2730
runs:
2831
using: "composite"
@@ -54,8 +57,8 @@ runs:
5457
env:
5558
JIRA_USER: ${{ fromJSON(steps.secrets.outputs.vault).JIRA_USER }}
5659
JIRA_TOKEN: ${{ fromJSON(steps.secrets.outputs.vault).JIRA_TOKEN }}
57-
JIRA_PROD_URL: "https://sonarsource.atlassian.net/"
58-
JIRA_SANDBOX_URL: "https://sonarsource-sandbox-608.atlassian.net/"
60+
ISSUE_TYPES: ${{ inputs.issue-types }}
61+
JIRA_URL: "https://sonarsource${{ ((inputs.use-jira-sandbox || env.USE_JIRA_SANDBOX) == 'true') && '-sandbox-608' || '' }}.atlassian.net/"
5962
run: |
6063
PROJECT_KEY="${{ inputs.jira-project-key || env.JIRA_PROJECT_KEY }}"
6164
VERSION_NAME="${{ inputs.jira-version-name || env.JIRA_VERSION_NAME }}"
@@ -68,6 +71,6 @@ runs:
6871
python ${{ github.action_path }}/get_jira_release_notes.py \
6972
--project-key="$PROJECT_KEY" \
7073
--version-name="$VERSION_NAME" \
71-
--issue-types="${{ inputs.issue-types }}" \
72-
--jira-url="${{ ((inputs.use-jira-sandbox || env.USE_JIRA_SANDBOX) == 'true') && env.JIRA_SANDBOX_URL || env.JIRA_PROD_URL }}" \
73-
| tee -a $GITHUB_OUTPUT | sed 's/^jira-release-url=/JIRA_RELEASE_URL=/' | sed 's/^release-notes<</RELEASE_NOTES<</' | sed 's/^jira-release-notes<</JIRA_RELEASE_NOTES<</' >> $GITHUB_ENV
74+
--issue-types="$ISSUE_TYPES" \
75+
--jira-url="$JIRA_URL" \
76+
| tee -a $GITHUB_OUTPUT | sed 's/^jira-release-url=/JIRA_RELEASE_URL=/' | sed 's/^jira-release-issue-filter-url=/JIRA_RELEASE_ISSUE_FILTER_URL=/' | sed 's/^release-notes<</RELEASE_NOTES<</' | sed 's/^jira-release-notes<</JIRA_RELEASE_NOTES<</' >> $GITHUB_ENV

get-jira-release-notes/get_jira_release_notes.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,11 @@ def generate_release_notes_url(jira_url, project_key, version_id):
145145
return f"{jira_url.rstrip('/')}/projects/{project_key}/versions/{version_id}/tab/release-report-all-issues"
146146

147147

148+
def generate_release_issue_filter_url(jira_url, version_id):
149+
"""Generates the issue filter URL for the release version."""
150+
return f"{jira_url.rstrip('/')}/issues/?jql=fixVersion%3D{version_id}"
151+
152+
148153
def main():
149154
"""Main function to orchestrate fetching and formatting notes."""
150155
parser = argparse.ArgumentParser(
@@ -174,13 +179,14 @@ def main():
174179
eprint(f"Using default issue type order: {category_order}")
175180

176181
jira = get_jira_instance(args.jira_url)
177-
182+
178183
# Get version ID for URL generation
179184
version_id = get_version_id(jira, args.project_key, args.version_name)
180-
181-
# Generate release notes URL
185+
186+
# Generate release notes URL and issue filter URL
182187
release_notes_url = generate_release_notes_url(args.jira_url, args.project_key, version_id)
183-
188+
release_issue_filter_url = generate_release_issue_filter_url(args.jira_url, version_id)
189+
184190
# Get project name and issues for both formats
185191
project_name = get_project_name(jira, args.project_key)
186192
issues = get_issues_for_release(jira, args.project_key, args.version_name)
@@ -190,6 +196,7 @@ def main():
190196
# Output results for GitHub Actions
191197
# Using multiline string format for the release notes
192198
print(f"jira-release-url={release_notes_url}")
199+
print(f"jira-release-issue-filter-url={release_issue_filter_url}")
193200
print("release-notes<<EOF")
194201
print(markdown_notes)
195202
print("EOF")

get-jira-release-notes/test_get_jira_release_notes.py

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
format_notes_as_markdown,
2323
format_notes_as_jira_markup,
2424
generate_release_notes_url,
25+
generate_release_issue_filter_url,
2526
main
2627
)
2728
from jira.exceptions import JIRAError
@@ -212,6 +213,18 @@ def test_generate_release_notes_url_trailing_slash(self):
212213
expected = 'https://jira.com/projects/TEST/versions/10001/tab/release-report-all-issues'
213214
self.assertEqual(url, expected)
214215

216+
def test_generate_release_issue_filter_url(self):
217+
"""Test release issue filter URL generation."""
218+
url = generate_release_issue_filter_url('https://jira.com', '10001')
219+
expected = 'https://jira.com/issues/?jql=fixVersion%3D10001'
220+
self.assertEqual(url, expected)
221+
222+
def test_generate_release_issue_filter_url_trailing_slash(self):
223+
"""Test release issue filter URL generation with trailing slash."""
224+
url = generate_release_issue_filter_url('https://jira.com/', '10001')
225+
expected = 'https://jira.com/issues/?jql=fixVersion%3D10001'
226+
self.assertEqual(url, expected)
227+
215228
# noinspection PyUnusedLocal
216229
@patch('sys.argv', [
217230
'get_jira_release_notes.py',
@@ -226,10 +239,12 @@ def test_generate_release_notes_url_trailing_slash(self):
226239
@patch('get_jira_release_notes.format_notes_as_markdown')
227240
@patch('get_jira_release_notes.format_notes_as_jira_markup')
228241
@patch('get_jira_release_notes.generate_release_notes_url')
242+
@patch('get_jira_release_notes.generate_release_issue_filter_url')
229243
@patch('sys.stderr', new_callable=StringIO)
230244
@patch('builtins.print')
231-
def test_main_success(self, mock_print, mock_stderr, mock_generate_url, mock_format_jira_markup, mock_format_notes,
232-
mock_get_issues, mock_get_project_name, mock_get_version_id, mock_get_jira):
245+
def test_main_success(self, mock_print, mock_stderr, mock_generate_filter_url, mock_generate_url,
246+
mock_format_jira_markup, mock_format_notes, mock_get_issues, mock_get_project_name,
247+
mock_get_version_id, mock_get_jira):
233248
"""Test successful main function execution."""
234249
# Setup mocks
235250
mock_jira = Mock()
@@ -240,13 +255,15 @@ def test_main_success(self, mock_print, mock_stderr, mock_generate_url, mock_for
240255
mock_format_notes.return_value = "# Release notes - Test Project - 1.0.0\n\nNo issues found."
241256
mock_format_jira_markup.return_value = "h1. Release notes - Test Project - 1.0.0\n\nNo issues found."
242257
mock_generate_url.return_value = "https://test.jira.com/projects/TEST/versions/10001/tab/release-report-all-issues"
258+
mock_generate_filter_url.return_value = "https://test.jira.com/issues/?jql=fixVersion%3D10001"
243259

244260
main()
245261

246262
# Verify all functions were called correctly
247263
mock_get_jira.assert_called_once_with('https://test.jira.com')
248264
mock_get_version_id.assert_called_once_with(mock_jira, 'TEST', '1.0.0')
249265
mock_generate_url.assert_called_once_with('https://test.jira.com', 'TEST', '10001')
266+
mock_generate_filter_url.assert_called_once_with('https://test.jira.com', '10001')
250267
mock_get_project_name.assert_called_once_with(mock_jira, 'TEST')
251268
mock_get_issues.assert_called_once_with(mock_jira, 'TEST', '1.0.0')
252269

@@ -256,15 +273,16 @@ def test_main_success(self, mock_print, mock_stderr, mock_generate_url, mock_for
256273

257274
# Verify expected output format
258275
print_calls = mock_print.call_args_list
259-
self.assertEqual(len(print_calls), 8) # URL + markdown start/content/end + jira start/content/end
276+
self.assertEqual(len(print_calls), 9) # URL + filter URL + markdown start/content/end + jira start/content/end
260277
# Check the main outputs
261278
self.assertEqual(print_calls[1][0][0], "jira-release-url=https://test.jira.com/projects/TEST/versions/10001/tab/release-report-all-issues")
262-
self.assertEqual(print_calls[2][0][0], "release-notes<<EOF")
263-
self.assertEqual(print_calls[3][0][0], "# Release notes - Test Project - 1.0.0\n\nNo issues found.")
264-
self.assertEqual(print_calls[4][0][0], "EOF")
265-
self.assertEqual(print_calls[5][0][0], "jira-release-notes<<EOF")
266-
self.assertEqual(print_calls[6][0][0], "h1. Release notes - Test Project - 1.0.0\n\nNo issues found.")
267-
self.assertEqual(print_calls[7][0][0], "EOF")
279+
self.assertEqual(print_calls[2][0][0], "jira-release-issue-filter-url=https://test.jira.com/issues/?jql=fixVersion%3D10001")
280+
self.assertEqual(print_calls[3][0][0], "release-notes<<EOF")
281+
self.assertEqual(print_calls[4][0][0], "# Release notes - Test Project - 1.0.0\n\nNo issues found.")
282+
self.assertEqual(print_calls[5][0][0], "EOF")
283+
self.assertEqual(print_calls[6][0][0], "jira-release-notes<<EOF")
284+
self.assertEqual(print_calls[7][0][0], "h1. Release notes - Test Project - 1.0.0\n\nNo issues found.")
285+
self.assertEqual(print_calls[8][0][0], "EOF")
268286

269287
@patch('sys.argv', [
270288
'get_jira_release_notes.py',

0 commit comments

Comments
 (0)