GitLab Manual CI #67
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: GitLab Manual CI | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| target_ref: | |
| description: "Branch, tag, or SHA in this repository to test" | |
| required: true | |
| default: "develop" | |
| code: | |
| description: "BenchKit code filter, for example: qws,genesis" | |
| required: false | |
| system: | |
| description: "System filter, for example: FugakuLN,MiyabiG" | |
| required: false | |
| app: | |
| description: "BenchPark app filter, for example: osu-micro-benchmarks" | |
| required: false | |
| benchpark: | |
| description: "Run the BenchPark path together with BenchKit" | |
| required: false | |
| type: boolean | |
| default: false | |
| park_only: | |
| description: "Run only the BenchPark path" | |
| required: false | |
| type: boolean | |
| default: false | |
| park_send: | |
| description: "Run the BenchPark send-only path" | |
| required: false | |
| type: boolean | |
| default: false | |
| concurrency: | |
| group: gitlab-manual-ci-${{ github.run_id }} | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| jobs: | |
| gitlab-manual-ci: | |
| name: Run GitLab CI manually | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check out trusted workflow ref | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| path: trusted | |
| - name: Prepare GitLab repository settings | |
| id: gitlab-repo | |
| uses: ./trusted/.github/actions/prepare-gitlab-repo | |
| with: | |
| gitlab-repo: ${{ secrets.GITLAB_REPO }} | |
| - name: Check out target ref | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ inputs.target_ref }} | |
| path: target | |
| - name: Push target ref to GitLab test branch | |
| working-directory: target | |
| env: | |
| GITLAB_TOKEN: ${{ secrets.GITLAB_TOKEN }} | |
| GITLAB_REPO_HOST_PATH: ${{ steps.gitlab-repo.outputs.host-path }} | |
| TARGET_REF: ${{ inputs.target_ref }} | |
| run: | | |
| set -euo pipefail | |
| if [ -z "${GITLAB_TOKEN}" ] || [ -z "${GITLAB_REPO_HOST_PATH}" ]; then | |
| echo "GITLAB_TOKEN and GITLAB_REPO secrets are required." | |
| exit 1 | |
| fi | |
| branch="github/manual-${GITHUB_RUN_ID}" | |
| echo "GITLAB_TEST_BRANCH=${branch}" >> "${GITHUB_ENV}" | |
| echo "Testing GitHub ref: ${TARGET_REF}" | |
| echo "Temporary GitLab branch: ${branch}" | |
| git config user.name "github-bot" | |
| git config user.email "bot@example.com" | |
| git remote add gitlab "https://oauth2:${GITLAB_TOKEN}@${GITLAB_REPO_HOST_PATH}" | |
| git push -o ci.skip gitlab "HEAD:refs/heads/${branch}" --force | |
| - name: Trigger and wait for GitLab pipeline | |
| env: | |
| GITLAB_TOKEN: ${{ secrets.GITLAB_TOKEN }} | |
| GITLAB_HOST: ${{ steps.gitlab-repo.outputs.host }} | |
| GITLAB_PROJECT_PATH: ${{ steps.gitlab-repo.outputs.project-path }} | |
| CODE_FILTER: ${{ inputs.code }} | |
| SYSTEM_FILTER: ${{ inputs.system }} | |
| BENCHPARK_APP: ${{ inputs.app }} | |
| BENCHPARK: ${{ inputs.benchpark }} | |
| PARK_ONLY: ${{ inputs.park_only }} | |
| PARK_SEND: ${{ inputs.park_send }} | |
| run: | | |
| set -euo pipefail | |
| project_encoded="$(PROJECT_PATH="${GITLAB_PROJECT_PATH}" python3 -c 'import os, urllib.parse; print(urllib.parse.quote(os.environ["PROJECT_PATH"], safe=""))')" | |
| api="https://${GITLAB_HOST}/api/v4/projects/${project_encoded}/pipeline" | |
| payload_file="$(mktemp)" | |
| PAYLOAD_FILE="${payload_file}" python3 - <<'PY' | |
| import json | |
| import os | |
| variables = [] | |
| def add_variable(key, value): | |
| if value: | |
| print(f"GitLab variable: {key}={value}") | |
| variables.append({ | |
| "key": key, | |
| "value": value, | |
| "variable_type": "env_var", | |
| }) | |
| add_variable("code", os.environ.get("CODE_FILTER", "")) | |
| add_variable("system", os.environ.get("SYSTEM_FILTER", "")) | |
| add_variable("app", os.environ.get("BENCHPARK_APP", "")) | |
| if os.environ.get("BENCHPARK") == "true": | |
| add_variable("benchpark", "true") | |
| if os.environ.get("PARK_ONLY") == "true": | |
| add_variable("park_only", "true") | |
| if os.environ.get("PARK_SEND") == "true": | |
| add_variable("park_send", "true") | |
| with open(os.environ["PAYLOAD_FILE"], "w", encoding="utf-8") as f: | |
| json.dump({ | |
| "ref": os.environ["GITLAB_TEST_BRANCH"], | |
| "variables": variables, | |
| }, f) | |
| PY | |
| response_file="$(mktemp)" | |
| http_status="$(curl --show-error --silent --output "${response_file}" --write-out "%{http_code}" --request POST --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" --header "Content-Type: application/json" --data @"${payload_file}" "${api}")" | |
| response="$(cat "${response_file}")" | |
| rm -f "${response_file}" "${payload_file}" | |
| if [ "${http_status}" -lt 200 ] || [ "${http_status}" -ge 300 ]; then | |
| echo "GitLab pipeline trigger failed with HTTP ${http_status}." | |
| echo "${response}" | |
| exit 1 | |
| fi | |
| pipeline_id="$(PIPELINE="${response}" python3 -c 'import json, os; print(json.loads(os.environ["PIPELINE"])["id"])')" | |
| pipeline_url="$(PIPELINE="${response}" python3 -c 'import json, os; print(json.loads(os.environ["PIPELINE"]).get("web_url", ""))')" | |
| echo "GitLab pipeline: ${pipeline_url}" | |
| pipeline_api="https://${GITLAB_HOST}/api/v4/projects/${project_encoded}/pipelines/${pipeline_id}" | |
| for _ in $(seq 1 180); do | |
| response_file="$(mktemp)" | |
| http_status="$(curl --show-error --silent --output "${response_file}" --write-out "%{http_code}" --header "PRIVATE-TOKEN: ${GITLAB_TOKEN}" "${pipeline_api}")" | |
| response="$(cat "${response_file}")" | |
| rm -f "${response_file}" | |
| if [ "${http_status}" -lt 200 ] || [ "${http_status}" -ge 300 ]; then | |
| echo "GitLab pipeline status request failed with HTTP ${http_status}." | |
| echo "${response}" | |
| exit 1 | |
| fi | |
| status="$(PIPELINE="${response}" python3 -c 'import json, os; print(json.loads(os.environ["PIPELINE"])["status"])')" | |
| echo "GitLab pipeline status: ${status}" | |
| case "${status}" in | |
| success) | |
| exit 0 | |
| ;; | |
| failed|canceled|skipped) | |
| exit 1 | |
| ;; | |
| manual) | |
| echo "GitLab pipeline is waiting for manual action." | |
| exit 1 | |
| ;; | |
| esac | |
| sleep 20 | |
| done | |
| echo "Timed out waiting for GitLab pipeline ${pipeline_id}." | |
| exit 1 | |
| - name: Delete GitLab test branch | |
| if: always() | |
| working-directory: trusted | |
| env: | |
| GITLAB_TOKEN: ${{ secrets.GITLAB_TOKEN }} | |
| GITLAB_REPO_HOST_PATH: ${{ steps.gitlab-repo.outputs.host-path }} | |
| run: | | |
| set -euo pipefail | |
| if [ -n "${GITLAB_TEST_BRANCH:-}" ] && [ -n "${GITLAB_REPO_HOST_PATH:-}" ]; then | |
| git remote add gitlab-cleanup "https://oauth2:${GITLAB_TOKEN}@${GITLAB_REPO_HOST_PATH}" || true | |
| git push gitlab-cleanup --delete "${GITLAB_TEST_BRANCH}" || true | |
| fi |