Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/compute-projects-to-test/action.yml
Original file line number Diff line number Diff line change
@@ -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
220 changes: 220 additions & 0 deletions .github/workflows/compute-projects-to-test/compute-projects-to-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
#!/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)}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this work, when a branch contains multiple commits (e.g. an original one and multiple corrections/tweaks) - essentially we should check the diff of the whole branch, right?

But when doing that, we also need to make sure that we ignore any changes from merge commits, like in llvm/llvm-admin#8, otherwise we will essentially end up testing every single subproject as soon as an MR contains a merge commit. IIRC git diff <base>...HEAD is the syntax for that, but it's worth testing and looking into.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The HEAD commit for a PR is a merge of the PR branch into main. It's not the HEAD for the PR target branch. In my testing using HEAD~1...HEAD worked for multiple commits. I did not test the case where the PR branch had a merge commit in it already. I can test git diff <base>...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}))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
projects_to_test=$(exclude-windows $(compute-projects-to-test ${modified_projects}))
# Don't run dependent projects on Windows for now.
projects_to_test=$(exclude-windows ${modified_projects})

else
echo "Unknown runner OS: $RUNNER_OS"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should exit with an error here:

Suggested change
echo "Unknown runner OS: $RUNNER_OS"
echo "Unknown runner OS: $RUNNER_OS"
exit 1

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping

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
61 changes: 61 additions & 0 deletions .github/workflows/precommit-windows.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: "Windows Precommit Tests"

permissions:
contents: read

on:
pull_request:
branches:
- main

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-llvm-windows:
name: "Build and test LLVM (Windows)"
runs-on: windows-2022
steps:
- name: Setup Windows
uses: llvm/actions/setup-windows@main
with:
arch: amd64
- name: Fetch LLVM sources
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Setup ccache
uses: hendrikmuhs/ccache-action@v1
with:
max-size: 500M
variant: sccache
key: precommit-windows
- name: Compute projects to test
id: compute-projects
uses: ./.github/workflows/compute-projects-to-test
with:
projects: clang llvm lld
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
with:
projects: clang llvm lld


- name: Configure LLVM
shell: bash
if: ${{ steps.compute-projects.outputs.check-targets }}
run: |
cmake -B build -GNinja \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_ENABLE_PROJECTS="${{ steps.compute-projects.outputs.projects }}" \
-DCMAKE_C_COMPILER_LAUNCHER=sccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache \
-DLLVM_ENABLE_ASSERTIONS=ON \
-DLLVM_LIT_ARGS="-v --no-progress-bar" \
-S llvm
- name: Build LLVM
if: ${{ steps.compute-projects.outputs.check-targets }}
run: |
ninja -C build test-depends
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This step will overbuild: if a PR only touches clang and not LLVM, it should only run ninja check-clang and not build the LLVM unit-tests and other things not needed by clang for example.
(same for the other projects)

Suggested change
- name: Build LLVM
if: ${{ steps.compute-projects.outputs.check-targets }}
run: |
ninja -C build test-depends

- name: Check LLVM
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- name: Check LLVM
- name: Check LLVM

This checks more than LLVM, doesn't it?

if: ${{ steps.compute-projects.outputs.check-targets }}
run: |
ninja -C build "${{ steps.compute-projects.outputs.check-targets }}"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ninja -C build "${{ steps.compute-projects.outputs.check-targets }}"
ninja -C build ${{ steps.compute-projects.outputs.check-targets }}

Need to remove the quotes here because there can be multiple targets