-
Notifications
You must be signed in to change notification settings - Fork 37
146 lines (137 loc) · 6.72 KB
/
Copy pathalcf.yml
File metadata and controls
146 lines (137 loc) · 6.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
name: ALCF CI
# Bridges GitHub to ALCF GitLab CI (https://gitlab-ci.alcf.anl.gov/mschanen/oneAPI-jl),
# which pull-mirrors this repository and runs the LTS-stack test suite on Aurora (see
# .gitlab-ci.yml). This workflow makes the GitLab pipeline show up as a PR check:
#
# - push to main / same-repo PRs: the mirror already carries the branch; force a mirror
# sync (instead of waiting for the ~30 min schedule), then poll the pipeline for the
# head SHA and adopt its result.
# - fork PRs: never run automatically — GitLab CI jobs execute as an ALCF user on
# Aurora, so running fork code is opt-in. A maintainer applies the 'alcf-ci' label,
# which pushes the PR head to GitLab as branch gh-pr-<N> and triggers a pipeline.
# Re-apply the label to re-run after new pushes. This workflow only moves refs; it
# never checks out or executes PR code.
#
# The push uses ci.skip and the pipeline is created through a pipeline trigger token
# (ALCF_GITLAB_TRIGGER_TOKEN secret) instead: ALCF_GITLAB_TOKEN is a project access
# token, i.e. a bot user, and ALCF's Jacamar runners refuse bot-attributed pipelines
# ("bot account token used for job, unsupported by runner"). Trigger-token pipelines
# run as the user who created the token, which Jacamar accepts.
on:
push:
branches: [main]
pull_request:
pull_request_target:
types: [labeled]
concurrency:
group: alcf-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
aurora:
name: LTS stack (ALCF GitLab CI, Aurora)
runs-on: ubuntu-latest
# PBS queue wait + 1 h walltime + build stage; generous but below the 6 h runner cap
timeout-minutes: 330
if: >-
github.event_name == 'push' ||
(github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name == github.repository) ||
(github.event_name == 'pull_request_target' &&
github.event.label.name == 'alcf-ci' &&
github.event.pull_request.head.repo.full_name != github.repository)
env:
GITLAB_HOST: gitlab-ci.alcf.anl.gov
GITLAB_PROJECT: mschanen/oneAPI-jl
API: https://gitlab-ci.alcf.anl.gov/api/v4/projects/238
GITLAB_TOKEN: ${{ secrets.ALCF_GITLAB_TOKEN }}
GITLAB_TRIGGER_TOKEN: ${{ secrets.ALCF_GITLAB_TRIGGER_TOKEN }}
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
steps:
- name: Push fork PR head to GitLab (label-gated)
if: github.event_name == 'pull_request_target'
env:
PR: ${{ github.event.pull_request.number }}
run: |
if [ -z "$GITLAB_TRIGGER_TOKEN" ]; then
echo "::error::ALCF_GITLAB_TRIGGER_TOKEN secret not set (create a pipeline trigger token in the GitLab project settings)"
exit 1
fi
git init -q head && cd head
git fetch -q "https://github.com/$GITHUB_REPOSITORY" "pull/$PR/head"
if [ "$(git rev-parse FETCH_HEAD)" != "$HEAD_SHA" ]; then
echo "::error::PR head moved since labeling; re-apply the label"
exit 1
fi
# ci.skip: a push pipeline would be attributed to the project access token's
# bot user, which the Jacamar runners refuse (see header comment). Move the
# ref only, then create the pipeline via the trigger token below.
git push -q -f -o ci.skip \
"https://oauth2:${GITLAB_TOKEN}@${GITLAB_HOST}/${GITLAB_PROJECT}.git" \
"FETCH_HEAD:refs/heads/gh-pr-$PR"
RESP=$(curl -sS -X POST "$API/trigger/pipeline" \
-F "token=${GITLAB_TRIGGER_TOKEN}" -F "ref=gh-pr-$PR")
if ! echo "$RESP" | jq -e '.id' >/dev/null 2>&1; then
echo "::error::failed to trigger GitLab pipeline: $RESP"
exit 1
fi
- name: Force mirror sync
if: github.event_name != 'pull_request_target'
run: |
# Best-effort: if this fails, the scheduled mirror sync still triggers the
# pipeline, just later; the polling step below tolerates the delay.
curl -sS -X POST -H "PRIVATE-TOKEN: ${GITLAB_TOKEN}" "$API/mirror/pull" \
|| echo "::warning::mirror sync request failed; relying on scheduled sync"
- name: Wait for pipeline and adopt its result
run: |
# Transient API failures (network, rate limiting) must not fail the check:
# api() degrades to empty output, and the loops treat that as "try again".
api() { curl -sS --max-time 30 -H "PRIVATE-TOKEN: ${GITLAB_TOKEN}" "$@" || true; }
echo "waiting for a GitLab pipeline for $HEAD_SHA"
ID=""
for i in $(seq 1 80); do # up to 40 min for mirror sync + pipeline creation
ID=$(api "$API/pipelines?sha=$HEAD_SHA&order_by=id&sort=desc&per_page=1" \
| jq -r '.[0].id // empty' 2>/dev/null || true)
if [ -n "$ID" ]; then break; fi
sleep 30
done
if [ -z "$ID" ]; then
echo "::error::no GitLab pipeline appeared for $HEAD_SHA within 40 min (mirror not synced, or ref filtered by workflow rules)"
exit 1
fi
URL="https://${GITLAB_HOST}/${GITLAB_PROJECT}/-/pipelines/$ID"
echo "pipeline: $URL"
echo "PIPELINE_ID=$ID" >> "$GITHUB_ENV"
echo "[ALCF GitLab pipeline $ID]($URL)" >> "$GITHUB_STEP_SUMMARY"
prev=""
while true; do
STATUS=$(api "$API/pipelines/$ID" | jq -r '.status // empty' 2>/dev/null || true)
if [ -n "$STATUS" ] && [ "$STATUS" != "$prev" ]; then echo "status: $STATUS"; prev="$STATUS"; fi
case "$STATUS" in
success)
exit 0 ;;
failed|canceled|skipped)
echo "failed jobs:"
api "$API/pipelines/$ID/jobs?per_page=100" \
| jq -r '.[] | select(.status=="failed") | " \(.name): \(.web_url)"' 2>/dev/null \
| tee -a "$GITHUB_STEP_SUMMARY" || true
echo "::error::GitLab pipeline $STATUS: $URL"
exit 1 ;;
esac
sleep 60
done
# The GitLab instance requires an ALCF login, so mirror the job logs into this
# run where any contributor can read them.
- name: Publish GitLab job logs
if: always() && env.PIPELINE_ID != ''
run: |
api() { curl -sS --max-time 60 -H "PRIVATE-TOKEN: ${GITLAB_TOKEN}" "$@" || true; }
api "$API/pipelines/$PIPELINE_ID/jobs?per_page=100" \
| jq -r '.[] | "\(.id)|\(.name)|\(.status)"' \
| while IFS='|' read -r jid jname jstatus; do
echo "::group::${jname} — ${jstatus}"
api "$API/jobs/$jid/trace"
echo ""
echo "::endgroup::"
done