servo/.github/workflows/windows.yml
Delan Azabani 642c25d9a7
CI: use monitor API for self-hosted runners (#33315)
Signed-off-by: Delan Azabani <dazabani@igalia.com>
2024-09-04 17:11:32 +00:00

259 lines
11 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

name: Windows
on:
workflow_call:
inputs:
profile:
required: false
default: "release"
type: string
unit-tests:
required: false
default: false
type: boolean
upload:
required: false
default: false
type: boolean
github-release-id:
required: false
type: string
workflow_dispatch:
inputs:
profile:
required: false
default: "release"
options: ["release", "debug", "production"]
type: choice
unit-tests:
required: false
default: false
type: boolean
upload:
required: false
default: false
type: boolean
env:
RUST_BACKTRACE: 1
SHELL: /bin/bash
CCACHE: "ccache"
CARGO_TARGET_DIR: C:\\a\\servo\\servo\\target
# clang_sys will search msys path before Program Files\LLVM
# so we need to override this behaviour until we update clang-sys
# https://github.com/KyleMayes/clang-sys/issues/150
LIBCLANG_PATH: C:\Program Files\LLVM\bin
RUSTUP_WINDOWS_PATH_ADD_BIN: 1
jobs:
# Automatic runner selection for job: build
# Runs the underlying job (“workload”) on a self-hosted runner if available,
# with the help of a `runner-select` job and a `runner-timeout` job.
# Selects a self-hosted runner if available, or else a GitHub-hosted runner.
# We generate a unique id for the workload, find an idle self-hosted runner
# with the given `image:` label that wasnt already reserved by another
# `runner-select` job run, and reserve it with a `reserved-for:<id>` label.
runner-select:
name: Select Runner
runs-on: ubuntu-latest
outputs:
unique-id: ${{ steps.select.outputs.unique_id }}
selected-runner-label: ${{ steps.select.outputs.selected_runner_label }}
is-self-hosted: ${{ steps.select.outputs.is_self_hosted }}
steps:
- name: Select and reserve best available runner
id: select
# Set the variables below to your desired runner images, runner scope
# (org or repo), and monitor API URL.
run: |
github_hosted_runner_label=windows-2022
self_hosted_image_name=servo-windows10
self_hosted_runner_scope=/orgs/${{ github.repository_owner }}/actions/runners
monitor_api_base_url=https://ci0.servo.org
set -euo pipefail
fall_back_to_github_hosted() {
echo 'Falling back to GitHub-hosted runner'
echo "selected_runner_label=$github_hosted_runner_label" | tee -a $GITHUB_OUTPUT
echo 'is_self_hosted=false' | tee -a $GITHUB_OUTPUT
exit 0
}
# Generate a unique id that allows the workload job to find the runner
# we are reserving for it (via runner labels), and allows the timeout
# job to find the workload job run (via the jobs friendly name), even
# if there are multiple instances in the workflow call tree.
unique_id=$(uuidgen)
echo "unique_id=$unique_id" | tee -a $GITHUB_OUTPUT
# Disable self-hosted runners by creating a repository variable named
# NO_SELF_HOSTED_RUNNERS with any non-empty value.
# <https://github.com/servo/servo/settings/variables/actions>
if [ -n '${{ vars.NO_SELF_HOSTED_RUNNERS }}' ]; then
echo 'NO_SELF_HOSTED_RUNNERS is set!'
fall_back_to_github_hosted
fi
# Use the monitor API to reserve a runner. If we get an object with
# runner details, we succeeded. If we get null, we failed.
take_runner_url=$monitor_api_base_url/$self_hosted_image_name/$unique_id/${{ github.repository }}/${{ github.run_id }}
echo
echo POST "$take_runner_url"
if ! curl -fsS --max-time 10 -X POST "$take_runner_url" \
-H 'Authorization: Bearer ${{ secrets.SERVO_CI_MONITOR_API_TOKEN }}' \
| jq -e; then
echo
echo 'No self-hosted runners available!'
fall_back_to_github_hosted
fi
echo
echo "selected_runner_label=reserved-for:$unique_id" | tee -a $GITHUB_OUTPUT
echo 'is_self_hosted=true' | tee -a $GITHUB_OUTPUT
# In the unlikely event a self-hosted runner was selected and reserved but it
# goes down before the workload starts, cancel the workflow run.
runner-timeout:
needs:
- runner-select
if: ${{ fromJSON(needs.runner-select.outputs.is-self-hosted) }}
name: Detect Runner Timeout
runs-on: ubuntu-latest
steps:
- name: Wait a bit
run: sleep 30
- name: Cancel if workload job is still queued
run: |
run_url=/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}
export GH_TOKEN=${{ secrets.GITHUB_TOKEN }}
if [ "$(gh api "$run_url/jobs" \
| jq -er --arg id '${{ needs.runner-select.outputs.unique-id }}' \
'.jobs[] | select(.name | contains("[" + $id + "]")) | .status'
)" = queued ]; then
echo 'Timeout waiting for runner assignment!'
echo 'Hint: does this repo have permission to access the runner group?'
echo 'Hint: https://github.com/organizations/servo/settings/actions/runner-groups'
echo
echo 'Cancelling workflow run'
gh api "$run_url/cancel" --method POST
exit 1
fi
build:
needs:
- runner-select
name: Windows Build [${{ needs.runner-select.outputs.unique-id }}]
runs-on: ${{ needs.runner-select.outputs.selected-runner-label }}
steps:
- if: ${{ ! fromJSON(needs.runner-select.outputs.is-self-hosted) && github.event_name != 'pull_request_target' }}
uses: actions/checkout@v4
- if: ${{ ! fromJSON(needs.runner-select.outputs.is-self-hosted) && github.event_name == 'pull_request_target' }}
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 1
# Faster checkout for self-hosted runner that uses prebaked repo.
- if: ${{ fromJSON(needs.runner-select.outputs.is-self-hosted) && github.event_name != 'pull_request_target' }}
run: git fetch --depth=1 origin $env:GITHUB_SHA
- if: ${{ fromJSON(needs.runner-select.outputs.is-self-hosted) && github.event_name == 'pull_request_target' }}
run: git fetch --depth=1 origin refs/pull/${{ github.event_number }}/head
- if: ${{ fromJSON(needs.runner-select.outputs.is-self-hosted) }}
# Same as `git switch --detach FETCH_HEAD`, but fixes up dirty working
# trees, in case the runner image was baked with a dirty working tree.
run: |
git switch --detach
git reset --hard FETCH_HEAD
- name: ccache
# FIXME: “Error: Restoring cache failed: Error: Unable to locate executable file: sh.”
if: ${{ ! fromJSON(needs.runner-select.outputs.is-self-hosted) }}
uses: hendrikmuhs/ccache-action@v1.2
# Install missing tools in a GitHub-hosted runner.
# Workaround for https://github.com/actions/runner-images/issues/10001:
- name: Upgrade llvm
if: ${{ ! fromJSON(needs.runner-select.outputs.is-self-hosted) }}
run: choco upgrade llvm
- name: Install wixtoolset
if: ${{ ! fromJSON(needs.runner-select.outputs.is-self-hosted) }}
run: |
choco install wixtoolset
echo "C:\\Program Files (x86)\\WiX Toolset v3.11\\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- uses: actions/setup-python@v5
if: ${{ ! fromJSON(needs.runner-select.outputs.is-self-hosted) }}
with:
python-version: "3.10"
- name: Bootstrap
if: ${{ ! fromJSON(needs.runner-select.outputs.is-self-hosted) }}
run: |
python -m pip install --upgrade pip
python mach fetch
python mach bootstrap-gstreamer
# For some reason WiX isn't currently on the GitHub runner path. This is a
# temporary workaround until that is fixed.
- name: Add WiX to Path
if: ${{ ! fromJSON(needs.runner-select.outputs.is-self-hosted) }}
run: |
"$env:WIX\bin" >> $env:GITHUB_PATH
# Always install crown, even on self-hosted runners, because it is tightly
# coupled to the rustc version, and we may have the wrong version if the
# commit we are building uses a different rustc version.
- name: Install crown
run: cargo install --path support/crown --force
- name: Debug logging for incremental builds
if: ${{ fromJSON(needs.runner-select.outputs.is-self-hosted) }}
run: |
cat C:\init\incremental_build_debug.txt
echo "`$env:LIBCLANG_PATH now = $env:LIBCLANG_PATH"
echo "`$env:PATH now = $env:PATH"
- name: Build (${{ inputs.profile }})
run: |
python mach build --use-crown --locked --${{ inputs.profile }}
cp C:\a\servo\servo\target\cargo-timings C:\a\servo\servo\target\cargo-timings-windows -Recurse
- name: Copy resources
if: ${{ ! fromJSON(needs.runner-select.outputs.is-self-hosted) }}
# GitHub-hosted runners check out the repo on D: drive.
run: cp D:\a\servo\servo\resources C:\a\servo\servo -Recurse
- name: Smoketest
run: python mach smoketest --${{ inputs.profile }}
- name: Unit tests
if: ${{ inputs.unit-tests }}
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3 # https://github.com/servo/servo/issues/30683
command: python mach test-unit --${{ inputs.profile }} -- -- --test-threads=1
- name: Archive build timing
uses: actions/upload-artifact@v4
with:
name: cargo-timings-windows
# Using a wildcard here ensures that the archive includes the path.
path: C:\\a\\servo\\servo\\target\\cargo-timings-*
- name: Build mach package
run: python mach package --${{ inputs.profile }}
- name: Upload artifact for mach package
uses: actions/upload-artifact@v4
with:
name: win
# These files are available
# MSI Installer: C:\a\servo\servo\target\${{ inputs.profile }}\msi\Installer.msi
# Bundle: C:\a\servo\servo\target\${{ inputs.profile }}\msi\Servo.exe
# Zip: C:\a\servo\servo\target\${{ inputs.profile }}\msi\Servo.zip
path: C:\\a\\servo\\servo\\target\\${{ inputs.profile }}\\msi\\Servo.exe
- name: Upload nightly
if: ${{ inputs.upload }}
run: |
python mach upload-nightly windows-msvc --secret-from-environment `
--github-release-id ${{ inputs.github-release-id }}
env:
S3_UPLOAD_CREDENTIALS: ${{ secrets.S3_UPLOAD_CREDENTIALS }}
NIGHTLY_REPO_TOKEN: ${{ secrets.NIGHTLY_REPO_TOKEN }}
NIGHTLY_REPO: ${{ github.repository_owner }}/servo-nightly-builds