diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml new file mode 100644 index 00000000000000..e1d1c02755939b --- /dev/null +++ b/.github/workflows/ci-tests.yml @@ -0,0 +1,156 @@ +name: "CI Tests" + +permissions: + contents: read + +on: + pull_request: + types: + - opened + - synchronize + - reopened + # When a PR is closed, we still start this workflow, but then skip + # all the jobs, which makes it effectively a no-op. The reason to + # do this is that it allows us to take advantage of concurrency groups + # to cancel in progress CI jobs whenever the PR is closed. + - closed + branches: + - 'release/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: True + +jobs: + compute-test-configs: + name: "Compute Configurations to Test" + if: >- + github.repository_owner == 'llvm' && + github.event.action != 'closed' + runs-on: ubuntu-22.04 + outputs: + projects: ${{ steps.vars.outputs.projects }} + check-targets: ${{ steps.vars.outputs.check-targets }} + test-build: ${{ steps.vars.outputs.check-targets != '' }} + test-platforms: ${{ steps.platforms.outputs.result }} + steps: + - name: Fetch LLVM sources + uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: Compute projects to test + id: vars + uses: ./.github/workflows/compute-projects-to-test + + - name: Compute platforms to test + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1 + id: platforms + with: + script: | + linuxConfig = { + name: "linux-x86_64", + runs_on: "ubuntu-22.04" + } + windowsConfig = { + name: "windows-x86_64", + runs_on: "windows-2022" + } + macConfig = { + name: "macos-x86_64", + runs_on: "macos-13" + } + macArmConfig = { + name: "macos-aarch64", + runs_on: "macos-14" + } + + configs = [] + + const base_ref = process.env.GITHUB_BASE_REF; + if (base_ref.startsWith('release/')) { + // This is a pull request against a release branch. + configs.push(macConfig) + configs.push(macArmConfig) + } + + return configs; + + ci-build-test: + # If this job name is changed, then we need to update the job-name + # paramater for the timeout-save step below. + name: "Build" + needs: + - compute-test-configs + permissions: + actions: write #pr-sccache-save may delete artifacts. + runs-on: ${{ matrix.runs_on }} + strategy: + fail-fast: false + matrix: + include: ${{ fromJson(needs.compute-test-configs.outputs.test-platforms) }} + if: needs.compute-test-configs.outputs.test-build == 'true' + steps: + - name: Fetch LLVM sources + uses: actions/checkout@v4 + + - name: Timeout Restore + id: timeout + uses: ./.github/workflows/timeout-restore + with: + artifact-name-suffix: ${{ matrix.name }} + + - name: Setup Windows + uses: llvm/actions/setup-windows@main + if: ${{ runner.os == 'Windows' }} + with: + arch: amd64 + + - name: Install Ninja + uses: llvm/actions/install-ninja@main + + - name: Setup sccache + uses: hendrikmuhs/ccache-action@v1 + with: + max-size: 2G + variant: sccache + key: ci-${{ matrix.name }} + + - name: Restore sccache from previous PR run + uses: ./.github/workflows/pr-sccache-restore + with: + artifact-name-suffix: ${{ matrix.name }} + + - name: Configure + if: ${{ steps.timeout.outputs.exists != 'true' }} + shell: bash + run: | + cmake -B build -GNinja \ + -DCMAKE_BUILD_TYPE=Release \ + -DLLVM_ENABLE_PROJECTS="${{ needs.compute-test-configs.outputs.projects }}" \ + -DLLVM_ENABLE_ASSERTIONS=ON \ + -DLLVM_LIT_ARGS="-v --no-progress-bar" \ + -DCMAKE_C_COMPILER_LAUNCHER=sccache \ + -DCMAKE_CXX_COMPILER_LAUNCHER=sccache \ + -S llvm + + - name: Build + shell: bash + timeout-minutes: 330 + run: | + ninja -C build -k 0 ${{ needs.compute-test-configs.outputs.check-targets }} + + - name: Timeout Save + if: always() + uses: ./.github/workflows/timeout-save + with: + job-name: "Build (${{ matrix.name }}, ${{ matrix.runs_on }})" + artifact-name-suffix: ${{ matrix.name }} + timeout-step: "Build" + timeout-minutes: 330 + + - name: Save sccache for next PR run + if: always() + uses: ./.github/workflows/pr-sccache-save + with: + artifact-name-suffix: ${{ matrix.name }} diff --git a/.github/workflows/clang-tests.yml b/.github/workflows/clang-tests.yml deleted file mode 100644 index 2569ce19518e3e..00000000000000 --- a/.github/workflows/clang-tests.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Clang Tests - -permissions: - contents: read - -on: - workflow_dispatch: - push: - branches: - - 'release/**' - paths: - - 'clang/**' - - '.github/workflows/clang-tests.yml' - - '.github/workflows/llvm-project-tests.yml' - - '!llvm/**' - pull_request: - branches: - - 'release/**' - paths: - - 'clang/**' - - '.github/workflows/clang-tests.yml' - - '.github/workflows/llvm-project-tests.yml' - - '!llvm/**' - -concurrency: - # Skip intermediate builds: always. - # Cancel intermediate builds: only if it is a pull request build. - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} - -jobs: - check_clang: - if: github.repository_owner == 'llvm' - name: Test clang,lldb,libclc - uses: ./.github/workflows/llvm-project-tests.yml - with: - build_target: check-clang - projects: clang;lldb;libclc diff --git a/.github/workflows/compute-projects-to-test/action.yml b/.github/workflows/compute-projects-to-test/action.yml new file mode 100644 index 00000000000000..37df06c8c301c5 --- /dev/null +++ b/.github/workflows/compute-projects-to-test/action.yml @@ -0,0 +1,21 @@ +name: 'Compute Projects To Test' +inputs: + projects: + required: false + type: 'string' + +outputs: + check-targets: + description: "A space delimited list of check-targets to pass to ninja." + value: ${{ steps.compute-projects.outputs.check-targets }} + + projects: + description: "A semi-colon delimited list of projects to pass to -DLLVM_ENABLE_PROJECTS." + value: ${{ steps.compute-projects.outputs.projects }} + +runs: + using: "composite" + steps: + - id: compute-projects + run: .github/workflows/compute-projects-to-test/compute-projects-to-test.sh ${{ inputs.projects }} + shell: bash diff --git a/.github/workflows/compute-projects-to-test/compute-projects-to-test.sh b/.github/workflows/compute-projects-to-test/compute-projects-to-test.sh new file mode 100755 index 00000000000000..4cfbda0c82034c --- /dev/null +++ b/.github/workflows/compute-projects-to-test/compute-projects-to-test.sh @@ -0,0 +1,221 @@ +#!/usr/bin/env bash +#===----------------------------------------------------------------------===## +# +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +#===----------------------------------------------------------------------===## + +# +# This file generates a Buildkite pipeline that triggers the various CI jobs for +# the LLVM project during pre-commit CI. +# +# See https://buildkite.com/docs/agent/v3/cli-pipeline#pipeline-format. +# +# As this outputs a yaml file, it's possible to log messages to stderr or +# prefix with "#". + + +set -eu +set -o pipefail + +# Environment variables script works with: + +# Set by GitHub +: ${GITHUB_OUTPUT:=} +: ${RUNNER_OS:=} + +# Allow users to specify which projects to build. +all_projects="bolt clang clang-tools-extra compiler-rt cross-project-tests flang libc libclc lld lldb llvm mlir openmp polly pstl" +if [ "$#" -ne 0 ]; then + wanted_projects="${@}" +else + wanted_projects="${all_projects}" +fi + +# List of files affected by this commit +: ${MODIFIED_FILES:=$(git diff --name-only HEAD~1...HEAD)} + +echo "Files modified:" >&2 +echo "$MODIFIED_FILES" >&2 +modified_dirs=$(echo "$MODIFIED_FILES" | cut -d'/' -f1 | sort -u) +echo "Directories modified:" >&2 +echo "$modified_dirs" >&2 +echo "wanted_projects: $wanted_projects" + +function remove-unwanted-projects() { + projects=${@} + for project in ${projects}; do + if echo "$wanted_projects" | tr ' ' '\n' | grep -q -E "^${project}$"; then + echo "${project}" + fi + done +} + +function compute-projects-to-test() { + projects=${@} + for project in ${projects}; do + echo "${project}" + case ${project} in + lld) + for p in bolt cross-project-tests; do + echo $p + done + ;; + llvm) + for p in bolt clang clang-tools-extra flang lld lldb mlir polly; do + echo $p + done + ;; + clang) + for p in clang-tools-extra compiler-rt flang libc lldb openmp cross-project-tests; do + echo $p + done + ;; + clang-tools-extra) + echo libc + ;; + mlir) + echo flang + ;; + *) + # Nothing to do + ;; + esac + done +} + +function add-dependencies() { + projects=${@} + for project in ${projects}; do + echo "${project}" + case ${project} in + bolt) + for p in lld llvm; do + echo $p + done + ;; + cross-project-tests) + for p in lld clang; do + echo $p + done + ;; + clang-tools-extra) + for p in llvm clang; do + echo $p + done + ;; + compiler-rt|libc|openmp) + echo clang lld + ;; + flang|lldb) + for p in llvm clang; do + echo $p + done + ;; + lld|mlir|polly) + echo llvm + ;; + *) + # Nothing to do + ;; + esac + done +} + +function exclude-linux() { + projects=${@} + for project in ${projects}; do + case ${project} in + cross-project-tests) ;; # tests failing + lldb) ;; # tests failing + openmp) ;; # https://github.com/google/llvm-premerge-checks/issues/410 + *) + echo "${project}" + ;; + esac + done +} + +function exclude-windows() { + projects=${@} + for project in ${projects}; do + case ${project} in + cross-project-tests) ;; # tests failing + compiler-rt) ;; # tests taking too long + openmp) ;; # TODO: having trouble with the Perl installation + libc) ;; # no Windows support + lldb) ;; # tests failing + bolt) ;; # tests are not supported yet + *) + echo "${project}" + ;; + esac + done +} + +# Prints only projects that are both present in $modified_dirs and the passed +# list. +function keep-modified-projects() { + projects=${@} + for project in ${projects}; do + if echo "$modified_dirs" | grep -q -E "^${project}$"; then + echo "${project}" + fi + done +} + +function check-targets() { + projects=${@} + for project in ${projects}; do + case ${project} in + clang-tools-extra) + echo "check-clang-tools" + ;; + compiler-rt) + echo "check-all" + ;; + cross-project-tests) + echo "check-cross-project" + ;; + lldb) + echo "check-all" # TODO: check-lldb may not include all the LLDB tests? + ;; + pstl) + echo "check-all" + ;; + libclc) + echo "check-all" + ;; + *) + echo "check-${project}" + ;; + esac + done +} + +# Generic pipeline for projects that have not defined custom steps. +# +# Individual projects should instead define the pre-commit CI tests that suits their +# needs while letting them run on the infrastructure provided by LLVM. + +# Figure out which projects need to be built on each platform +modified_projects="$(keep-modified-projects ${all_projects})" +echo "modified_projects: $modified_projects" + +if [ "${RUNNER_OS}" = "Linux" ]; then + projects_to_test=$(exclude-linux $(compute-projects-to-test ${modified_projects})) +elif [ "${RUNNER_OS}" = "Windows" ]; then + projects_to_test=$(exclude-windows $(compute-projects-to-test ${modified_projects})) +else + echo "Unknown runner OS: $RUNNER_OS" + exit 1 +fi +check_targets=$(check-targets $(remove-unwanted-projects ${projects_to_test}) | sort | uniq) +projects=$(remove-unwanted-projects $(add-dependencies ${projects_to_test}) | sort | uniq) + +echo "check-targets=$(echo ${check_targets} | tr ' ' ' ')" >> $GITHUB_OUTPUT +echo "projects=$(echo ${projects} | tr ' ' ';')" >> $GITHUB_OUTPUT + +cat $GITHUB_OUTPUT diff --git a/.github/workflows/continue-timeout-job.yml b/.github/workflows/continue-timeout-job.yml new file mode 100644 index 00000000000000..f3ff58c77cfe0e --- /dev/null +++ b/.github/workflows/continue-timeout-job.yml @@ -0,0 +1,75 @@ +name: Continue Timeout Job + +on: + workflow_run: + workflows: + - "Windows Precommit Tests" + - "CI Tests" + types: + - completed + +permissions: + contents: read + +jobs: + restart: + name: "Restart Job" + permissions: + actions: write + runs-on: ubuntu-22.04 + if: github.event.workflow_run.conclusion == 'failure' + steps: + - name: "Restart Job" + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1 + with: + script: | + const response = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id + }) + + job_ids = []; + + for (artifact of response.data.artifacts) { + console.log(artifact); + const match = artifact.name.match(/timeout-([0-9]+)/); + console.log(match); + if (!match) { + continue; + } + job_ids.push(match[1]); + + // Delete the timeout artifact to prepare for the next run + await github.rest.actions.deleteArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: artifact.id + }); + } + + if (job_ids.length == 0) { + return; + } + + if (job_ids.length > 1) { + // We aren't able to re-start multiple jobs individually, so our + // only option is to restart all failed jobs. + await github.rest.actions.reRunWorkflowFailedJobs({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id + }) + console.log("Restarted workflow: " + context.payload.workflow_run.id); + return; + } + + job_id = job_ids[0]; + // This function does not exist even though it is in the document + //github.rest.actions.reRunJobForWorkflow({ + await github.request('POST /repos/{owner}/{repo}/actions/jobs/{job_id}/rerun', { + owner: context.repo.owner, + repo: context.repo.repo, + job_id: job_id + }) + console.log("Restarted job: " + job_id); diff --git a/.github/workflows/get-job-id/action.yml b/.github/workflows/get-job-id/action.yml new file mode 100644 index 00000000000000..65495efd86820a --- /dev/null +++ b/.github/workflows/get-job-id/action.yml @@ -0,0 +1,30 @@ +name: Get Job ID +inputs: + job-name: + required: false + type: 'string' + +outputs: + job-id: + description: "A space delimited list of check-targets to pass to ninja." + value: ${{ steps.job-id.outputs.result }} + +runs: + using: "composite" + steps: + - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1 + id: job-id + with: + script: | + const job_data = await github.rest.actions.listJobsForWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.runId, + }); + + for (job of job_data.data.jobs) { + console.log(job) + if (job.name == "${{ inputs.job-name }}") { + return job.id + } + } diff --git a/.github/workflows/libclc-tests.yml b/.github/workflows/libclc-tests.yml deleted file mode 100644 index 23192f776a985e..00000000000000 --- a/.github/workflows/libclc-tests.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: libclc Tests - -permissions: - contents: read - -on: - workflow_dispatch: - push: - branches: - - 'release/**' - paths: - - 'libclc/**' - - '.github/workflows/libclc-tests.yml' - - '.github/workflows/llvm-project-tests.yml' - - '!clang/**' - - '!llvm/**' - pull_request: - branches: - - 'release/**' - paths: - - 'libclc/**' - - '.github/workflows/libclc-tests.yml' - - '.github/workflows/llvm-project-tests.yml' - - '!clang/**' - - '!llvm/**' - -concurrency: - # Skip intermediate builds: always. - # Cancel intermediate builds: only if it is a pull request build. - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} - -jobs: - check_libclc: - if: github.repository_owner == 'llvm' - name: Test libclc - uses: ./.github/workflows/llvm-project-tests.yml - with: - projects: clang;libclc diff --git a/.github/workflows/lld-tests.yml b/.github/workflows/lld-tests.yml deleted file mode 100644 index 599c0975fa6858..00000000000000 --- a/.github/workflows/lld-tests.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: LLD Tests - -permissions: - contents: read - -on: - workflow_dispatch: - push: - branches: - - 'release/**' - paths: - - 'lld/**' - - '.github/workflows/lld-tests.yml' - - '.github/workflows/llvm-project-tests.yml' - - '!llvm/**' - pull_request: - branches: - - 'release/**' - paths: - - 'lld/**' - - '.github/workflows/lld-tests.yml' - - '.github/workflows/llvm-project-tests.yml' - - '!llvm/**' - -concurrency: - # Skip intermediate builds: always. - # Cancel intermediate builds: only if it is a pull request build. - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} - -jobs: - check_lld: - if: github.repository_owner == 'llvm' - name: Test lld - uses: ./.github/workflows/llvm-project-tests.yml - with: - build_target: check-lld - projects: lld diff --git a/.github/workflows/lldb-tests.yml b/.github/workflows/lldb-tests.yml deleted file mode 100644 index 6bb9721956258f..00000000000000 --- a/.github/workflows/lldb-tests.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: lldb Tests - -permissions: - contents: read - -on: - workflow_dispatch: - push: - branches: - - 'release/**' - paths: - - 'lldb/**' - - '.github/workflows/lldb-tests.yml' - - '.github/workflows/llvm-project-tests.yml' - - '!clang/**' - - '!llvm/**' - pull_request: - branches: - - 'release/**' - paths: - - 'lldb/**' - - '.github/workflows/lldb-tests.yml' - - '.github/workflows/llvm-project-tests.yml' - - '!clang/**' - - '!llvm/**' - -concurrency: - # Skip intermediate builds: always. - # Cancel intermediate builds: only if it is a pull request build. - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} - -jobs: - build_lldb: - if: github.repository_owner == 'llvm' - name: Build lldb - uses: ./.github/workflows/llvm-project-tests.yml - with: - projects: clang;lldb diff --git a/.github/workflows/llvm-tests.yml b/.github/workflows/llvm-tests.yml index 64d60bc3da45e1..016da80472e20a 100644 --- a/.github/workflows/llvm-tests.yml +++ b/.github/workflows/llvm-tests.yml @@ -11,14 +11,12 @@ on: paths: - 'llvm/**' - '.github/workflows/llvm-tests.yml' - - '.github/workflows/llvm-project-tests.yml' pull_request: branches: - 'release/**' paths: - 'llvm/**' - '.github/workflows/llvm-tests.yml' - - '.github/workflows/llvm-project-tests.yml' concurrency: # Skip intermediate builds: always. @@ -27,14 +25,6 @@ concurrency: cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} jobs: - check-all: - if: github.repository_owner == 'llvm' - name: Build and Test - uses: ./.github/workflows/llvm-project-tests.yml - with: - build_target: check-all - projects: clang;lld;libclc;lldb - abi-dump-setup: if: github.repository_owner == 'llvm' runs-on: ubuntu-latest diff --git a/.github/workflows/pr-sccache-restore/action.yml b/.github/workflows/pr-sccache-restore/action.yml new file mode 100644 index 00000000000000..8aa87025ba54b7 --- /dev/null +++ b/.github/workflows/pr-sccache-restore/action.yml @@ -0,0 +1,26 @@ +name: PR sccache restore + +inputs: + artifact-name-suffix: + desciption: The suffix to append to the artifict name (sccache-pr#) + required: true + +runs: + using: "composite" + steps: + - uses: ./.github/workflows/unprivileged-download-artifact + id: download-artifact + with: + artifact-name: sccache-pr${{ github.event.pull_request.number }}-${{ inputs.artifact-name-suffix }} + + - shell: bash + if: steps.download-artifact.outputs.filename != '' + run: | + # Is this the best way to clear the cache? + rm -Rf .sccache/ + unzip ${{ steps.download-artifact.outputs.filename }} + rm ${{ steps.download-artifact.outputs.filename }} + tar --zstd -xf sccache.tar.zst + rm sccache.tar.zst + ls -altr + diff --git a/.github/workflows/pr-sccache-save/action.yml b/.github/workflows/pr-sccache-save/action.yml new file mode 100644 index 00000000000000..badf623d32d5ef --- /dev/null +++ b/.github/workflows/pr-sccache-save/action.yml @@ -0,0 +1,27 @@ +name: PR sccache save +inputs: + artifact-name-suffix: + desciption: The suffix to append to the artifict name (sccache-pr#) + required: true + +runs: + using: "composite" + steps: + - name: Package sccache Directory + shell: bash + run: | + # Dereference symlinks so that this works on Windows. + tar -h -c .sccache | zstd -T0 -c > sccache.tar.zst + + - uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0 + with: + name: 'sccache-pr${{ github.event.number }}-${{ inputs.artifact-name-suffix }}' + path: sccache.tar.zst + retention-days: 7 + overwrite: true + + - shell: bash + run: | + rm sccache.tar.zst + sccache --show-stats + diff --git a/.github/workflows/timeout-restore/action.yml b/.github/workflows/timeout-restore/action.yml new file mode 100644 index 00000000000000..417782ccc5ca18 --- /dev/null +++ b/.github/workflows/timeout-restore/action.yml @@ -0,0 +1,33 @@ +name: Timeout Restore +description: Save build state from a timed out job. +inputs: + artifact-name-suffix: + desciption: Suffix to add to the name of the artifact containing the build state. + required: true + +outputs: + exists: + description: "This is true if a previous timeout build was restored, false otherwise." + value: ${{ steps.timeout-artifact.exists }} + +runs: + using: "composite" + steps: + - name: Download Artifact + uses: actions/download-artifact@6b208ae046db98c579e8a3aa621ab581ff575935 # v4.1.1 + with: + pattern: timeout-build-${{ inputs.artifact-name-suffix }} + merge-multiple: true + + - name: Unpack Artifact + id: timeout-artifact + shell: bash + run: | + if [ -e llvm-project.tar.zst ]; then + tar --zstd -xf llvm-project.tar.zst + rm llvm-project.tar.zst + echo "exists=true" >> $GITHUB_OUTPUT + else + echo "exists=false" >> $GITHUB_OUTPUT + fi + diff --git a/.github/workflows/timeout-save/action.yml b/.github/workflows/timeout-save/action.yml new file mode 100644 index 00000000000000..fcea59165cf30b --- /dev/null +++ b/.github/workflows/timeout-save/action.yml @@ -0,0 +1,94 @@ +name: Timeout Save +description: Save build state when a timeout occurs so that it can be reused when the job is restarted. +inputs: + job-name: + description: The name of the job. This is used to look up the job id. + required: true + artifact-name-suffix: + desciption: Suffix to add to the name of the artifact containing the build state. + required: true + timeout-step: + description: The step that we want to restart if there is a timeout. + required: true + timeout-minutes: + description: The value of timeout-minutes for this step. + required: true + +runs: + using: "composite" + steps: + - name: Check for timeout + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1 + id: timeout + with: + script: | + const job_data = await github.rest.actions.listJobsForWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.runId, + }); + + for (job of job_data.data.jobs) { + console.log(job) + if (job.name != "${{ inputs.job-name }}") { + continue; + } + + for (step of job.steps) { + console.log(step); + if (step.name != "${{ inputs.timeout-step }}") { + continue; + } + if (step.conclusion != "failure") { + return false; + } + + // This run failed, check for timeout. + console.log(step.completed_at) + console.log(step.started_at) + completed_at = Date.parse(step.completed_at); + started_at = Date.parse(step.started_at); + console.log(completed_at) + console.log(started_at) + const diff = (completed_at - started_at) / 1000; + console.log(diff); + if (diff > 60 * ${{ inputs.timeout-minutes }}) + return true; + } + } + return false; + + - name: Save Working Directory + shell: bash + if: steps.timeout.outputs.result == 'true' + run: | + # Dereference symlinks so that this works on Windows. + tar -h -c . | zstd -T0 -c > ../llvm-project.tar.zst + mv ../llvm-project.tar.zst . + + - name: Upload Working Directory + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0 + if: steps.timeout.outputs.result == 'true' + with: + name: timeout-build-${{ inputs.artifact-name-suffix }} + path: llvm-project.tar.zst + retention-days: 2 + + - name: Get Job ID + id: job-id + if: steps.timeout.outputs.result == 'true' + uses: ./.github/workflows/get-job-id + with: + job-name: ${{ inputs.job-name }} + + - name: Create Timeout File + if: steps.timeout.outputs.result == 'true' + shell: bash + run: touch timeout-${{ steps.job-id.outputs.job-id }} + + - name: Upload Timeout File + if: steps.timeout.outputs.result == 'true' + uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 #v4.3.0 + with: + name: timeout-${{ steps.job-id.outputs.job-id }} + path: timeout-${{ steps.job-id.outputs.job-id }} diff --git a/.github/workflows/unprivileged-download-artifact/action.yml b/.github/workflows/unprivileged-download-artifact/action.yml new file mode 100644 index 00000000000000..5ff657d9378895 --- /dev/null +++ b/.github/workflows/unprivileged-download-artifact/action.yml @@ -0,0 +1,77 @@ +name: Unprivileged Download Artifact +description: Download artifacts from another workflow run without using an access token. +inputs: + run-id: + description: The run-id for the workflow run that you want to download the artifact from. If ommited it will download the most recently created artifact from the repo with the artifact-name. + required: false + artifact-name: + desciption: The name of the artifact to download. + required: true + + +outputs: + filename: + description: "The filename of the downloaded artifact or the empty string if the artifact was not found." + value: ${{ steps.download-artifact.outputs.filename }} + artifact-id: + description: "The id of the artifact being downloaded." + value: ${{ steps.artifact-url.outputs.id }} + + +runs: + using: "composite" + steps: + - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea #v7.0.1 + id: artifact-url + with: + script: | + var response; + if (!"${{ inputs.run-id }}") { + response = await github.rest.actions.listArtifactsForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + name: "${{ inputs.artifact-name }}" + }) + } else { + const response = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: "${{ inputs.run-id }}", + name: "${{ inputs.artifact-name }}" + }) + } + + console.log(response) + + for (artifact of response.data.artifacts) { + console.log(artifact); + } + + if (response.data.artifacts.length == 0) { + console.log("Could not find artifact ${{ inputs.artifact-name }} for workflow run ${{ inputs.run-id }}") + return; + } + + const url_response = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: response.data.artifacts[0].id, + archive_format: "zip" + }) + + core.setOutput("url", url_response.url); + core.setOutput("id", response.data.artifacts[0].id); + + - shell: bash + run: | + echo "${{ steps.artifact-url.outputs.url }}" + echo "${{ steps.artifact-url.outputs.result }}" + echo "${{ steps.artifact-url.outputs.result.url }}" + echo "${{ steps.artifact-url.outputs.result.id }}" + + - shell: bash + if: steps.artifact-url.outputs.url != '' + id: download-artifact + run: | + curl -L -o ${{ inputs.artifact-name }}.zip "${{ steps.artifact-url.outputs.url }}" + echo "filename=${{ inputs.artifact-name }}.zip" >> $GITHUB_OUTPUT diff --git a/llvm/a b/llvm/a new file mode 100644 index 00000000000000..e69de29bb2d1d6