Skip to content

Commit 582e6a6

Browse files
committed
Add notify failure for av scan template
Signed-off-by: Alexey Paschenko <alexey.paschenko@flant.com>
1 parent 982b3ec commit 582e6a6

1 file changed

Lines changed: 85 additions & 1 deletion

File tree

templates/Antivirus_Scan.gitlab-ci.yml

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ variables:
1717
AV_MODULE_NAME: ${MODULES_MODULE_NAME}
1818
AV_PROD_REGISTRY: ${PROD_REGISTRY}
1919
AV_DEV_REGISTRY: ${DEV_REGISTRY}
20+
AV_N8N_LOOP_NOTIFIER_URL: ${N8N_LOOP_NOTIFIER_URL}
2021

2122
Antivirus scan get tags:
2223
stage: antivirus_scan
@@ -75,7 +76,7 @@ Antivirus scan get tags:
7576
\${AV_ANTIVIRUS_NAME}-scan:
7677
stage: antivirus_scan
7778
tags:
78-
- antivirus
79+
- docker
7980
parallel:
8081
matrix:
8182
- TAG: [\${TAGS_ARRAY}]
@@ -172,3 +173,86 @@ Antivirus scan trigger:
172173
- artifact: child-pipeline-kaspersky.yml
173174
job: "Antivirus scan get tags"
174175
strategy: depend
176+
177+
notify-failure:
178+
stage: antivirus_scan
179+
tags:
180+
- antivirus
181+
image: debian:bookworm-slim
182+
before_script:
183+
- apt-get update && apt-get install -y curl jq
184+
rules:
185+
- when: on_failure
186+
needs:
187+
- job: Antivirus scan get tags
188+
- job: Antivirus scan trigger
189+
optional: true
190+
script:
191+
- |
192+
set -euo pipefail
193+
194+
API="${CI_API_V4_URL}"
195+
PROJECT_ID="${CI_PROJECT_ID}"
196+
PIPELINE_ID="${CI_PIPELINE_ID}"
197+
198+
# auth: prefer CI_JOB_TOKEN, fallback to personal/project token
199+
AUTH_HEADER=()
200+
if [[ -n "${CI_JOB_TOKEN:-}" ]]; then
201+
AUTH_HEADER=(-H "JOB-TOKEN: ${CI_JOB_TOKEN}")
202+
elif [[ -n "${GITLAB_API_TOKEN:-}" ]]; then
203+
AUTH_HEADER=(-H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}")
204+
else
205+
echo "No CI_JOB_TOKEN or GITLAB_API_TOKEN available"
206+
exit 1
207+
fi
208+
209+
# 1) Find the bridge job "Antivirus scan trigger" and extract downstream_pipeline.id
210+
BRIDGES_JSON="$(curl -sf "${AUTH_HEADER[@]}" \
211+
"${API}/projects/${PROJECT_ID}/pipelines/${PIPELINE_ID}/bridges?per_page=100")"
212+
213+
DOWNSTREAM_ID="$(echo "${BRIDGES_JSON}" | jq -r '
214+
.[] | select(.name=="Antivirus scan trigger") | .downstream_pipeline.id // empty
215+
')"
216+
217+
if [[ -z "${DOWNSTREAM_ID}" ]]; then
218+
echo "Downstream pipeline id not found for bridge 'Antivirus scan trigger'"
219+
# Fallback: just send a generic alert
220+
DOWNSTREAM_URL="${CI_PIPELINE_URL}"
221+
else
222+
DOWNSTREAM_URL="${CI_PROJECT_URL}/-/pipelines/${DOWNSTREAM_ID}"
223+
fi
224+
225+
# 2) If downstream exists, fetch job statuses in the child pipeline
226+
FAILED_LIST=""
227+
if [[ -n "${DOWNSTREAM_ID}" ]]; then
228+
JOBS_JSON="$(curl -sf "${AUTH_HEADER[@]}" \
229+
"${API}/projects/${PROJECT_ID}/pipelines/${DOWNSTREAM_ID}/jobs?per_page=200")"
230+
231+
# Only take scan jobs; include failed/canceled
232+
FAILED_LIST="$(echo "${JOBS_JSON}" | jq -r '
233+
[ .[]
234+
| select(.name|test("-scan$"))
235+
| select(.status=="failed" or .status=="canceled")
236+
| "- \(.name) (status: \(.status)) \(.web_url)"
237+
] | .[]?
238+
')"
239+
fi
240+
241+
if [[ -z "${FAILED_LIST}" ]]; then
242+
FAILED_LIST="- (could not determine the specific failed job(s); check the pipeline/child pipeline)"
243+
fi
244+
245+
# 3) Render template
246+
MSG=$(jq -n --arg pipeline "${CI_PIPELINE_URL}" \
247+
--arg child "${DOWNSTREAM_URL}" \
248+
--arg failed "${FAILED_LIST}" '
249+
"🛑 GitLab Antivirus Scan Failed\n\n" +
250+
"Failed jobs:\n" + $failed + "\n\n" +
251+
"Pipeline: " + $pipeline + "\n" +
252+
"Child pipeline: " + $child
253+
' -r)
254+
255+
# 4) Send to n8n
256+
curl -sf -L -X POST "$AV_N8N_LOOP_NOTIFIER_URL" \
257+
-H "Content-Type: application/json" \
258+
--data "$(jq -n --arg type "ci_fail" --arg message "$MSG" '{type:$type,message:$message}')"

0 commit comments

Comments
 (0)