操作
タスク #488
完了機能 #481: VRChatチルワールド制作 — 海沿い高層階の1LDK(二人向け)
GitLab CI構築
タスク #488:
GitLab CI構築
説明
以下を参考にDiscord通知を実装する。
多分このプロジェクトにテストは不要だと思うので、no-opジョブを必ず実行し、その後の通知を飛ばす。
もしテストが必要な場合はテストを追加。
# Discord notification for merge-request pipeline results (#306). Horizontally
# replicated from the izu-IR implementation (#305, the source ticket). Two terminal-stage
# jobs post the MR pipeline outcome to a Discord channel via an incoming webhook:
# notify:success -> green embed when every prior-stage job succeeded
# notify:failure -> red embed (with the list of failed jobs) when a prior job failed
# Both run ONLY on merge_request_event pipelines and never on the tag/release pipeline, and
# both allow_failure so a notification hiccup can never block the merge gate. The webhook
# URL is read from the masked CI/CD variable DISCORD_WEBHOOK_URL; when it is unset the jobs
# no-op (exit 0) so the pipeline still passes before the variable exists. Failed-job
# enrichment queries the GitLab API with the optional GITLAB_API_TOKEN (read_api) variable,
# falling back to CI_JOB_TOKEN; if neither can read the jobs endpoint the embed still links
# to the pipeline.
# NOTE: the project `default:` (Ubuntu temurin image + apt/sibling-repo before_script +
# gradle cache) is overridden here — these run on alpine with an apk before_script and an
# empty cache (mirroring the `release` / `no-op` jobs).
.notify-base:
stage: notify
image: alpine:3.20
allow_failure: true
before_script:
- apk add --no-cache curl jq
cache: {}
notify:success:
extends: .notify-base
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: on_success
script:
- |
if [ -z "$DISCORD_WEBHOOK_URL" ]; then
echo "DISCORD_WEBHOOK_URL is not set; skipping Discord notification."
exit 0
fi
- |
jq -n \
--arg title "✅ Pipeline succeeded" \
--arg url "$CI_PIPELINE_URL" \
--arg project "$CI_PROJECT_PATH" \
--arg branch "$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME" \
--arg target "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" \
--arg mr "[!${CI_MERGE_REQUEST_IID}: ${CI_MERGE_REQUEST_TITLE}](${CI_MERGE_REQUEST_PROJECT_URL}/-/merge_requests/${CI_MERGE_REQUEST_IID})" \
--arg commit "${CI_COMMIT_SHORT_SHA}: ${CI_COMMIT_TITLE}" \
--arg author "$GITLAB_USER_NAME" \
'{embeds: [{
title: $title,
url: $url,
color: 3066993,
fields: [
{name: "Project", value: $project, inline: true},
{name: "Branch", value: ($branch + " -> " + $target), inline: true},
{name: "MR", value: $mr},
{name: "Commit", value: $commit},
{name: "Author", value: $author, inline: true}
]
}]}' > payload.json
- 'curl --fail --silent --show-error -H "Content-Type: application/json" -d @payload.json "$DISCORD_WEBHOOK_URL"'
notify:failure:
extends: .notify-base
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: on_failure
script:
- |
if [ -z "$DISCORD_WEBHOOK_URL" ]; then
echo "DISCORD_WEBHOOK_URL is not set; skipping Discord notification."
exit 0
fi
- |
if [ -n "$GITLAB_API_TOKEN" ]; then
AUTH_HEADER="PRIVATE-TOKEN: $GITLAB_API_TOKEN"
else
AUTH_HEADER="JOB-TOKEN: $CI_JOB_TOKEN"
fi
JOBS_JSON=$(curl --silent --show-error -H "$AUTH_HEADER" \
"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/pipelines/${CI_PIPELINE_ID}/jobs?scope=failed&per_page=100" 2>/dev/null || echo "")
FAILED_JOBS=""
if echo "$JOBS_JSON" | jq -e 'type == "array"' >/dev/null 2>&1; then
FAILED_JOBS=$(echo "$JOBS_JSON" | jq -r '[.[] | "- [" + .name + "](" + .web_url + ")"] | join("\n")')
fi
if [ -z "$FAILED_JOBS" ]; then
FAILED_JOBS="(failed job list unavailable - open the pipeline for details)"
fi
# Discord embed field values cap at 1024 chars; truncate defensively.
printf '%s' "$FAILED_JOBS" | cut -c1-1000 > failed_jobs.txt
- |
jq -n \
--arg title "❌ Pipeline failed" \
--arg url "$CI_PIPELINE_URL" \
--arg project "$CI_PROJECT_PATH" \
--arg branch "$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME" \
--arg target "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" \
--arg mr "[!${CI_MERGE_REQUEST_IID}: ${CI_MERGE_REQUEST_TITLE}](${CI_MERGE_REQUEST_PROJECT_URL}/-/merge_requests/${CI_MERGE_REQUEST_IID})" \
--arg commit "${CI_COMMIT_SHORT_SHA}: ${CI_COMMIT_TITLE}" \
--arg author "$GITLAB_USER_NAME" \
--rawfile failed failed_jobs.txt \
'{embeds: [{
title: $title,
url: $url,
color: 15158332,
fields: [
{name: "Project", value: $project, inline: true},
{name: "Branch", value: ($branch + " -> " + $target), inline: true},
{name: "MR", value: $mr},
{name: "Commit", value: $commit},
{name: "Author", value: $author, inline: true},
{name: "Failed jobs", value: $failed}
]
}]}' > payload.json
- 'curl --fail --silent --show-error -H "Content-Type: application/json" -d @payload.json "$DISCORD_WEBHOOK_URL"'
操作