Skip to content

Commit ff0d3c0

Browse files
authored
Release 20250700 (#5659)
2 parents 49ed760 + 5581042 commit ff0d3c0

File tree

117 files changed

+8353
-274
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

117 files changed

+8353
-274
lines changed
Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
name: Workflow incident tracking
2+
description: Create Jira ticket on incident
3+
4+
inputs:
5+
jira_base_url:
6+
required: true
7+
description: jira base url
8+
jira_user_email:
9+
required: true
10+
description: jira user email
11+
jira_api_token:
12+
required: true
13+
description: jira api token
14+
module_name:
15+
required: true
16+
description: module name
17+
ticket_labels:
18+
required: true
19+
description: ticket labels, usually Pipeline + Nightly/Veracode + x
20+
default: 'Pipeline'
21+
ticket_squad:
22+
required: true
23+
description: id of the squad to assign the ticket to
24+
default: 'DevSecOps'
25+
26+
27+
runs:
28+
using: "composite"
29+
steps:
30+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
31+
32+
- name: Get ticket elements from context
33+
id: get_context
34+
run: |
35+
# Safely set/unset IFS in order to properly parse the table of labels
36+
[ -n "${IFS+set}" ] && saved_IFS=$IFS
37+
IFS=', ' read -a ticket_labels <<< $(echo "${{ inputs.ticket_labels }}" | tr -d "[],'")
38+
unset IFS
39+
[ -n "${saved_IFS+set}" ] && { IFS=$saved_IFS; unset saved_IFS; }
40+
41+
# Change the context elements (summary, parent epic, etc.) that are checked depending on these ticket labels
42+
if [[ "${ticket_labels[@]}" =~ "Nightly" ]]; then
43+
parent_epic_id=206242
44+
parent_epic_key="MON-151547"
45+
ticket_summary="$(date '+%Y-%m-%d') ${{ inputs.module_name }}-${{ github.ref_name }} nightly build failure"
46+
47+
JSON_TEMPLATE_FILE="./.github/actions/create-jira-ticket/nightly-ticket-template.json"
48+
sed -i \
49+
-e 's|@MODULE_NAME@|${{ inputs.module_name }}|g' \
50+
-e "s|@DATE@|$(date '+%Y-%m-%d')|g" $JSON_TEMPLATE_FILE
51+
52+
else
53+
echo "::error::Cannot find a valid labelling option for the ticket."
54+
exit 1
55+
fi
56+
57+
case "${{ inputs.ticket_squad }}" in
58+
"DevSecOps")
59+
ticket_squad_id=10524
60+
ticket_board_id=184
61+
squad_name="DEVSECOPS"
62+
project_name="MON"
63+
;;
64+
"Connectors")
65+
ticket_squad_id=10504
66+
ticket_board_id=222
67+
squad_name="CONNECTORS"
68+
project_name="CTOR"
69+
*)
70+
echo "::error::Cannot find a valid squad for value ${{ inputs.ticket_squad }}."
71+
exit 1
72+
;;
73+
esac
74+
75+
echo "Ticket will be assigned to the $squad_name team."
76+
77+
current_sprint=$(curl --request GET \
78+
--url ${{ inputs.jira_base_url }}/rest/agile/1.0/board/$ticket_board_id/sprint?state=active \
79+
--user "${{ inputs.jira_user_email }}:${{ inputs.jira_api_token }}" \
80+
--header "Accept: application/json" | jq --arg squad_name "$squad_name" '.values[] | select(.name | test($squad_name; "i")) | .id')
81+
82+
echo "[DEBUG] current_sprint: $current_sprint"
83+
84+
# General updates on all template files
85+
sed -i \
86+
-e 's|@GITHUB_BRANCH@|${{ github.base_ref || github.ref_name }}|g' \
87+
-e 's|@GITHUB_SERVER_URL@|${{ github.server_url }}|g' \
88+
-e 's|@GITHUB_REPOSITORY@|${{ github.repository }}|g' \
89+
-e 's|@GITHUB_RUN_ID@|${{ github.run_id }}|g' \
90+
-e 's|@GITHUB_RUN_ATTEMPT@|${{ github.run_attempt }}|g' $JSON_TEMPLATE_FILE
91+
92+
echo "parent_epic_id=$parent_epic_id" >> $GITHUB_OUTPUT
93+
echo "parent_epic_key=$parent_epic_key" >> $GITHUB_OUTPUT
94+
echo "ticket_summary=$ticket_summary" >> $GITHUB_OUTPUT
95+
echo "ticket_board_id=$ticket_board_id" >> $GITHUB_OUTPUT
96+
echo "ticket_squad_id=$ticket_squad_id" >> $GITHUB_OUTPUT
97+
echo "project_name=$project_name" >> $GITHUB_OUTPUT
98+
echo "current_sprint=$current_sprint" >> $GITHUB_OUTPUT
99+
echo "json_template_file=$JSON_TEMPLATE_FILE" >> $GITHUB_OUTPUT
100+
101+
cat $JSON_TEMPLATE_FILE
102+
cat $GITHUB_OUTPUT
103+
shell: bash
104+
env:
105+
GH_TOKEN: ${{ github.token }}
106+
107+
- name: Check if the ticket already exists
108+
id: check_ticket
109+
run: |
110+
# Checking if an incident ticket already exists
111+
response=$(curl \
112+
--write-out "%{http_code}" \
113+
--request POST \
114+
--url "${{ inputs.jira_base_url }}/rest/api/3/search" \
115+
--user "${{ inputs.jira_user_email }}:${{ inputs.jira_api_token }}" \
116+
--header "Accept:application/json" \
117+
--header "Content-Type:application/json" \
118+
--data '{
119+
"fields": ["summary"],
120+
"jql": "project = ${{ steps.get_context.outputs.project_name }} AND parentEpic = ${{ steps.get_context.outputs.parent_epic_key }} AND issueType = Technical AND summary ~ \"${{ steps.get_context.outputs.ticket_summary }}\" AND component = \"${{ inputs.module_name }}\" AND resolution = unresolved ORDER BY key ASC",
121+
"maxResults": 1
122+
}'
123+
)
124+
echo "[DEBUG] $response"
125+
126+
if [[ $(echo "$response" | tr -d '\n' | tail -c 3) -ne 200 ]]; then
127+
echo "::error:: Jira API request was not completed properly."
128+
fi
129+
130+
ticket_key=$(echo "$response" | head -c -4 | jq .issues[0].key | xargs)
131+
if [[ "$ticket_key" != "null" ]]; then
132+
echo "abort_ticket_creation=true" >> $GITHUB_ENV
133+
echo "ticket_key=$ticket_key" >> $GITHUB_ENV
134+
echo "::notice::ticket found as $ticket_key aborting ticket creation"
135+
fi
136+
shell: bash
137+
138+
- name: Update existing nightly Jira ticket
139+
if: |
140+
env.abort_ticket_creation == 'true' &&
141+
contains(steps.get_context.outputs.parent_epic_key, 'MON-151547')
142+
run: |
143+
# Adding failed job labels for already existing ticket
144+
[ -n "${IFS+set}" ] && saved_IFS=$IFS
145+
IFS=', ' read -a ticket_labels <<< $(echo "${{ inputs.ticket_labels }}" | tr -d "[],'")
146+
unset IFS
147+
[ -n "${saved_IFS+set}" ] && { IFS=$saved_IFS; unset saved_IFS; }
148+
149+
for label in ${ticket_labels[@]}; do
150+
response=$(curl \
151+
--request PUT \
152+
--url "${{ inputs.jira_base_url }}/rest/api/3/issue/${{ env.ticket_key }}" \
153+
--user "${{ inputs.jira_user_email }}:${{ inputs.jira_api_token }}" \
154+
--header 'Accept: application/json' \
155+
--header 'Content-Type: application/json' \
156+
--data "{ \"update\": { \"labels\": [ { \"add\": \"$label\" } ] } }"
157+
)
158+
done
159+
160+
ticket_description=$(curl --request GET \
161+
--url "${{ inputs.jira_base_url }}/rest/api/3/issue/${{ env.ticket_key }}" \
162+
--user "${{ inputs.jira_user_email }}:${{ inputs.jira_api_token }}" \
163+
--header "Accept: application/json" | jq '.fields.description')
164+
165+
mapfile -t jobs_failed < <(gh run view ${{ github.run_id }} --json jobs -q '.jobs[] | select(.conclusion == "failure") | .name')
166+
echo "[DEBUG] - jobs failed for component ${FAILED_COMPONENTS[index]}: $jobs_failed"
167+
168+
new_list_of_failed_jobs=$(for job in "${jobs_failed[@]}"; do
169+
cat <<EOF
170+
{
171+
"type": "listItem",
172+
"content": [
173+
{
174+
"type": "paragraph",
175+
"content": [
176+
{
177+
"type": "text",
178+
"text": "$job"
179+
}
180+
]
181+
}
182+
]
183+
}
184+
EOF
185+
done | jq -s '.'
186+
)
187+
188+
updated_ticket_description=$(echo "$ticket_description" | jq --argjson new_list_of_failed_jobs "$new_list_of_failed_jobs" '
189+
(.content[] | select(.type == "bulletList") | .content) = $new_list_of_failed_jobs
190+
')
191+
192+
echo "[DEBUG] - updated_ticket_description = $updated_ticket_description"
193+
194+
curl --request PUT \
195+
--url "${{ inputs.jira_base_url }}/rest/api/3/issue/${{ env.ticket_key }}" \
196+
--user "${{ inputs.jira_user_email }}:${{ inputs.jira_api_token }}" \
197+
--header "Accept: application/json" \
198+
--header "Content-Type: application/json" \
199+
--data "{
200+
\"fields\": {
201+
\"description\": $updated_ticket_description
202+
}
203+
}"
204+
205+
shell: bash
206+
env:
207+
GH_TOKEN: ${{ github.token }}
208+
209+
- name: Create Jira Issue
210+
if: ${{ env.abort_ticket_creation != 'true' }}
211+
run: |
212+
# Get the name of the current job and list it
213+
failed_job_name=$(gh run view ${{ github.run_id }} --json jobs | jq -r --arg job_name "${{ github.job }}" '.jobs[] | select(.name == $job_name) | .name')
214+
215+
CONTENT_TO_ADD_TO_TEMPLATE_FILE=$(jq -n --arg job "$failed_job_name" '{
216+
"type": "bulletList",
217+
"content": [
218+
{
219+
"type": "listItem",
220+
"content": [
221+
{
222+
"type": "paragraph",
223+
"content": [
224+
{
225+
"type": "text",
226+
"text": $job
227+
}
228+
]
229+
}
230+
]
231+
}
232+
]
233+
}')
234+
235+
echo "[DEBUG] - CONTENT_TO_ADD_TO_TEMPLATE_FILE: $CONTENT_TO_ADD_TO_TEMPLATE_FILE"
236+
237+
TEMPLATE_FILE=$(cat ${{ steps.get_context.outputs.json_template_file }})
238+
UPDATED_TEMPLATE_FILE=$(jq --argjson NEW_CONTENT "$CONTENT_TO_ADD_TO_TEMPLATE_FILE" '.content += [$NEW_CONTENT]' <<< "$TEMPLATE_FILE")
239+
240+
# Creating a new incident ticket on Jira
241+
DATA=$( cat <<-EOF
242+
{
243+
"fields": {
244+
"summary": "${{ steps.get_context.outputs.ticket_summary }}",
245+
"project": {"key": "${{ steps.get_context.outputs.project_name }}"},
246+
"issuetype": {"id": "10209"},
247+
"parent": {"id": "${{ steps.get_context.outputs.parent_epic_id }}", "key": "${{ steps.get_context.outputs.parent_epic_key }}"},
248+
"labels": ${{ inputs.ticket_labels }},
249+
"components":[{"name": "${{ inputs.module_name }}"}],
250+
"customfield_10902": {"id": "${{ steps.get_context.outputs.ticket_squad_id }}", "value": "${{ inputs.ticket_squad }}"},
251+
"description": $UPDATED_TEMPLATE_FILE
252+
}
253+
}
254+
EOF
255+
)
256+
257+
if [[ ${{ steps.get_context.outputs.current_sprint }} != "null" ]]; then
258+
DATA=$(echo "$DATA" | jq '.fields.customfield_10007 = ${{ steps.get_context.outputs.current_sprint }}')
259+
fi
260+
echo "[DEBUG] - DATA: $DATA"
261+
262+
response=$(curl \
263+
--request POST \
264+
--url "${{ inputs.jira_base_url }}/rest/api/3/issue" \
265+
--user "${{ inputs.jira_user_email }}:${{ inputs.jira_api_token }}" \
266+
--header 'Accept: application/json' \
267+
--header 'Content-Type: application/json' \
268+
--data "$DATA")
269+
270+
if [ $? -ne 0 ]; then
271+
echo "::error::Failed to create ticket: $response"
272+
exit 1
273+
fi
274+
275+
echo $response
276+
277+
ticket_key=$(echo "$response" | jq -r .key)
278+
echo "::notice::Created ticket: $ticket_key"
279+
280+
# Update priority on newly created ticket since you cannot create a ticket with another priority than medium
281+
response=$(curl \
282+
--request PUT \
283+
--url "${{ inputs.jira_base_url }}/rest/api/3/issue/$ticket_key" \
284+
--user "${{ inputs.jira_user_email }}:${{ inputs.jira_api_token }}" \
285+
--header 'Accept: application/json' \
286+
--header 'Content-Type: application/json' \
287+
--data '{ "fields": { "priority": { "id": "1" } } }'
288+
)
289+
290+
echo $response
291+
292+
# Update ticket status so that squad members can see it in their respective sprints
293+
for transition_id in 11 21; do
294+
response=$(curl \
295+
--request POST \
296+
--url "${{ inputs.jira_base_url }}/rest/api/latest/issue/$ticket_key/transitions" \
297+
--user "${{ inputs.jira_user_email }}:${{ inputs.jira_api_token }}" \
298+
--header 'Accept: application/json' \
299+
--header 'Content-Type: application/json' \
300+
--data "{\"transition\": {\"id\": \"$transition_id\"} }"
301+
)
302+
303+
echo $response
304+
done
305+
306+
shell: bash
307+
env:
308+
GH_TOKEN: ${{ github.token }}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
{
2+
"version": 1,
3+
"type": "doc",
4+
"content": [
5+
{
6+
"type": "paragraph",
7+
"content": [
8+
{
9+
"type": "text",
10+
"text": "This ticket was automatically created by the nightly workflow run. Feel free to update it as you need to. If you have any feedback about it, please contact the Delivery team.",
11+
"marks": [
12+
{
13+
"type": "em"
14+
}
15+
]
16+
}
17+
]
18+
},
19+
{
20+
"type": "paragraph",
21+
"content": [
22+
{
23+
"type": "text",
24+
"text": "This incident ticket relates to the @MODULE_NAME@ nightly on the @GITHUB_BRANCH@ branch which failed on @DATE@."
25+
}
26+
]
27+
},
28+
{
29+
"type": "paragraph",
30+
"content": [
31+
{
32+
"type": "text",
33+
"text": "Link to the failed nightly",
34+
"marks": [
35+
{
36+
"type": "link",
37+
"attrs": {
38+
"href": "@GITHUB_SERVER_URL@/@GITHUB_REPOSITORY@/actions/runs/@GITHUB_RUN_ID@/attempts/@GITHUB_RUN_ATTEMPT@"
39+
}
40+
}
41+
]
42+
}
43+
]
44+
},
45+
{
46+
"type": "paragraph",
47+
"content": [
48+
{
49+
"type": "text",
50+
"text": "List of jobs that failed on the @MODULE_NAME@ nightly:"
51+
}
52+
]
53+
}
54+
]
55+
}

.github/docker/packaging/Dockerfile.packaging-plugins-java-alma8

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ dnf install -y \
1111
zstd
1212

1313
cd /usr/local/src
14-
wget https://dlcdn.apache.org/maven/maven-3/3.8.8/binaries/apache-maven-3.8.8-bin.tar.gz
15-
tar zxf apache-maven-3.8.8-bin.tar.gz
16-
ln -s /usr/local/src/apache-maven-3.8.8/bin/mvn /usr/bin/mvn
17-
rm -f apache-maven-3.8.8-bin.tar.gz
14+
wget https://dlcdn.apache.org/maven/maven-3/3.8.9/binaries/apache-maven-3.8.9-bin.tar.gz
15+
tar zxf apache-maven-3.8.9-bin.tar.gz
16+
ln -s /usr/local/src/apache-maven-3.8.9/bin/mvn /usr/bin/mvn
17+
rm -f apache-maven-3.8.9-bin.tar.gz
1818

1919
echo '[goreleaser]
2020
name=GoReleaser

.github/docker/packaging/Dockerfile.packaging-plugins-java-alma9

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ dnf install -y \
1111
zstd
1212

1313
cd /usr/local/src
14-
wget https://dlcdn.apache.org/maven/maven-3/3.8.8/binaries/apache-maven-3.8.8-bin.tar.gz
15-
tar zxf apache-maven-3.8.8-bin.tar.gz
16-
ln -s /usr/local/src/apache-maven-3.8.8/bin/mvn /usr/bin/mvn
17-
rm -f apache-maven-3.8.8-bin.tar.gz
14+
wget https://dlcdn.apache.org/maven/maven-3/3.8.9/binaries/apache-maven-3.8.9-bin.tar.gz
15+
tar zxf apache-maven-3.8.9-bin.tar.gz
16+
ln -s /usr/local/src/apache-maven-3.8.9/bin/mvn /usr/bin/mvn
17+
rm -f apache-maven-3.8.9-bin.tar.gz
1818

1919
echo '[goreleaser]
2020
name=GoReleaser

0 commit comments

Comments
 (0)