From 6fbd28cef96c4a8302fa9004404ebc61d064a32b Mon Sep 17 00:00:00 2001 From: Michel Schanen Date: Wed, 19 Aug 2026 22:20:56 +0000 Subject: [PATCH 1/2] Fix Runic check on fork PRs after checkout v7 hardening actions/checkout@v7 refuses to check out fork code from a pull_request_target workflow unless explicitly opted in, so the runic job failed before running anything. Opt in: the PR code is only parsed by Runic, never executed. Also pin the checkout to the event's head SHA instead of the branch name, and stop persisting credentials in the checkout. --- .github/workflows/Format.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/Format.yml b/.github/workflows/Format.yml index be7fd53f..9decb87b 100644 --- a/.github/workflows/Format.yml +++ b/.github/workflows/Format.yml @@ -18,7 +18,12 @@ jobs: - name: Check out repository uses: actions/checkout@v7 with: - ref: ${{github.event.pull_request.head.ref}} + # Checking out fork code in a pull_request_target workflow requires an explicit + # opt-in since checkout v7. Safe here: the PR code is only parsed by Runic, + # never executed, and we drop the credentials and pin the event's head SHA. + allow-unsafe-pr-checkout: true + persist-credentials: false + ref: ${{github.event.pull_request.head.sha}} repository: ${{github.event.pull_request.head.repo.full_name}} fetch-depth: 0 From c6e57ec9919f11cbc8dc8548f951297ef0f3d801 Mon Sep 17 00:00:00 2001 From: Michel Schanen Date: Wed, 19 Aug 2026 22:21:15 +0000 Subject: [PATCH 2/2] Attribute fork-PR ALCF pipelines to a real user The label-gated fork-PR push authenticates with a project access token, so the resulting push pipeline is attributed to the project's bot user, and ALCF's Jacamar runners refuse those ('bot account token used for job, unsupported by runner'), failing the pipeline before any job runs. Push with ci.skip so no bot-attributed pipeline is created, and create the pipeline through a pipeline trigger token instead: trigger-token pipelines run as the user who created the token, which Jacamar accepts. Requires a new ALCF_GITLAB_TRIGGER_TOKEN repository secret, and .gitlab-ci.yml now accepts the 'trigger' pipeline source. --- .github/workflows/alcf.yml | 23 ++++++++++++++++++++++- .gitlab-ci.yml | 5 ++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/.github/workflows/alcf.yml b/.github/workflows/alcf.yml index 8896a932..51f2af07 100644 --- a/.github/workflows/alcf.yml +++ b/.github/workflows/alcf.yml @@ -12,6 +12,12 @@ name: ALCF CI # which pushes the PR head to GitLab as branch gh-pr- 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: @@ -45,6 +51,7 @@ jobs: 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) @@ -52,14 +59,28 @@ jobs: 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 - git push -q -f "https://oauth2:${GITLAB_TOKEN}@${GITLAB_HOST}/${GITLAB_PROJECT}.git" \ + # 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' diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6e305ab0..095f176e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -17,7 +17,10 @@ include: workflow: rules: - - if: $CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "web" || $CI_PIPELINE_SOURCE == "api" + # "trigger" covers fork-PR pipelines, created via a pipeline trigger token by + # .github/workflows/alcf.yml so they run as a real user instead of the mirror + # project's bot (which the Jacamar runners refuse). + - if: $CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "web" || $CI_PIPELINE_SOURCE == "api" || $CI_PIPELINE_SOURCE == "trigger" default: interruptible: true # force-pushes cancel stale runs instead of queueing behind them