Test new workflow. #6
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: "Workflow/Bisect" | ||
defaults: | ||
run: | ||
shell: bash --noprofile --norc -euo pipefail {0} | ||
on: | ||
workflow_dispatch: | ||
inputs: | ||
runner: | ||
description: "Runner label" | ||
required: false | ||
default: linux-amd64-cpu16 | ||
type: string | ||
good_ref: | ||
description: "Good ref/sha/tag/branch. Defaults to latest release tag. Accepts '-Nd' (e.g., '-14d') to mean 'origin/main as of N days ago'." | ||
required: false | ||
type: string | ||
bad_ref: | ||
description: "Bad ref/sha/tag/branch. Defaults to main. Accepts '-Nd' (e.g., '-14d') to mean 'origin/main as of N days ago'." | ||
required: false | ||
type: string | ||
launch_args: | ||
description: "Arguments for .devcontainer/launch.sh -d" | ||
required: false | ||
default: "" | ||
type: string | ||
preset: | ||
description: "CMake preset" | ||
required: false | ||
default: "" | ||
type: string | ||
cmake_options: | ||
description: "Additional options passed to CMake preset configure (e.g. -DVAR=ON)" | ||
required: false | ||
default: "" | ||
type: string | ||
configure_override: | ||
description: "Command to run for configuration; overrides preset and cmake_options" | ||
required: false | ||
default: "" | ||
type: string | ||
build_targets: | ||
description: "Space separated ninja build targets" | ||
required: false | ||
default: "" | ||
type: string | ||
ctest_targets: | ||
description: "Space separated CTest targets" | ||
required: false | ||
default: "" | ||
type: string | ||
lit_precompile_tests: | ||
description: "Space-separated libcudacxx lit test paths to precompile without execution" | ||
required: false | ||
default: "" | ||
type: string | ||
lit_tests: | ||
description: "Space-separated libcudacxx lit test paths to execute" | ||
required: false | ||
default: "" | ||
type: string | ||
custom_test_cmd: | ||
description: "Command run after build and tests" | ||
required: false | ||
default: "" | ||
type: string | ||
workflow_call: | ||
inputs: | ||
runner: | ||
description: "Runner label" | ||
required: false | ||
default: linux-amd64-cpu16 | ||
type: string | ||
good_ref: | ||
description: "Good ref/sha/tag/branch. Defaults to latest release tag. Accepts '-Nd' (e.g., '-14d') to mean 'origin/main as of N days ago'." | ||
required: false | ||
type: string | ||
bad_ref: | ||
description: "Bad ref/sha/tag/branch. Defaults to HEAD. Accepts '-Nd' (e.g., '-14d') to mean 'origin/main as of N days ago'." | ||
required: false | ||
type: string | ||
launch_args: | ||
description: "Arguments for .devcontainer/launch.sh -d" | ||
required: false | ||
default: "" | ||
type: string | ||
preset: | ||
description: "CMake preset" | ||
required: false | ||
default: "" | ||
type: string | ||
cmake_options: | ||
description: "Additional options passed to CMake preset configure (e.g. -DVAR=ON)" | ||
required: false | ||
default: "" | ||
type: string | ||
configure_override: | ||
description: "Command to run for configuration; overrides preset and cmake_options" | ||
required: false | ||
default: "" | ||
type: string | ||
build_targets: | ||
description: "Space separated ninja build targets" | ||
required: false | ||
default: "" | ||
type: string | ||
ctest_targets: | ||
description: "Space separated CTest targets" | ||
required: false | ||
default: "" | ||
type: string | ||
lit_precompile_tests: | ||
description: "Space-separated libcudacxx lit test paths to precompile without execution" | ||
required: false | ||
default: "" | ||
type: string | ||
lit_tests: | ||
description: "Space-separated libcudacxx lit test paths to execute" | ||
required: false | ||
default: "" | ||
type: string | ||
custom_test_cmd: | ||
description: "Command run after build and tests" | ||
required: false | ||
default: "" | ||
type: string | ||
jobs: | ||
# Hash all of the inputs and generate a descriptive, but unique, name for the bisect job. | ||
# This is necessary because GitHub Actions does not provide an easy way to get the numeric | ||
# job id from within a running job, unless the name is unique across the entire run. | ||
generate-job-name: | ||
name: Generate Unique Job Name | ||
runs-on: ubuntu-latest | ||
outputs: | ||
job-name: ${{ steps.set-name.outputs.unique-name }} | ||
steps: | ||
- name: Set unique name | ||
id: set-name | ||
run: | | ||
# Hash the inputs to create a unique identifier | ||
input_string=$(cat <<HASH | ||
${{ inputs.runner }} | ||
${{ inputs.launch_args }} | ||
${{ inputs.preset }} | ||
${{ inputs.cmake_options }} | ||
${{ inputs.configure_override }} | ||
${{ inputs.build_targets }} | ||
${{ inputs.ctest_targets }} | ||
${{ inputs.lit_precompile_tests }} | ||
${{ inputs.lit_tests }} | ||
${{ inputs.custom_test_cmd }} | ||
${{ inputs.good_ref }} | ||
${{ inputs.bad_ref }} | ||
HASH | ||
) | ||
hash=$(echo -n "$input_string" | sha256sum | awk '{print $1}') | ||
short_hash=${hash:0:8} | ||
function sanitize() { | ||
echo "$1" | tr -cd '[:alnum:]-' | ||
} | ||
function compress() { | ||
input=$1 | ||
input_length=${#input} | ||
# "begin.and.end" -> "begin_d.end" | ||
delim="_" | ||
keep_chars=5 | ||
compressed_str=${input:0:keep_chars}$delim${input: -keep_chars} | ||
compressed_length=${#compressed_str} | ||
if [[ $input_length -gt $compressed_length ]]; then | ||
echo "$compressed_str" | ||
else | ||
echo "$input" | ||
fi | ||
} | ||
preset=$(sanitize "${{ inputs.preset }}") | ||
good_ref=$(sanitize "${{ inputs.good_ref }}") | ||
bad_ref=$(sanitize "${{ inputs.bad_ref }}") | ||
build_targets=$(sanitize "${{ inputs.build_targets }}") | ||
ctest_targets=$(sanitize "${{ inputs.ctest_targets }}") | ||
lit_precompile_tests=$(sanitize "${{ inputs.lit_precompile_tests }}") | ||
lit_tests=$(sanitize "${{ inputs.lit_tests }}") | ||
build_targets_part=$(compress "$build_targets") | ||
ctest_targets_part=$(compress "$ctest_targets") | ||
# Parse "--cuda XX.Y" / "-c XX.Y" and "--host <str>" / "-H <str>" | ||
launch_args="${{ inputs.launch_args }}" | ||
cuda_version=$(grep -oP '(?:--cuda|-c)\s+\K\S+' <<< "$launch_args" || true) | ||
host_name=$(grep -oP '(?:--host|-H)\s+\K\S+' <<< "$launch_args" || true) | ||
# Parse `amd64/arm64` and -gpu-<gpu_name> from runner name. | ||
# Ex: 'linux-amd64-gpu-rtxa6000-latest-1' | ||
runner=${{ inputs.runner }} | ||
cpu_arch=$(echo "${runner}" | grep -oP '(?:^|-)\K(?:amd64|arm64)(?=-)' || true) | ||
gpu_name=$(echo "${runner}" | grep -oP '(?:-gpu-)\K\S+' || true) | ||
unique_name="bisect" | ||
declare -a vars=( | ||
"runner" | ||
"cuda_version" | ||
"host_name" | ||
"preset" | ||
"build_targets_part" | ||
"ctest_targets_part" | ||
"lit_precompile_tests" | ||
"lit_tests" | ||
"gpu_name" | ||
"cpu_arch" | ||
"short_hash" | ||
) | ||
for var in "${vars[@]}"; do | ||
val=${!var} | ||
if [[ -n "$val" ]]; then | ||
unique_name+="-$val"" | ||
fi | ||
done | ||
echo "Unique job name: $unique_name" | ||
echo "unique-name=$unique_name" >> "$GITHUB_OUTPUT" | ||
bisect: | ||
needs: [generate-job-name] | ||
name: ${{ needs.generate-job-name.outputs.job-name }} | ||
runs-on: ${{ inputs.runner }} | ||
permissions: | ||
id-token: write | ||
contents: read | ||
steps: | ||
- name: Checkout repository | ||
uses: actions/checkout@v4 | ||
with: | ||
persist-credentials: false | ||
fetch-depth: 0 # FULL history | ||
fetch-tags: true # Ensure tags are present | ||
- name: Get AWS credentials for sccache bucket | ||
uses: aws-actions/configure-aws-credentials@v4 | ||
with: | ||
role-to-assume: arn:aws:iam::279114543810:role/gha-oidc-NVIDIA | ||
aws-region: us-east-2 | ||
role-duration-seconds: 43200 # 12 hours | ||
- name: Prepare AWS config for devcontainer | ||
run: | | ||
# The devcontainer will mount this path to the home directory | ||
aws_dir="${{ github.workspace }}/.aws" | ||
mkdir -p "${aws_dir}" | ||
cat > "${aws_dir}/config" <<EOF | ||
[default] | ||
bucket=rapids-sccache-devs | ||
region=us-east-2 | ||
EOF | ||
cat > "${aws_dir}/credentials" <<EOF | ||
[default] | ||
aws_access_key_id=${AWS_ACCESS_KEY_ID} | ||
aws_session_token=${AWS_SESSION_TOKEN} | ||
aws_secret_access_key=${AWS_SECRET_ACCESS_KEY} | ||
EOF | ||
chmod 0600 "${aws_dir}/credentials" | ||
chmod 0664 "${aws_dir}/config" | ||
- name: Run git bisect | ||
env: | ||
GITHUB_TOKEN: ${{ github.token }} | ||
LAUNCH_ARGS: ${{ inputs.launch_args }} | ||
GITHUB_REPOSITORY: ${{ github.repository }} | ||
# AWS credentials from the configure-aws-credentials action | ||
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }} | ||
AWS_SESSION_TOKEN: ${{ env.AWS_SESSION_TOKEN }} | ||
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }} | ||
AWS_REGION: ${{ env.AWS_REGION }} | ||
run: | | ||
echo -e "\e[1;34mLaunching devcontainer and running git bisect...\e[0m" | ||
GPU_ARGS="" | ||
if [[ "${{ inputs.runner }}" == *"-gpu-"* ]]; then | ||
if [[ ! "${LAUNCH_ARGS}" =~ "--gpus" ]]; then | ||
echo "GPU runner detected; enabling '--gpus all'" | ||
GPU_ARGS="--gpus all" | ||
else | ||
echo "GPU runner detected, but '--gpus' already present in LAUNCH_ARGS" | ||
fi | ||
fi | ||
# Grab the url for this step summary | ||
run="$GITHUB_RUN_ID" | ||
attempt="${GITHUB_RUN_ATTEMPT:-1}" | ||
server="${GITHUB_SERVER_URL:-https://github.com}" | ||
repo="$GITHUB_REPOSITORY" | ||
job_name="${{ needs.generate-job-name.outputs.job-name }}" | ||
job_id=$( | ||
gh api --paginate --slurp \ | ||
repos/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}/jobs \ | ||
--jq ".jobs[] | select(.name==\"${job_name}\") | .id" | ||
) || : | ||
echo "Job name: ${job_name}" | ||
echo "Job names:" | ||
gh api --paginate --slurp \ | ||
repos/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}/jobs \ | ||
--jq ".jobs[] | .name" || : | ||
echo "Jobs:" | ||
gh api --paginate --slurp \ | ||
repos/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}/jobs \ | ||
--jq ".jobs[] | .name" || : | ||
GHA_LOG_URL="$server/$repo/actions/runs/$run/jobs/$job_id" | ||
STEP_SUMMARY_URL="$server/$repo/actions/runs/$run/attempts/$attempt#summary-$job_id" | ||
echo -e "\e[1;34mGHA Log URL: $GHA_LOG_URL\e[0m" | ||
echo -e "\e[1;34mBisection Results: $STEP_SUMMARY_URL\e[0m" | ||
mkdir -p /tmp/shared | ||
rc=0 | ||
set -x | ||
.devcontainer/launch.sh -d ${LAUNCH_ARGS} ${GPU_ARGS} \ | ||
--env "AWS_ROLE_ARN=" \ | ||
--env "AWS_REGION=${AWS_REGION}" \ | ||
--env "SCCACHE_REGION=${AWS_REGION}" \ | ||
--env "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" \ | ||
--env "AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}" \ | ||
--env "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" \ | ||
--env "GITHUB_REPOSITORY=${GITHUB_REPOSITORY}" \ | ||
--env "LAUNCH_ARGS=${LAUNCH_ARGS} ${GPU_ARGS}" \ | ||
--env "STEP_SUMMARY_URL=${STEP_SUMMARY_URL}" \ | ||
--env "GHA_LOG_URL=${GHA_LOG_URL}" \ | ||
--volume "/tmp/shared:/tmp/shared" \ | ||
-- ./ci/util/git_bisect.sh \ | ||
--summary-file "/tmp/shared/summary.md" \ | ||
--good-ref "${{ inputs.good_ref }}" \ | ||
--bad-ref "${{ inputs.bad_ref }}" \ | ||
--preset "${{ inputs.preset }}" \ | ||
--cmake-options "${{ inputs.cmake_options }}" \ | ||
--configure-override "${{ inputs.configure_override }}" \ | ||
--build-targets "${{ inputs.build_targets }}" \ | ||
--ctest-targets "${{ inputs.ctest_targets }}" \ | ||
--lit-precompile-tests "${{ inputs.lit_precompile_tests }}" \ | ||
--lit-tests "${{ inputs.lit_tests }}" \ | ||
--custom-test-cmd "${{ inputs.custom_test_cmd }}" \ | ||
|| rc=$? | ||
set +x | ||
# Append the summary (if any) to the GitHub step summary | ||
if [[ -d /tmp/shared ]]; then | ||
find /tmp/shared -type f -exec cat {} \; >> "$GITHUB_STEP_SUMMARY" || : | ||
fi | ||
echo -e "\e[1;34mGHA Log URL: $GHA_LOG_URL\e[0m" | ||
echo -e "\e[1;34mBisection Results: $STEP_SUMMARY_URL\e[0m" | ||
exit $rc |