diff --git a/.devcontainer/cuda11.8-gcc11/devcontainer.json b/.devcontainer/cuda11.8-gcc11/devcontainer.json new file mode 100644 index 000000000..d359badde --- /dev/null +++ b/.devcontainer/cuda11.8-gcc11/devcontainer.json @@ -0,0 +1,42 @@ +{ + "shutdownAction": "stopContainer", + "image": "rapidsai/devcontainers:23.10-cpp-gcc11-cuda11.8-ubuntu22.04", + "hostRequirements": { + "gpu": true + }, + "initializeCommand": [ + "/bin/bash", + "-c", + "mkdir -m 0755 -p ${localWorkspaceFolder}/.{aws,cache,config}" + ], + "containerEnv": { + "SCCACHE_REGION": "us-east-2", + "SCCACHE_BUCKET": "rapids-sccache-devs", + "VAULT_HOST": "https://vault.ops.k8s.rapids.ai", + "HISTFILE": "${containerWorkspaceFolder}/.cache/._bash_history", + "DEVCONTAINER_NAME": "cuda11.8-gcc11", + "CUCO_CUDA_VERSION": "11.8", + "CUCO_HOST_COMPILER": "gcc", + "CUCO_HOST_COMPILER_VERSION": "11" + }, + "workspaceFolder": "/home/coder/${localWorkspaceFolderBasename}", + "workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/${localWorkspaceFolderBasename},type=bind,consistency=consistent", + "mounts": [ + "source=${localWorkspaceFolder}/.aws,target=/home/coder/.aws,type=bind,consistency=consistent", + "source=${localWorkspaceFolder}/.cache,target=/home/coder/.cache,type=bind,consistency=consistent", + "source=${localWorkspaceFolder}/.config,target=/home/coder/.config,type=bind,consistency=consistent" + ], + "customizations": { + "vscode": { + "extensions": [ + "llvm-vs-code-extensions.vscode-clangd" + ], + "settings": { + "clangd.arguments": [ + "--compile-commands-dir=${workspaceFolder}/build/latest" + ] + } + } + }, + "name": "cuda11.8-gcc11" +} diff --git a/.devcontainer/cuda12.2-gcc12/devcontainer.json b/.devcontainer/cuda12.2-gcc12/devcontainer.json index 199ce44f4..936429f0d 100644 --- a/.devcontainer/cuda12.2-gcc12/devcontainer.json +++ b/.devcontainer/cuda12.2-gcc12/devcontainer.json @@ -1,6 +1,6 @@ { "shutdownAction": "stopContainer", - "image": "rapidsai/devcontainers:23.08-cpp-gcc12-cuda12.2-ubuntu22.04", + "image": "rapidsai/devcontainers:23.10-cpp-gcc12-cuda12.2-ubuntu22.04", "hostRequirements": { "gpu": true }, @@ -14,7 +14,10 @@ "SCCACHE_BUCKET": "rapids-sccache-devs", "VAULT_HOST": "https://vault.ops.k8s.rapids.ai", "HISTFILE": "${containerWorkspaceFolder}/.cache/._bash_history", - "DEVCONTAINER_NAME": "cuda12.2-gcc12" + "DEVCONTAINER_NAME": "cuda12.2-gcc12", + "CUCO_CUDA_VERSION": "12.2", + "CUCO_HOST_COMPILER": "gcc", + "CUCO_HOST_COMPILER_VERSION": "12" }, "workspaceFolder": "/home/coder/${localWorkspaceFolderBasename}", "workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/${localWorkspaceFolderBasename},type=bind,consistency=consistent", diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 84cfa82cc..936429f0d 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,37 +1,42 @@ { - "shutdownAction": "stopContainer", - "image": "rapidsai/devcontainers:23.08-cpp-gcc12-cuda12.2-ubuntu22.04", - "hostRequirements": { - "gpu": true - }, - "initializeCommand": [ - "/bin/bash", - "-c", - "mkdir -m 0755 -p ${localWorkspaceFolder}/.{aws,cache,config}" - ], - "containerEnv": { - "SCCACHE_REGION": "us-east-2", - "SCCACHE_BUCKET": "rapids-sccache-devs", - "VAULT_HOST": "https://vault.ops.k8s.rapids.ai", - "HISTFILE": "${containerWorkspaceFolder}/.cache/._bash_history" - }, - "workspaceFolder": "/home/coder/${localWorkspaceFolderBasename}", - "workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/${localWorkspaceFolderBasename},type=bind,consistency=consistent", - "mounts": [ - "source=${localWorkspaceFolder}/.aws,target=/home/coder/.aws,type=bind,consistency=consistent", - "source=${localWorkspaceFolder}/.cache,target=/home/coder/.cache,type=bind,consistency=consistent", - "source=${localWorkspaceFolder}/.config,target=/home/coder/.config,type=bind,consistency=consistent" - ], - "customizations": { - "vscode": { - "extensions": [ - "llvm-vs-code-extensions.vscode-clangd" - ], - "settings": { - "clangd.arguments": [ - "--compile-commands-dir=${workspaceFolder}/build/latest" - ] - } - } + "shutdownAction": "stopContainer", + "image": "rapidsai/devcontainers:23.10-cpp-gcc12-cuda12.2-ubuntu22.04", + "hostRequirements": { + "gpu": true + }, + "initializeCommand": [ + "/bin/bash", + "-c", + "mkdir -m 0755 -p ${localWorkspaceFolder}/.{aws,cache,config}" + ], + "containerEnv": { + "SCCACHE_REGION": "us-east-2", + "SCCACHE_BUCKET": "rapids-sccache-devs", + "VAULT_HOST": "https://vault.ops.k8s.rapids.ai", + "HISTFILE": "${containerWorkspaceFolder}/.cache/._bash_history", + "DEVCONTAINER_NAME": "cuda12.2-gcc12", + "CUCO_CUDA_VERSION": "12.2", + "CUCO_HOST_COMPILER": "gcc", + "CUCO_HOST_COMPILER_VERSION": "12" + }, + "workspaceFolder": "/home/coder/${localWorkspaceFolderBasename}", + "workspaceMount": "source=${localWorkspaceFolder},target=/home/coder/${localWorkspaceFolderBasename},type=bind,consistency=consistent", + "mounts": [ + "source=${localWorkspaceFolder}/.aws,target=/home/coder/.aws,type=bind,consistency=consistent", + "source=${localWorkspaceFolder}/.cache,target=/home/coder/.cache,type=bind,consistency=consistent", + "source=${localWorkspaceFolder}/.config,target=/home/coder/.config,type=bind,consistency=consistent" + ], + "customizations": { + "vscode": { + "extensions": [ + "llvm-vs-code-extensions.vscode-clangd" + ], + "settings": { + "clangd.arguments": [ + "--compile-commands-dir=${workspaceFolder}/build/latest" + ] + } } -} \ No newline at end of file + }, + "name": "cuda12.2-gcc12" +} diff --git a/.devcontainer/make_devcontainers.sh b/.devcontainer/make_devcontainers.sh index 700dc3713..a3705963b 100755 --- a/.devcontainer/make_devcontainers.sh +++ b/.devcontainer/make_devcontainers.sh @@ -20,24 +20,103 @@ # GitHub docs on using multiple devcontainer.json files: # https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/adding-a-dev-container-configuration/introduction-to-dev-containers#devcontainerjson +set -euo pipefail + # Ensure the script is being executed in its containing directory cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; -# The root devcontainer.json file is used as a template for all other devcontainer.json files -# by replacing the `image:` field with the appropriate image name -base_devcontainer_file="./devcontainer.json" +function usage { + echo "Usage: $0 [--clean] [-h/--help] [-v/--verbose]" + echo " --clean Remove stale devcontainer subdirectories" + echo " -h, --help Display this help message" + echo " -v, --verbose Enable verbose mode (set -x)" + exit 1 +} +# Function to update the devcontainer.json file with the provided parameters +update_devcontainer() { + local input_file="$1" + local output_file="$2" + local name="$3" + local cuda_version="$4" + local compiler_name="$5" + local compiler_version="$6" + local os="$7" + local devcontainer_version="$8" -# Read matrix.yaml and convert it to json -matrix_json=$(yq -o json ../ci/matrix.yml) + local IMAGE_ROOT="rapidsai/devcontainers:${devcontainer_version}-cpp-" + local image="${IMAGE_ROOT}${compiler_name}${compiler_version}-cuda${cuda_version}-${os}" + + jq --arg image "$image" --arg name "$name" \ + --arg cuda_version "$cuda_version" --arg compiler_name "$compiler_name" \ + --arg compiler_version "$compiler_version" --arg os "$os" \ + '.image = $image | .name = $name | .containerEnv.DEVCONTAINER_NAME = $name | + .containerEnv.CUCO_CUDA_VERSION = $cuda_version | .containerEnv.CUCO_HOST_COMPILER = $compiler_name | + .containerEnv.CUCO_HOST_COMPILER_VERSION = $compiler_version' \ + "$input_file" > "$output_file" +} + +make_name() { + local cuda_version="$1" + local compiler_name="$2" + local compiler_version="$3" + + echo "cuda$cuda_version-$compiler_name$compiler_version" +} + +CLEAN=false +VERBOSE=false +while [[ $# -gt 0 ]]; do + case "$1" in + --clean) + CLEAN=true + ;; + -h|--help) + usage + ;; + -v|--verbose) + VERBOSE=true + ;; + *) + usage + ;; + esac + shift +done + +MATRIX_FILE="../ci/matrix.yml" +# Enable verbose mode if requested +if [ "$VERBOSE" = true ]; then + set -x + cat ${MATRIX_FILE} +fi + +# Read matrix.yaml and convert it to json +matrix_json=$(yq -o json ${MATRIX_FILE}) # Get the devcontainer image version and define image tag root -DEVCONTAINER_VERSION=$(echo "$matrix_json" | jq -r '.devcontainer_version') -IMAGE_ROOT="rapidsai/devcontainers:${DEVCONTAINER_VERSION}-cpp-" +readonly DEVCONTAINER_VERSION=$(echo "$matrix_json" | jq -r '.devcontainer_version') # Get unique combinations of cuda version, compiler name/version, and Ubuntu version -combinations=$(echo "$matrix_json" | jq -c '[.pull_request.nvcc[] | {cuda: .cuda, compiler_name: .compiler.name, compiler_version: .compiler.version, os: .os}] | unique | .[]') +readonly combinations=$(echo "$matrix_json" | jq -c '[.pull_request.nvcc[] | {cuda: .cuda, compiler_name: .compiler.name, compiler_version: .compiler.version, os: .os}] | unique | .[]') + +# Update the base devcontainer with the default values +# The root devcontainer.json file is used as the default container as well as a template for all +# other devcontainer.json files by replacing the `image:` field with the appropriate image name +readonly base_devcontainer_file="./devcontainer.json" +readonly NEWEST_GCC_CUDA_ENTRY=$(echo "$combinations" | jq -rs '[.[] | select(.compiler_name == "gcc")] | sort_by((.cuda | tonumber), (.compiler_version | tonumber)) | .[-1]') +readonly DEFAULT_CUDA=$(echo "$NEWEST_GCC_CUDA_ENTRY" | jq -r '.cuda') +readonly DEFAULT_COMPILER_NAME=$(echo "$NEWEST_GCC_CUDA_ENTRY" | jq -r '.compiler_name') +readonly DEFAULT_COMPILER_VERSION=$(echo "$NEWEST_GCC_CUDA_ENTRY" | jq -r '.compiler_version') +readonly DEFAULT_OS=$(echo "$NEWEST_GCC_CUDA_ENTRY" | jq -r '.os') +readonly DEFAULT_NAME=$(make_name "$DEFAULT_CUDA" "$DEFAULT_COMPILER_NAME" "$DEFAULT_COMPILER_VERSION") + +update_devcontainer ${base_devcontainer_file} "./temp_devcontainer.json" "$DEFAULT_NAME" "$DEFAULT_CUDA" "$DEFAULT_COMPILER_NAME" "$DEFAULT_COMPILER_VERSION" "$DEFAULT_OS" "$DEVCONTAINER_VERSION" +mv "./temp_devcontainer.json" ${base_devcontainer_file} + +# Create an array to keep track of valid subdirectory names +valid_subdirs=() # For each unique combination for combination in $combinations; do @@ -46,15 +125,23 @@ for combination in $combinations; do compiler_version=$(echo "$combination" | jq -r '.compiler_version') os=$(echo "$combination" | jq -r '.os') - name="cuda$cuda_version-$compiler_name$compiler_version" + name=$(make_name "$cuda_version" "$compiler_name" "$compiler_version") mkdir -p "$name" - devcontainer_file="$name/devcontainer.json" - image="$IMAGE_ROOT$compiler_name$compiler_version-cuda$cuda_version-$os" + new_devcontainer_file="$name/devcontainer.json" + + update_devcontainer "$base_devcontainer_file" "$new_devcontainer_file" "$name" "$cuda_version" "$compiler_name" "$compiler_version" "$os" "$DEVCONTAINER_VERSION" + echo "Created $new_devcontainer_file" - # Use the base_devcontainer.json as a template, plug in the CUDA, compiler names, versions, and Ubuntu version, - # and write the output to the new devcontainer.json file - #jq --arg image "$image" --arg name "$name" '. + {image: $image, name: $name}' $base_devcontainer_file > "$devcontainer_file" - jq --arg image "$image" --arg name "$name" '.image = $image | .name = $name | .containerEnv.DEVCONTAINER_NAME = $name' $base_devcontainer_file > "$devcontainer_file" + # Add the subdirectory name to the valid_subdirs array + valid_subdirs+=("$name") +done - echo "Created $devcontainer_file" -done \ No newline at end of file +# Clean up stale subdirectories and devcontainer.json files +if [ "$CLEAN" = true ]; then + for subdir in ./*; do + if [ -d "$subdir" ] && [[ ! " ${valid_subdirs[@]} " =~ " ${subdir#./} " ]]; then + echo "Removing stale subdirectory: $subdir" + rm -r "$subdir" + fi + done +fi \ No newline at end of file diff --git a/.devcontainer/verify_devcontainer.sh b/.devcontainer/verify_devcontainer.sh new file mode 100644 index 000000000..439be1b5a --- /dev/null +++ b/.devcontainer/verify_devcontainer.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +function usage { + echo "Usage: $0" + echo + echo "This script is intended to be run within one of CUCO's Dev Containers." + echo "It verifies that the expected environment variables and binary versions match what is expected." +} + +check_envvars() { + for var_name in "$@"; do + if [[ -z "${!var_name:-}" ]]; then + echo "::error:: ${var_name} variable is not set." + exit 1 + else + echo "$var_name=${!var_name}" + fi + done +} + +check_host_compiler_version() { + local version_output=$($CXX --version) + + if [[ "$CXX" == "g++" ]]; then + local actual_version=$(echo "$version_output" | head -n 1 | cut -d ' ' -f 4 | cut -d '.' -f 1) + local expected_compiler="gcc" + elif [[ "$CXX" == "clang++" ]]; then + if [[ $version_output =~ clang\ version\ ([0-9]+) ]]; then + actual_version=${BASH_REMATCH[1]} + else + echo "::error:: Unable to determine clang version." + exit 1 + fi + expected_compiler="llvm" + else + echo "::error:: Unexpected CXX value ($CXX)." + exit 1 + fi + + if [[ "$expected_compiler" != "${CUCO_HOST_COMPILER}" || "$actual_version" != "$CUCO_HOST_COMPILER_VERSION" ]]; then + echo "::error:: CXX ($CXX) version ($actual_version) does not match the expected compiler (${CUCO_HOST_COMPILER}) and version (${CUCO_HOST_COMPILER_VERSION})." + exit 1 + else + echo "Detected host compiler: $CXX version $actual_version" + fi +} + +check_cuda_version() { + local cuda_version_output=$(nvcc --version) + if [[ $cuda_version_output =~ release\ ([0-9]+\.[0-9]+) ]]; then + local actual_cuda_version=${BASH_REMATCH[1]} + else + echo "::error:: Unable to determine CUDA version from nvcc." + exit 1 + fi + + if [[ "$actual_cuda_version" != "$CUCO_CUDA_VERSION" ]]; then + echo "::error:: CUDA version ($actual_cuda_version) does not match the expected CUDA version ($CUCO_CUDA_VERSION)." + exit 1 + else + echo "Detected CUDA version: $actual_cuda_version" + fi +} + +main() { + if [[ "$1" == "-h" || "$1" == "--help" ]]; then + usage + exit 0 + fi + + set -euo pipefail + + check_envvars DEVCONTAINER_NAME CXX CUCO_HOST_COMPILER CUCO_CUDA_VERSION CUCO_HOST_COMPILER_VERSION + + check_host_compiler_version + + check_cuda_version + + echo "Dev Container successfully verified!" +} + +main "$@" \ No newline at end of file diff --git a/.github/actions/compute-matrix/compute-matrix.sh b/.github/actions/compute-matrix/compute-matrix.sh index 64a6f5642..db79721d1 100755 --- a/.github/actions/compute-matrix/compute-matrix.sh +++ b/.github/actions/compute-matrix/compute-matrix.sh @@ -16,22 +16,47 @@ set -euo pipefail -# Check for the correct number of arguments -if [ $# -ne 2 ]; then - echo "Usage: $0 MATRIX_FILE MATRIX_QUERY" - echo "MATRIX_FILE: The path to the matrix file." - echo "MATRIX_QUERY: The jq query used to specify the desired matrix. e.g., '.pull-request.nvcc'" +write_output() { + local key="$1" + local value="$2" + echo "$key=$value" | tee --append "${GITHUB_OUTPUT:-/dev/null}" +} + +explode_std_versions() { + jq -cr 'map(. as $o | {std: $o.std[]} + del($o.std))' +} + +extract_matrix() { + local file="$1" + local type="$2" + local matrix=$(yq -o=json "$file" | jq -cr ".$type") + write_output "DEVCONTAINER_VERSION" "$(yq -o json "$file" | jq -cr '.devcontainer_version')" + local nvcc_full_matrix="$(echo "$matrix" | jq -cr '.nvcc' | explode_std_versions )" + write_output "NVCC_FULL_MATRIX" "$nvcc_full_matrix" + write_output "CUDA_VERSIONS" "$(echo "$nvcc_full_matrix" | jq -cr '[.[] | .cuda] | unique')" + write_output "HOST_COMPILERS" "$(echo "$nvcc_full_matrix" | jq -cr '[.[] | .compiler.name] | unique')" + write_output "PER_CUDA_COMPILER_MATRIX" "$(echo "$nvcc_full_matrix" | jq -cr ' group_by(.cuda + .compiler.name) | map({(.[0].cuda + "-" + .[0].compiler.name): .}) | add')" +} + +main() { + if [ "$1" == "-v" ]; then + set -x + shift + fi + + if [ $# -ne 2 ] || [ "$2" != "pull_request" ]; then + echo "Usage: $0 [-v] MATRIX_FILE MATRIX_TYPE" + echo " -v : Enable verbose output" + echo " MATRIX_FILE : The path to the matrix file." + echo " MATRIX_TYPE : The desired matrix. Supported values: 'pull_request'" exit 1 -fi + fi -# Get realpath before changing directory -MATRIX_FILE=$(realpath "$1") -MATRIX_QUERY="$2" + echo "Input matrix file:" >&2 + cat "$1" >&2 + echo "Matrix Type: $2" >&2 -# Ensure the script is being executed in its containing directory -cd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"; + extract_matrix "$1" "$2" +} -echo "Input matrix file:" >&2 -cat "$MATRIX_FILE" >&2 -echo "Query: $MATRIX_QUERY" >&2 -echo $(yq -o=json "$MATRIX_FILE" | jq -c -r "$MATRIX_QUERY | map(. as \$o | {std: .std[]} + del(\$o.std))") \ No newline at end of file +main "$@" \ No newline at end of file diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 6599e9dcb..046cb9cfa 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -22,65 +22,33 @@ defaults: on: workflow_call: inputs: - devcontainer_version: {type: string, required: true} - cuda_version: {type: string, required: true} - compiler: {type: string, required: true} - compiler_exe: {type: string, required: true} - compiler_version: {type: string, required: true} - std: {type: string, required: true} - gpu_build_archs: {type: string, required: true} cpu: {type: string, required: true} - os: {type: string, required: true} + test_name: {type: string, required: false} build_script: {type: string, required: false} test_script: {type: string, required: false} + container_image: {type: string, required: false} run_tests: {type: boolean, required: false, default: true} jobs: - devcontainer_image: - name: Devcontainer ${{ inputs.os }}/${{ inputs.compiler }}${{ inputs.compiler_version }} - runs-on: ubuntu-latest - outputs: - image_name: ${{ steps.compute-devcontainer-image-name.outputs.name }} - steps: - - name: Compute devcontainer image name - id: compute-devcontainer-image-name - run: | - COMPILER_SEGMENT="" - if [ "${{ inputs.compiler }}" != "cc" ] && [ "${{ inputs.compiler_exe }}" != "c++" ]; then - COMPILER_SEGMENT="${{ inputs.compiler }}${{ inputs.compiler_version }}-" - fi - DEVCONTAINER_IMAGE="rapidsai/devcontainers:${{inputs.devcontainer_version}}-cpp-${COMPILER_SEGMENT}cuda${{inputs.cuda_version}}-${{inputs.os}}" - echo "DEVCONTAINER_IMAGE=$DEVCONTAINER_IMAGE" >> $GITHUB_ENV - echo "name=$DEVCONTAINER_IMAGE" >> $GITHUB_OUTPUT - - name: Check if devcontainer image exists - run: | - docker buildx imagetools inspect $DEVCONTAINER_IMAGE > /dev/null - if [ $? -ne 0 ]; then - echo "Error: Docker image $DEVCONTAINER_IMAGE does not exist." - exit 1 - fi - build: - needs: devcontainer_image - if: inputs.build_script != '' && needs.devcontainer_image.outputs.image_name != '' - name: Build ${{inputs.compiler}}${{inputs.compiler_version}}/C++${{inputs.std}}/SM${{inputs.gpu_build_archs}} + name: Build ${{inputs.test_name}} uses: ./.github/workflows/run-as-coder.yml with: - name: Build ${{inputs.compiler}}${{inputs.compiler_version}}/C++${{inputs.std}}/SM${{inputs.gpu_build_archs}} + name: Build ${{inputs.test_name}} runner: linux-${{inputs.cpu}}-cpu16 - image: ${{ needs.devcontainer_image.outputs.image_name }} + image: ${{ inputs.container_image }} command: | - ${{ inputs.build_script }} "${{inputs.compiler_exe}}" "${{inputs.std}}" "${{inputs.gpu_build_archs}}" + ${{ inputs.build_script }} test: - needs: [devcontainer_image, build] - if: ${{ !cancelled() && ( needs.build.result == 'success' || needs.build.result == 'skipped' ) && inputs.test_script != '' && needs.devcontainer_image.outputs.image_name != '' && inputs.run_tests}} - name: Test ${{inputs.compiler}}${{inputs.compiler_version}}/C++${{inputs.std}}/SM${{inputs.gpu_build_archs}} + needs: build + if: ${{ !cancelled() && ( needs.build.result == 'success' || needs.build.result == 'skipped' ) && inputs.run_tests}} + name: Test ${{inputs.test_name}} uses: ./.github/workflows/run-as-coder.yml with: - name: Test ${{inputs.compiler}}${{inputs.compiler_version}}/C++${{inputs.std}}/SM${{inputs.gpu_build_archs}} + name: Test ${{inputs.test_name}} runner: linux-${{inputs.cpu}}-gpu-v100-latest-1 - image: ${{ needs.devcontainer_image.outputs.image_name }} + image: ${{inputs.container_image}} command: | nvidia-smi - ${{ inputs.test_script }} "${{inputs.compiler_exe}}" "${{inputs.std}}" "${{inputs.gpu_build_archs}}" \ No newline at end of file + ${{ inputs.test_script }} \ No newline at end of file diff --git a/.github/workflows/dispatch-build-and-test.yml b/.github/workflows/dispatch-build-and-test.yml index dea71e00e..9f2e083ed 100644 --- a/.github/workflows/dispatch-build-and-test.yml +++ b/.github/workflows/dispatch-build-and-test.yml @@ -19,8 +19,6 @@ on: workflow_call: inputs: per_cuda_compiler_matrix: {type: string, required: true} - build_script: {type: string, required: false} - test_script: {type: string, required: false} devcontainer_version: {type: string, required: true} jobs: @@ -35,15 +33,9 @@ jobs: matrix: include: ${{ fromJSON(inputs.per_cuda_compiler_matrix) }} with: - devcontainer_version: ${{ inputs.devcontainer_version }} - cuda_version: ${{ matrix.cuda }} - compiler: ${{ matrix.compiler.name }} - compiler_exe: ${{ matrix.compiler.exe }} - compiler_version: ${{ matrix.compiler.version }} - std: ${{ matrix.std }} - gpu_build_archs: ${{ matrix.gpu_build_archs }} cpu: ${{ matrix.cpu }} - os: ${{ matrix.os }} - build_script: ${{ inputs.build_script }} - test_script: ${{ inputs.test_script }} + test_name: ${{matrix.compiler.name}}${{matrix.compiler.version}}/C++${{matrix.std}} + build_script: "./ci/build.sh ${{matrix.compiler.exe}} ${{matrix.std}} ${{matrix.gpu_build_archs}}" + test_script: "./ci/test.sh ${{matrix.compiler.exe}} ${{matrix.std}} ${{matrix.gpu_build_archs}}" + container_image: rapidsai/devcontainers:${{inputs.devcontainer_version}}-cpp-${{matrix.compiler.name}}${{matrix.compiler.version}}-cuda${{matrix.cuda}}-${{matrix.os}} run_tests: ${{ contains(matrix.jobs, 'test') && !contains(github.event.head_commit.message, 'skip-tests') }} diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 061b30a99..25b7ee69e 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -23,8 +23,6 @@ defaults: on: push: branches: - - main - - dev - "pull-request/[0-9]+" # Only runs one instance of this workflow at a time for a given PR and cancels any in-progress runs when a new one starts. @@ -52,52 +50,26 @@ jobs: fi shell: bash -euxo pipefail {0} - get-devcontainer-version: - name: Get devcontainer version + compute-matrix: + name: Compute matrix runs-on: ubuntu-latest outputs: - DEVCONTAINER_VERSION: ${{ steps.set-outputs.outputs.DEVCONTAINER_VERSION }} + DEVCONTAINER_VERSION: ${{steps.set-outputs.outputs.DEVCONTAINER_VERSION}} + NVCC_FULL_MATRIX: ${{steps.set-outputs.outputs.NVCC_FULL_MATRIX}} + CUDA_VERSIONS: ${{steps.set-outputs.outputs.CUDA_VERSIONS}} + HOST_COMPILERS: ${{steps.set-outputs.outputs.HOST_COMPILERS}} + PER_CUDA_COMPILER_MATRIX: ${{steps.set-outputs.outputs.PER_CUDA_COMPILER_MATRIX}} steps: - name: Checkout repo uses: actions/checkout@v3 - - name: Get devcontainer version + - name: Compute matrix outputs id: set-outputs run: | - DEVCONTAINER_VERSION=$(yq -o json ci/matrix.yml | jq -r '.devcontainer_version') - echo "DEVCONTAINER_VERSION=$DEVCONTAINER_VERSION" | tee -a "$GITHUB_OUTPUT" - - compute-nvcc-matrix: - name: Compute NVCC matrix - runs-on: ubuntu-latest - outputs: - FULL_MATRIX: ${{ steps.set-outputs.outputs.FULL_MATRIX }} - CUDA_VERSIONS: ${{ steps.set-outputs.outputs.CUDA_VERSIONS }} - HOST_COMPILERS: ${{ steps.set-outputs.outputs.HOST_COMPILERS }} - PER_CUDA_COMPILER_MATRIX: ${{ steps.set-outputs.outputs.PER_CUDA_COMPILER_MATRIX }} - steps: - - name: Checkout repo - uses: actions/checkout@v3 - - name: Get full nvcc matrix - id: compute-nvcc-matrix - uses: ./.github/actions/compute-matrix - with: - matrix_file: './ci/matrix.yml' - matrix_query: '.pull_request.nvcc' - - name: Set outputs - id: set-outputs - run: | - FULL_MATRIX='${{steps.compute-nvcc-matrix.outputs.matrix}}' - echo "FULL_MATRIX=$FULL_MATRIX" | tee -a "$GITHUB_OUTPUT" - CUDA_VERSIONS=$(echo $FULL_MATRIX | jq -c '[.[] | .cuda] | unique') - echo "CUDA_VERSIONS=$CUDA_VERSIONS" | tee -a "$GITHUB_OUTPUT" - HOST_COMPILERS=$(echo $FULL_MATRIX | jq -c '[.[] | .compiler.name] | unique') - echo "HOST_COMPILERS=$HOST_COMPILERS" | tee -a "$GITHUB_OUTPUT" - PER_CUDA_COMPILER_MATRIX=$(echo $FULL_MATRIX | jq -c ' group_by(.cuda + .compiler.name) | map({(.[0].cuda + "-" + .[0].compiler.name): .}) | add') - echo "PER_CUDA_COMPILER_MATRIX=$PER_CUDA_COMPILER_MATRIX" | tee -a "$GITHUB_OUTPUT" + .github/actions/compute-matrix/compute-matrix.sh ci/matrix.yml pull_request ci: name: CUDA${{ matrix.cuda_version }} ${{ matrix.compiler }} - needs: [compute-nvcc-matrix, get-devcontainer-version] + needs: compute-matrix uses: ./.github/workflows/dispatch-build-and-test.yml strategy: fail-fast: false @@ -106,10 +78,12 @@ jobs: compiler: ${{ fromJSON(needs.compute-nvcc-matrix.outputs.HOST_COMPILERS) }} with: per_cuda_compiler_matrix: ${{ toJSON(fromJSON(needs.compute-nvcc-matrix.outputs.PER_CUDA_COMPILER_MATRIX)[ format('{0}-{1}', matrix.cuda_version, matrix.compiler) ]) }} - build_script: "./ci/build.sh" - test_script: "./ci/test.sh" devcontainer_version: ${{ needs.get-devcontainer-version.outputs.DEVCONTAINER_VERSION }} + verify-devcontainers: + name: Verify Dev Containers + uses: ./.github/workflows/verify-devcontainers.yml + # This job is the final job that runs after all other jobs and is used for branch protection status checks. # See: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/about-status-checks ci-success: @@ -117,5 +91,6 @@ jobs: name: CI success needs: - ci + - verify-devcontainers steps: - run: echo "CI success" \ No newline at end of file diff --git a/.github/workflows/verify-devcontainers.yml b/.github/workflows/verify-devcontainers.yml new file mode 100644 index 000000000..913f8e945 --- /dev/null +++ b/.github/workflows/verify-devcontainers.yml @@ -0,0 +1,88 @@ +name: Verify devcontainers + +on: + workflow_call: + +defaults: + run: + shell: bash -euo pipefail {0} + +jobs: + verify-make-devcontainers: + name: Verify devcontainers + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Setup jq and yq + run: | + sudo apt-get update + sudo apt-get install jq -y + sudo wget -O /usr/local/bin/yq https://github.com/mikefarah/yq/releases/download/v4.34.2/yq_linux_amd64 + sudo chmod +x /usr/local/bin/yq + - name: Run the script to generate devcontainer files + run: | + ./.devcontainer/make_devcontainers.sh --verbose + - name: Check for changes + run: | + if [[ $(git diff --stat) != '' ]]; then + git diff --minimal + echo "::error:: Dev Container files are out of date. Run the .devcontainer/make_devcontainers.sh script and commit the changes." + exit 1 + else + echo "::note::Dev Container files are up-to-date." + fi + get-devcontainer-list: + needs: verify-make-devcontainers + name: Get list of devcontainer.json files + runs-on: ubuntu-latest + outputs: + devcontainers: ${{ steps.get-list.outputs.devcontainers }} + steps: + - name: Check out the code + uses: actions/checkout@v3 + - name: Get list of devcontainer.json paths and names + id: get-list + run: | + devcontainers=$(find .devcontainer/ -name 'devcontainer.json' | while read -r devcontainer; do + jq --arg path "$devcontainer" '{path: $path, name: .name}' "$devcontainer" + done | jq -s -c .) + echo "devcontainers=${devcontainers}" | tee --append "${GITHUB_OUTPUT}" + verify-devcontainers: + needs: get-devcontainer-list + name: ${{matrix.devcontainer.name}} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + devcontainer: ${{fromJson(needs.get-devcontainer-list.outputs.devcontainers)}} + permissions: + id-token: write + contents: read + steps: + - name: Check out the code + uses: actions/checkout@v3 + # devcontainer/ci doesn't supported nested devcontainer.json files, so we need to copy the devcontainer.json + # file to the top level .devcontainer/ directory + - name: Copy devcontainer.json to .devcontainer/ + run: | + src="${{ matrix.devcontainer.path }}" + dst=".devcontainer/devcontainer.json" + if [[ "$src" != "$dst" ]]; then + cp "$src" "$dst" + fi + # We don't really need sccache configured, but we need the AWS credentials envvars to be set + # in order to avoid the devcontainer hanging waiting for GitHub authentication + - name: Configure credentials and environment variables for sccache + uses: ./.github/actions/configure_cccl_sccache + - name: Run in devcontainer + uses: devcontainers/ci@v0.3 + with: + push: never + env: | + SCCACHE_REGION=${{ env.SCCACHE_REGION }} + 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 }} + runCmd: | + .devcontainer/verify_devcontainer.sh \ No newline at end of file diff --git a/ci/matrix.yml b/ci/matrix.yml index 5916dd113..fde7f09fe 100644 --- a/ci/matrix.yml +++ b/ci/matrix.yml @@ -19,10 +19,11 @@ cuda_newest: &cuda_newest '12.2' # The GPUs to test on # Note: This assumes that the appropriate gpu_build_archs are set to include building for the GPUs listed here gpus: + - 'a100' - 'v100' # The version of the devcontainer images to use from https://hub.docker.com/r/rapidsai/devcontainers -devcontainer_version: '23.08' +devcontainer_version: '23.10' # Each environment below will generate a unique build/test job # See the "compute-matrix" job in the workflow for how this is parsed and used