From 8256d08a33b47347cf26ece9119a1a336e105770 Mon Sep 17 00:00:00 2001 From: Allison Piper Date: Fri, 31 May 2024 18:08:16 +0000 Subject: [PATCH] WIP Split workflow into multiple dispatch groups to avoid skipped jobs. --- .github/actions/workflow-build/action.yml | 25 +++-- .../prepare-workflow-dispatch.py | 95 ++++++++++++++++ .../actions/workflow-run-job-linux/action.yml | 104 ++++++++++++++++++ .../workflow-run-job-windows/action.yml | 84 ++++++++++++++ .../workflows/ci-workflow-pull-request.yml | 26 ++--- .../workflow-dispatch-job-array-linux.yml | 51 +++++++++ .../workflow-dispatch-job-single-linux.yml | 49 +++++++++ ...orkflow-dispatch-two-stage-group-linux.yml | 33 ++++++ .../workflow-dispatch-two-stage-linux.yml | 70 ++++++++++++ .../workflow-dispatch-two-stage-windows.yml | 0 .../workflows/workflow-dispatch-two-stage.yml | 31 ++---- .github/workflows/workflow-dispatch.yml | 48 ++------ ci/matrix.yaml | 1 + 13 files changed, 531 insertions(+), 86 deletions(-) create mode 100755 .github/actions/workflow-build/prepare-workflow-dispatch.py create mode 100644 .github/actions/workflow-run-job-linux/action.yml create mode 100644 .github/actions/workflow-run-job-windows/action.yml create mode 100644 .github/workflows/workflow-dispatch-job-array-linux.yml create mode 100644 .github/workflows/workflow-dispatch-job-single-linux.yml create mode 100644 .github/workflows/workflow-dispatch-two-stage-group-linux.yml create mode 100644 .github/workflows/workflow-dispatch-two-stage-linux.yml create mode 100644 .github/workflows/workflow-dispatch-two-stage-windows.yml diff --git a/.github/actions/workflow-build/action.yml b/.github/actions/workflow-build/action.yml index 3bfaceae3b5..f4bcc1d22ec 100644 --- a/.github/actions/workflow-build/action.yml +++ b/.github/actions/workflow-build/action.yml @@ -32,11 +32,8 @@ inputs: outputs: workflow: - description: "The dispatchable workflow matrix" - value: ${{ steps.build-workflow.outputs.workflow }} - workflow_keys: - description: "The keys of the parsed workflow" - value: ${{ steps.build-workflow.outputs.workflow_keys }} + description: "The dispatchable workflows" + value: ${{ steps.build-workflow.outputs.DISPATCH_WORKFLOWS }} runs: using: "composite" @@ -85,13 +82,21 @@ runs: cat workflow/job_list.txt echo "::endgroup::" - echo "Setting outputs..." - echo "::group::GHA Output: WORKFLOW" - printf "WORKFLOW=%s\n" "$(cat workflow/workflow.json | jq -c '.')" | tee -a "${GITHUB_OUTPUT}" + - name: Create dispatch workflows + shell: bash --noprofile --norc -euo pipefail {0} + run: | + '${GITHUB_ACTION_PATH}/prepare-workflow-dispatch.py' workflow/workflow.json + + echo "::group::Dispatch Workflows" + cat dispatch/dispatch.json echo "::endgroup::" - echo "::group::GHA Output: WORKFLOW_KEYS" - printf "WORKFLOW_KEYS=%s\n" "$(cat workflow/workflow_keys.json | jq -c '.')" | tee -a "${GITHUB_OUTPUT}" + - name: Set outputs + id: outputs + shell: bash --noprofile --norc -euo pipefail {0} + run: | + echo "::group::GHA Output: DISPATCH_WORKFLOWS" + printf "DISPATCH_WORKFLOWS=%s\n" "$(cat workflow/workflow.json | jq -c '.')" | tee -a "${GITHUB_OUTPUT}" echo "::endgroup::" - name: Upload artifacts diff --git a/.github/actions/workflow-build/prepare-workflow-dispatch.py b/.github/actions/workflow-build/prepare-workflow-dispatch.py new file mode 100755 index 00000000000..cf18ac0c657 --- /dev/null +++ b/.github/actions/workflow-build/prepare-workflow-dispatch.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 + +""" +This script prepares a full workflow for GHA dispatch. + +To avoid skipped jobs from cluttering the GHA UI, this script splits the full workflow.json into multiple workflows +that don't require large numbers of skipped jobs in the workflow implementation. +""" + +import argparse +import json +import os +import sys + + +def write_json_file(filename, json_object): + with open(filename, 'w') as f: + json.dump(json_object, f, indent=2) + + +def is_windows(job): + return job['runner'].startswith('windows') + + +def split_workflow(workflow): + linux_standalone = {} + linux_two_stage = {} + windows_standalone = {} + windows_two_stage = {} + + def strip_extra_info(job): + del job['origin'] + + for group_name, group_json in workflow.items(): + standalone = group_json['standalone'] if 'standalone' in group_json else [] + two_stage = group_json['two_stage'] if 'two_stage' in group_json else [] + + if len(standalone) > 0: + for job in standalone: + strip_extra_info(job) + + if is_windows(standalone[0]): + windows_standalone[group_name] = standalone + else: + linux_standalone[group_name] = standalone + + if len(two_stage) > 0: + for ts in two_stage: + for job in ts['producers']: + strip_extra_info(job) + for job in ts['consumers']: + strip_extra_info(job) + + if is_windows(two_stage[0]['producers'][0]): + windows_two_stage[group_name] = two_stage + else: + linux_two_stage[group_name] = two_stage + + dispatch = { + 'linux_standalone': { + 'keys': list(linux_standalone.keys()), + 'jobs': linux_standalone}, + 'linux_two_stage': { + 'keys': list(linux_two_stage.keys()), + 'jobs': linux_two_stage}, + 'windows_standalone': { + 'keys': list(windows_standalone.keys()), + 'jobs': windows_standalone}, + 'windows_two_stage': { + 'keys': list(windows_two_stage.keys()), + 'jobs': windows_two_stage} + } + + os.makedirs('dispatch', exist_ok=True) + write_json_file('dispatch/dispatch.json', dispatch) + + +def main(): + parser = argparse.ArgumentParser(description='Prepare a full workflow for GHA dispatch.') + parser.add_argument('workflow_json', help='Path to the full workflow.json file') + args = parser.parse_args() + + # Check if the workflow file exists + if not os.path.isfile(args.workflow_json): + print(f"Error: Matrix file '{args.workflow_json}' not found.") + sys.exit(1) + + with open(args.workflow_json) as f: + workflow = json.load(f) + + split_workflow(workflow) + + +if __name__ == '__main__': + main() diff --git a/.github/actions/workflow-run-job-linux/action.yml b/.github/actions/workflow-run-job-linux/action.yml new file mode 100644 index 00000000000..91b67b3ff6e --- /dev/null +++ b/.github/actions/workflow-run-job-linux/action.yml @@ -0,0 +1,104 @@ +name: "Run Linux Job" +description: "Run a job on a Linux runner." + +inputs: + id: + description: "A unique identifier." + required: true + command: + description: "The command to run." + required: true + image: + description: "The Docker image to use." + required: true + +runs: + using: "composite" + steps: + - name: Checkout repo + uses: actions/checkout@v3 + with: + path: ${{github.event.repository.name}} + persist-credentials: false + - name: Link files to coder user home directory + shell: bash --noprofile --norc -euo pipefail {0} + run: | + ln -s "$(pwd)/${{github.event.repository.name}}" /home/coder/${{github.event.repository.name}} + chown -R coder:coder ${{github.event.repository.name}} + chown -R coder:coder /home/coder/${{github.event.repository.name}} + - name: Add NVCC problem matcher + shell: bash --noprofile --norc -euo pipefail {0} + run: | + echo "::add-matcher::${{github.event.repository.name}}/.github/problem-matchers/problem-matcher.json" + - name: Get AWS credentials for sccache bucket + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: arn:aws:iam::279114543810:role/gha-oidc-NVIDIA + aws-region: us-east-2 + role-duration-seconds: 43200 # 12 hours) + - name: Set environment variables + shell: bash --noprofile --norc -euo pipefail {0} + run: | + echo "SCCACHE_BUCKET=rapids-sccache-devs" >> $GITHUB_ENV + echo "SCCACHE_REGION=us-east-2" >> $GITHUB_ENV + echo "SCCACHE_IDLE_TIMEOUT=32768" >> $GITHUB_ENV + echo "SCCACHE_S3_USE_SSL=true" >> $GITHUB_ENV + echo "SCCACHE_S3_NO_CREDENTIALS=false" >> $GITHUB_ENV + - name: Run command # Do not change this step's name, it is checked in parse-job-times.py + shell: su coder {0} + env: + # Dereferencing the command from and env var instead of a GHA input avoids issues with escaping + # semicolons and other special characters (e.g. `-arch "60;70;80"`). + COMMAND: ${{inputs.command}} + run: | + set -eo pipefail + cd ~/${{github.event.repository.name}} + echo -e "\e[1;34mRunning as 'coder' user in $(pwd):\e[0m" + echo -e "\e[1;34m${COMMAND}\e[0m" + eval "${COMMAND}" || exit_code=$? + if [ ! -z "$exit_code" ]; then + echo -e "::group::️❗ \e[1;31mInstructions to Reproduce CI Failure Locally\e[0m" + echo "::error:: To replicate this failure locally, follow the steps below:" + echo "1. Clone the repository, and navigate to the correct branch and commit:" + echo " git clone --branch $GITHUB_REF_NAME --single-branch https://github.com/$GITHUB_REPOSITORY.git && cd $(echo $GITHUB_REPOSITORY | cut -d'/' -f2) && git checkout $GITHUB_SHA" + echo "" + echo "2. Run the failed command inside the same Docker container used by the CI:" + echo " docker run --rm -it --gpus all --pull=always --volume \$PWD:/repo --workdir /repo ${{ inputs.image }} ${COMMAND}" + echo "" + echo "For additional information, see:" + echo " - DevContainer Documentation: https://github.com/NVIDIA/cccl/blob/main/.devcontainer/README.md" + echo " - Continuous Integration (CI) Overview: https://github.com/NVIDIA/cccl/blob/main/ci-overview.md" + exit $exit_code + fi + - name: Prepare job artifacts + id: done + shell: bash --noprofile --norc -euo pipefail {0} + run: | + echo "SUCCESS=true" | tee -a "${GITHUB_OUTPUT}" + result_dir="jobs/${{inputs.id}}" + mkdir -p "$result_dir" + + touch "$result_dir/success" + + # Finds a matching file in the repo directory and copies it to the results directory. + find_and_copy() { + filename="$1" + filepath="$(find ${{github.event.repository.name}} -name "${filename}" -print -quit)" + if [[ -z "$filepath" ]]; then + echo "${filename} does not exist in repo directory." + return 1 + fi + cp -v "$filepath" "$result_dir" + } + + find_and_copy "sccache_stats.json" || true # Ignore failures + + echo "::group::Job artifacts" + tree "$result_dir" + echo "::endgroup::" + + - name: Upload job artifacts + uses: actions/upload-artifact@v3 + with: + name: jobs + path: jobs diff --git a/.github/actions/workflow-run-job-windows/action.yml b/.github/actions/workflow-run-job-windows/action.yml new file mode 100644 index 00000000000..b3636c1396d --- /dev/null +++ b/.github/actions/workflow-run-job-windows/action.yml @@ -0,0 +1,84 @@ +name: "Run Linux Job" +description: "Run a job on a Linux runner." + +inputs: + image: { type: string, required: true } + command: { type: string, required: true } + id: { type: string, required: true } + +runs: + using: "composite" + steps: + - name: Get AWS credentials for sccache bucket + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: arn:aws:iam::279114543810:role/gha-oidc-NVIDIA + aws-region: us-east-2 + role-duration-seconds: 43200 # 12 hours + - name: Checkout repo + uses: actions/checkout@v3 + with: + path: ${{github.event.repository.name}} + persist-credentials: false + - name: Fetch ${{ inputs.image }} + shell: bash --noprofile --norc -euo pipefail {0} + run: docker pull ${{ inputs.image }} + - name: Prepare paths for docker + id: paths + shell: bash --noprofile --norc -euo pipefail {0} + run: | + echo "HOST_REPO=${{ github.workspace }}\${{ github.event.repository.name }}".Replace('\', '/') | Out-File -FilePath $env:GITHUB_OUTPUT -Append + echo "MOUNT_REPO=C:/${{ github.event.repository.name }}" | Out-File -FilePath $env:GITHUB_OUTPUT -Append + cat $env:GITHUB_OUTPUT + shell: powershell + - name: Run command # Do not change this step's name, it is checked in parse-job-times.py + shell: bash --noprofile --norc -euo pipefail {0} + run: | + docker run \ + --mount type=bind,source="${{steps.paths.outputs.HOST_REPO}}",target="${{steps.paths.outputs.MOUNT_REPO}}" \ + --workdir "${{steps.paths.outputs.MOUNT_REPO}}" \ + ${{ inputs.image }} \ + powershell -c " + [System.Environment]::SetEnvironmentVariable('AWS_ACCESS_KEY_ID','${{env.AWS_ACCESS_KEY_ID}}'); + [System.Environment]::SetEnvironmentVariable('AWS_SECRET_ACCESS_KEY','${{env.AWS_SECRET_ACCESS_KEY}}'); + [System.Environment]::SetEnvironmentVariable('AWS_SESSION_TOKEN','${{env.AWS_SESSION_TOKEN }}'); + [System.Environment]::SetEnvironmentVariable('SCCACHE_BUCKET','${{env.SCCACHE_BUCKET}}'); + [System.Environment]::SetEnvironmentVariable('SCCACHE_REGION','${{env.SCCACHE_REGION}}'); + [System.Environment]::SetEnvironmentVariable('SCCACHE_IDLE_TIMEOUT','${{env.SCCACHE_IDLE_TIMEOUT}}'); + [System.Environment]::SetEnvironmentVariable('SCCACHE_S3_USE_SSL','${{env.SCCACHE_S3_USE_SSL}}'); + [System.Environment]::SetEnvironmentVariable('SCCACHE_S3_NO_CREDENTIALS','${{env.SCCACHE_S3_NO_CREDENTIALS}}'); + git config --global --add safe.directory '${{steps.paths.outputs.MOUNT_REPO}}'; + ${{inputs.command}}" + - name: Prepare job artifacts + id: done + shell: bash --noprofile --norc -euo pipefail {0} + run: | + echo "SUCCESS=true" | tee -a "${GITHUB_OUTPUT}" + + result_dir="jobs/${{inputs.id}}" + mkdir -p "$result_dir" + + touch "$result_dir/success" + + # Finds a matching file in the repo directory and copies it to the results directory. + find_and_copy() { + filename="$1" + filepath="$(find ${{github.event.repository.name}} -name "${filename}" -print -quit)" + if [[ -z "$filepath" ]]; then + echo "${filename} does not exist in repo directory." + return 1 + fi + cp -v "$filepath" "$result_dir" + } + + find_and_copy "sccache_stats.json" || true # Ignore failures + + echo "::group::Job artifacts" + find "$result_dir" # Tree not available in this image. + echo "::endgroup::" + + - name: Upload job artifacts + uses: actions/upload-artifact@v3 + with: + name: jobs + path: jobs diff --git a/.github/workflows/ci-workflow-pull-request.yml b/.github/workflows/ci-workflow-pull-request.yml index baa1fceafe8..b07a6f7f3d6 100644 --- a/.github/workflows/ci-workflow-pull-request.yml +++ b/.github/workflows/ci-workflow-pull-request.yml @@ -39,7 +39,6 @@ jobs: pull-requests: read outputs: workflow: ${{ steps.build-workflow.outputs.workflow }} - workflow_keys: ${{ steps.build-workflow.outputs.workflow_keys }} steps: - name: Checkout repo uses: actions/checkout@v3 @@ -62,22 +61,15 @@ jobs: ${{ env.nightly_workflow }} run-workflow: - name: ${{ matrix.name }} + name: Run workflow needs: build-workflow permissions: id-token: write contents: read - strategy: - fail-fast: false - matrix: - name: ${{ fromJSON(needs.build-workflow.outputs.workflow_keys) }} uses: ./.github/workflows/workflow-dispatch.yml with: - name: ${{ matrix.name }} - jobs: ${{ toJSON(fromJSON(needs.build-workflow.outputs.workflow)[matrix.name]) }} + workflow: ${{ needs.build-workflow.outputs.workflow }} - # This job acts as a sentry and will fail if any leaf job in the workflow tree fails, as - # run-workflow always succeeds. Use this job when checking for successful matrix workflow job completion. verify-workflow: name: Verify and summarize workflow results if: ${{ always() && !cancelled() }} @@ -103,12 +95,12 @@ jobs: github_token: ${{ secrets.GITHUB_TOKEN }} pr_number: ${{ fromJSON(steps.get-pr-info.outputs.pr-info).number }} - verify-devcontainers: - name: Verify Dev Containers - permissions: - id-token: write - contents: read - uses: ./.github/workflows/verify-devcontainers.yml +# verify-devcontainers: +# name: Verify Dev Containers +# permissions: +# id-token: write +# contents: read +# uses: ./.github/workflows/verify-devcontainers.yml # Check all other job statuses. This job gates branch protection checks. ci: @@ -120,7 +112,7 @@ jobs: if: ${{ always() }} needs: - verify-workflow - - verify-devcontainers +# - verify-devcontainers runs-on: ubuntu-latest steps: - name: Check results diff --git a/.github/workflows/workflow-dispatch-job-array-linux.yml b/.github/workflows/workflow-dispatch-job-array-linux.yml new file mode 100644 index 00000000000..6851a789420 --- /dev/null +++ b/.github/workflows/workflow-dispatch-job-array-linux.yml @@ -0,0 +1,51 @@ +name: "Workflow/Dispatch/Job/Array/Linux" + +# 'job-single' and 'job-array' are split and have redundent implementations for two reasons: +# 1. GHA doesn't aggregate success results from a matrix dispatch job. +# - single-job is used when a job has dependencies, eg. producers. +# - array-job can be used for arrays of standalone and consumer jobs. +# 2. GHA limits the number of nested workflows severely. +# - Reimplementing the job logic in `job-array` instead of reusing `job-single` helps keep the +# number of nested workflows low. +# +# To reduce the amount of code duplication, the `job-single` and `job-array` workflows are implemented +# using the same action. Only the runner/container config is duplicated. + +defaults: + run: + shell: bash --noprofile --norc -euo pipefail {0} + +on: + workflow_call: + inputs: + jobs: + description: "Array of dispatch job objects as a JSON string." + type: string + required: true + +permissions: + contents: read + +jobs: + run: + name: ${{matrix.name}} + strategy: + fail-fast: false + matrix: + include: ${{fromJSON(inputs.jobs)}} + permissions: + id-token: write + contents: read + runs-on: ${{matrix.runner}} + container: + options: -u root + image: ${{matrix.image}} + env: + NVIDIA_VISIBLE_DEVICES: ${{ env.NVIDIA_VISIBLE_DEVICES }} + steps: + - name: Run job + uses: ./.github/actions/workflow-run-job-linux.yml + with: + id: ${{matrix.id}} + command: ${{matrix.command}} + image: ${{matrix.image}} diff --git a/.github/workflows/workflow-dispatch-job-single-linux.yml b/.github/workflows/workflow-dispatch-job-single-linux.yml new file mode 100644 index 00000000000..e9074de2159 --- /dev/null +++ b/.github/workflows/workflow-dispatch-job-single-linux.yml @@ -0,0 +1,49 @@ +name: "Workflow/Dispatch/Job/Single/Linux" + +# 'job-single' and 'job-array' are split and have redundent implementations for two reasons: +# 1. GHA doesn't aggregate success results from a matrix dispatch job. +# - single-job is used when a job has dependencies, eg. producers. +# - array-job can be used for arrays of standalone and consumer jobs. +# 2. GHA limits the number of nested workflows severely. +# - Reimplementing the job logic in `job-array` instead of reusing `job-single` helps keep the +# number of nested workflows low. +# +# To reduce the amount of code duplication, the `job-single` and `job-array` workflows are implemented +# using the same action. Only the runner/container config is duplicated. + +defaults: + run: + shell: bash --noprofile --norc -euo pipefail {0} + +on: + workflow_call: + inputs: + name: {type: string, required: true} + image: {type: string, required: true} + runner: {type: string, required: true} + command: {type: string, required: true} + id: {type: string, required: true} + env: {type: string, required: false} + +permissions: + contents: read + +jobs: + run: + name: ${{inputs.name}} + permissions: + id-token: write + contents: read + runs-on: ${{inputs.runner}} + container: + options: -u root + image: ${{inputs.image}} + env: + NVIDIA_VISIBLE_DEVICES: ${{ env.NVIDIA_VISIBLE_DEVICES }} + steps: + - name: Run job + uses: ./.github/actions/workflow-run-job-linux.yml + with: + id: ${{inputs.id}} + command: ${{inputs.command}} + image: ${{inputs.image}} diff --git a/.github/workflows/workflow-dispatch-two-stage-group-linux.yml b/.github/workflows/workflow-dispatch-two-stage-group-linux.yml new file mode 100644 index 00000000000..bd8258eb3b0 --- /dev/null +++ b/.github/workflows/workflow-dispatch-two-stage-group-linux.yml @@ -0,0 +1,33 @@ +name: "Workflow/Dispatch/TwoStageGroup/Linux" + +defaults: + run: + shell: bash --noprofile --norc -euo pipefail {0} + +on: + workflow_call: + inputs: + name: + description: "The dispatch.json's linux_two_stage.jobs subkey for this two-stage group." + type: string + required: true + pc-array: + description: "The dispatch.json's linux_two_stage.jobs. array of producer/consumer chains." + type: string + required: true + +jobs: + dispatch-pcs: + name: ${{ matrix.id }} + permissions: + id-token: write + contents: read + strategy: + fail-fast: false + matrix: + include: ${{ fromJSON(inputs.pc-array) }} + uses: ./.github/workflows/workflow-dispatch-two-stage-linux.yml + with: + id: ${{ matrix.id }} + producers: ${{ toJSON(matrix.producers) }} + consumers: ${{ toJSON(matrix.consumers) }} diff --git a/.github/workflows/workflow-dispatch-two-stage-linux.yml b/.github/workflows/workflow-dispatch-two-stage-linux.yml new file mode 100644 index 00000000000..b36e45c452b --- /dev/null +++ b/.github/workflows/workflow-dispatch-two-stage-linux.yml @@ -0,0 +1,70 @@ +name: "Workflow/Dispatch/TwoStage/Linux" + +defaults: + run: + shell: bash --noprofile --norc -euo pipefail {0} + +on: + workflow_call: + inputs: + producers: + description: "The dispatch.json's linux_two_stage.jobs.[*].producers array." + type: string + required: true + consumers: + description: "The dispatch.json's linux_two_stage.jobs.[*].consumers array." + type: string + required: true + id: + description: "The dispatch.json's linux_two_stage.jobs.[*].id." + type: string + required: true + +jobs: + # Accumulating results from multiple producers is not easily implemented. For now, only a single producer is supported. + # The build-workflow.py script will emit an error if more than one producer is specified. + producer: + name: ${{ fromJSON(inputs.producers)[0].name }} + permissions: + id-token: write + contents: read + runs-on: ${{ fromJSON(inputs.producers)[0].runner }} + container: + options: -u root + image: ${{inputs.image}} + env: + NVIDIA_VISIBLE_DEVICES: ${{ env.NVIDIA_VISIBLE_DEVICES }} + steps: + - name: Run job + uses: ./.github/actions/workflow-run-job-linux.yml + with: + id: ${{ fromJSON(inputs.producers)[0].id }} + command: ${{ fromJSON(inputs.producers)[0].command }} + image: ${{ fromJSON(inputs.producers)[0].image }} + + consumers: + # This is an internal dispatch job and the name is not important. + # Give the job a short and unique name, otherwise github will bloat the job name with the matrix values. + # This keeps the UI from getting cluttered. + name: "${{ matrix.id }}" + needs: producer + strategy: + fail-fast: false + matrix: + include: ${{ fromJSON(inputs.consumers) }} + permissions: + id-token: write + contents: read + runs-on: ${{ matrix.runner }} + container: + options: -u root + image: ${{matrix.image}} + env: + NVIDIA_VISIBLE_DEVICES: ${{ env.NVIDIA_VISIBLE_DEVICES }} + steps: + - name: Run job + uses: ./.github/actions/workflow-run-job-linux.yml + with: + id: ${{ matrix.id }} + command: ${{ matrix.command }} + image: ${{ matrix.image }} diff --git a/.github/workflows/workflow-dispatch-two-stage-windows.yml b/.github/workflows/workflow-dispatch-two-stage-windows.yml new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.github/workflows/workflow-dispatch-two-stage.yml b/.github/workflows/workflow-dispatch-two-stage.yml index 16dea85000f..f5289b400ec 100644 --- a/.github/workflows/workflow-dispatch-two-stage.yml +++ b/.github/workflows/workflow-dispatch-two-stage.yml @@ -14,38 +14,27 @@ permissions: contents: read jobs: - # It is impossible to accumulate output variables across a matrix, - # and we cannot rely on the results of the dispatch-job workflow to determine success. - # See the note in ci-dispatch-job.yml for more information. - # - # Since we cannot accumulate results from multiple producers, only support a single producer for now. - # This is enforced by compute-matrix.py. - producers: - # This is an internal dispatch job and the name is not important. - # Give the job a short and unique name, otherwise github will bloat the job name with the matrix values. - # This keeps the UI from getting cluttered. - name: "p.${{ matrix.id }}" + # Accumulating results from multiple producers is not easily implemented. For now, only a single producer is supported. + # The build-workflow.py script will emit an error if more than one producer is specified. + producer: + name: "p.${{ fromJSON(inputs.producers)[0].id }}" permissions: id-token: write contents: read - strategy: - fail-fast: false - matrix: - include: ${{fromJSON(inputs.producers)}} uses: ./.github/workflows/workflow-dispatch-job.yml with: - name: ${{ matrix.name }} - runner: ${{ matrix.runner }} - image: ${{ matrix.image }} - command: ${{ matrix.command }} - id: ${{ matrix.id }} + name: ${{ fromJSON(inputs.producers)[0].name }} + runner: ${{ fromJSON(inputs.producers)[0].runner }} + image: ${{ fromJSON(inputs.producers)[0].image }} + command: ${{ fromJSON(inputs.producers)[0].command }} + id: ${{ fromJSON(inputs.producers)[0].id }} consumers: # This is an internal dispatch job and the name is not important. # Give the job a short and unique name, otherwise github will bloat the job name with the matrix values. # This keeps the UI from getting cluttered. name: "c.${{ matrix.id }}" - needs: producers + needs: producer permissions: id-token: write contents: read diff --git a/.github/workflows/workflow-dispatch.yml b/.github/workflows/workflow-dispatch.yml index 7df1bbfeb03..984cad8968c 100644 --- a/.github/workflows/workflow-dispatch.yml +++ b/.github/workflows/workflow-dispatch.yml @@ -1,4 +1,4 @@ -name: "Workflow/Dispatch/Group" +name: "Workflow/Dispatch" defaults: run: @@ -7,49 +7,21 @@ defaults: on: workflow_call: inputs: - name: {type: string, required: true} - jobs: {type: string, required: true} - -permissions: - contents: read + workflow: + type: string + required: true jobs: - - standlone-jobs: - # This is an internal dispatch job and the name is not important. - # Give the job a short and unique name, otherwise github will bloat the job name with the matrix values. - # This keeps the UI from getting cluttered. - name: "s.${{ matrix.id }}" - if: ${{ fromJSON(inputs.jobs)['standalone'] != null }} - permissions: - id-token: write - contents: read - strategy: - fail-fast: false - matrix: - include: ${{fromJSON(inputs.jobs)['standalone']}} - uses: ./.github/workflows/workflow-dispatch-job.yml - with: - name: ${{ matrix.name }} - runner: ${{ matrix.runner }} - image: ${{ matrix.image }} - command: ${{ matrix.command }} - id: ${{ matrix.id }} - - two-stage-jobs: - # This is an internal dispatch job and the name is not important. - # Give the job a short and unique name, otherwise github will bloat the job name with the matrix values. - # This keeps the UI from getting cluttered. - name: "t.${{ matrix.id }}" - if: ${{ fromJSON(inputs.jobs)['two_stage'] != null }} + dispatch-groups-linux-two-stage: + name: ${{ matrix.name }} permissions: id-token: write contents: read strategy: fail-fast: false matrix: - include: ${{fromJSON(inputs.jobs)['two_stage']}} - uses: ./.github/workflows/workflow-dispatch-two-stage.yml + name: ${{ fromJSON(inputs.workflow)['linux_two_stage']['keys'] }} + uses: ./.github/workflows/workflow-dispatch-two-stage-group-linux.yml with: - producers: ${{ toJSON(matrix.producers) }} - consumers: ${{ toJSON(matrix.consumers) }} + name: ${{ matrix.name }} + pc-array: ${{ toJSON(fromJSON(inputs.workflow)['linux_two_stage']['jobs'][matrix.name]) }} diff --git a/ci/matrix.yaml b/ci/matrix.yaml index 1945f668510..b8b305eac07 100644 --- a/ci/matrix.yaml +++ b/ci/matrix.yaml @@ -51,6 +51,7 @@ workflows: # - {jobs: ['build'], project['thrust'], std: 17, ctk: *ctk_curr, cxx: [*gcc12, *llvm16]} # override: + - {jobs: ['test'], std: 17, project: 'thrust', cxx: [*gcc12, *llvm16], ctk: [*ctk_curr]} pull_request: # Old CTK