Legacy Readme #4775
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Celerity CI | |
on: | |
push: | |
pull_request: | |
workflow_dispatch: | |
inputs: | |
test-head: | |
description: "Test against 'HEAD' revisions" | |
type: boolean | |
required: true | |
default: false | |
tag-latest: | |
description: "Tag 'HEAD' revisions as 'latest' if successful" | |
type: boolean | |
required: true | |
default: false | |
# We use nightly builds to determine whether CI passes for "HEAD" revisions | |
# of DPC++ and AdaptiveCpp. If so, these revisions are tagged as "latest" and | |
# used for all subsequent CI runs. | |
schedule: | |
# Every night at 05:00 UTC | |
- cron: "0 5 * * *" | |
jobs: | |
find-duplicate-workflows: | |
runs-on: [ self-hosted, slurm ] | |
outputs: | |
should_skip: ${{ steps.skip-check.outputs.should_skip }} | |
steps: | |
- id: skip-check | |
uses: fkirc/[email protected] | |
with: | |
concurrent_skipping: "never" | |
skip_after_successful_duplicate: "false" | |
do_not_skip: '["workflow_dispatch", "schedule"]' | |
cancel_others: "true" | |
# Run Clang-Tidy checks | |
# | |
# Note: | |
# - The action we use for this (ZedThree/clang-tidy-review) is a Docker action. | |
# However, to obtain the required compile_commands.json file, we need our own | |
# Docker container environment. We therefore run this job within a build container | |
# and manually call the job's Python script. | |
# - This action currently only supports pull_request triggers (as it creates review | |
# comments), so we have to run it regardless of skip-duplicate-action's outcome | |
# (as otherwise pull_request triggers will usually be skipped due to the push | |
# trigger already running). | |
# | |
# TODO: This should be combined with the report (or "lint") step, really | |
clang-tidy: | |
if: github.event.pull_request | |
runs-on: [ self-hosted, slurm-nvidia ] | |
env: | |
container-workspace: <placeholder> | |
build-dir: /root/build | |
container: | |
# We could run this for more than one implementation, | |
# but would likely end up with mostly duplicate diagnostics. | |
image: celerity-build/hipsycl:ubuntu22.04-latest | |
volumes: | |
- ccache:/ccache | |
steps: | |
# Here and in jobs below: We need to manually set the container workspace | |
# path as an environment variable, as (curiously) the `github.workspace` context | |
# variable contains the path on the container host (but $GITHUB_WORKSPACE is correct). | |
- name: Set container workspace environment variable | |
run: echo "container-workspace=$GITHUB_WORKSPACE" > $GITHUB_ENV | |
- uses: actions/checkout@v2 | |
with: | |
submodules: true | |
# We only want to configure CMake, so we build the "help" target, | |
# which doesn't actually do anything (other than print all targets). | |
- name: Configure CMake | |
run: bash -o pipefail -c "bash /root/build-celerity.sh ${{ env.container-workspace }} --build-type Debug --target help" | |
- name: Check clang-tidy | |
working-directory: ${{ env.build-dir }} | |
run: | | |
git clone https://github.com/ZedThree/clang-tidy-review.git | |
cd clang-tidy-review | |
git checkout v0.9.0 | |
pip install -r ./requirements.txt | |
cd ${{ env.container-workspace }} | |
python3 ${{ env.build-dir }}/clang-tidy-review/review.py \ | |
--clang_tidy_binary=clang-tidy \ | |
--token=${{ github.token }} \ | |
--repo=${{ github.repository }} \ | |
--pr=${{ github.event.pull_request.number }} \ | |
--build_dir=${{ env.build-dir }} \ | |
--config_file=${{ env.container-workspace }}/.clang-tidy \ | |
--include="*.h,*.cc,*.[ch]pp" \ | |
--lgtm-comment-body="" | |
# We need to jump through some hoops to have different build matrices based on what triggered the workflow. | |
# For normal CI runs we want to build and test against everything except the "HEAD" revisions, whereas during | |
# nightly builds we *only* want those. | |
# | |
# Current workaround is to represent the matrix as a JSON object, which is then deserialized in the next job. | |
read-build-matrix: | |
needs: find-duplicate-workflows | |
if: needs.find-duplicate-workflows.outputs.should_skip != 'true' | |
runs-on: self-hosted | |
outputs: | |
matrix: ${{ steps.read-json-matrix.outputs.matrix }} | |
steps: | |
- uses: actions/checkout@v2 | |
- id: read-json-matrix | |
name: Read build matrix from file | |
shell: python | |
run: | | |
import json | |
with open("${{ github.workspace }}/.github/workflows/build_matrix.json") as f: | |
matrices = json.load(f) | |
if '${{ github.event_name != 'schedule' && inputs.test-head == false }}' == 'true': | |
matrix = matrices['default'] | |
else: | |
matrix = matrices['nightly'] | |
print('::set-output name=matrix::{ "include":%s }' % json.dumps(matrix)) | |
build-and-test: | |
needs: [find-duplicate-workflows, read-build-matrix] | |
if: ${{ needs.find-duplicate-workflows.outputs.should_skip != 'true' }} | |
runs-on: [ self-hosted, "slurm-${{ matrix.platform }}" ] | |
strategy: | |
fail-fast: false | |
matrix: ${{ fromJSON(needs.read-build-matrix.outputs.matrix) }} | |
# These outputs are required by the image tagging step, only set during nightly builds. | |
outputs: | |
dpcpp-HEAD-Debug-works: ${{ steps.set-head-results.outputs.dpcpp-HEAD-Debug-works }} | |
dpcpp-HEAD-Release-works: ${{ steps.set-head-results.outputs.dpcpp-HEAD-Release-works }} | |
dpcpp-HEAD-ubuntu-version: ${{ steps.set-head-results.outputs.dpcpp-HEAD-ubuntu-version }} | |
acpp-HEAD-Debug-works: ${{ steps.set-head-results.outputs.acpp-HEAD-Debug-works }} | |
acpp-HEAD-Release-works: ${{ steps.set-head-results.outputs.acpp-HEAD-Release-works }} | |
acpp-HEAD-ubuntu-version: ${{ steps.set-head-results.outputs.acpp-HEAD-ubuntu-version }} | |
env: | |
build-name: ${{ matrix.platform }}-ubuntu${{ matrix.ubuntu-version }}-${{ matrix.sycl }}-${{ matrix.sycl-version }}-${{ matrix.build-type }} | |
container-workspace: <placeholder> | |
build-dir: /root/build | |
examples-build-dir: /root/build-examples | |
container: | |
image: celerity-build/${{ matrix.sycl }}:ubuntu${{ matrix.ubuntu-version }}-${{ matrix.sycl-version }} | |
volumes: | |
- ccache:/ccache | |
steps: | |
- name: Set container workspace environment variable | |
run: echo "container-workspace=$GITHUB_WORKSPACE" > $GITHUB_ENV | |
- name: Print exact SYCL revision used for this CI run | |
run: cat /VERSION | |
- uses: actions/checkout@v2 | |
with: | |
submodules: true | |
- name: Build and install Celerity | |
run: bash -o pipefail -c "bash /root/build-celerity.sh ${{ env.container-workspace }} --build-type ${{ matrix.build-type }} --target install 2>&1 | tee ${{ env.build-name }}.log" | |
# Upload build log for report step | |
- name: Upload build logs | |
if: always() | |
uses: actions/upload-artifact@v2 | |
with: | |
name: ${{ env.build-name }} | |
path: ${{ env.build-name }}.log | |
- name: Build examples against installed Celerity | |
run: bash /root/build-examples.sh ${{ env.container-workspace }}/examples --build-type ${{ matrix.build-type }} | |
- name: Reset coverage counters | |
if: matrix.build-type == 'Debug' && matrix.sycl == 'simsycl' # celerity-build/simsycl image enables --coverage for Debug builds | |
run: fastcov -z -d "${{ env.build-dir }}" | |
# For a run with ASan, we need to fake dlclose() so all shared libraries are still mapped when leaks are evaluated | |
# - otherwise, we will see "<unknown module>" instead of a proper trace if it originated in an unloaded library | |
# (see https://github.com/google/sanitizers/issues/89#issuecomment-406316683). LD_PRELOAD will be set to CI_LD_PRELOAD | |
# by /root/capture-backtrace.sh (otherwise we would also preload for other processes like bash, which we don't want to do). | |
# Also, hwloc (used by OpenMPI) will attempt to dlopen(RTLD_DEEPBIND) for GPU backend discovery which is incompatible | |
# with sanitizers but also irrelevant for a SimSYCL build, so we set HWLOC_COMPONENTS accordingly. | |
- name: Prepare Sanitizer run | |
if: matrix.sycl == 'simsycl' && matrix.build-type == 'Debug' | |
run: | | |
echo "ASAN_OPTIONS=detect_leaks=1" >> $GITHUB_ENV | |
echo "LSAN_OPTIONS=suppressions=$GITHUB_WORKSPACE/ci/lsan.suppressions" >> $GITHUB_ENV | |
echo "int dlclose(void *p) { return 0; }" | cc -x c -shared -o libfake_dlclose.so - | |
echo "CI_LD_PRELOAD=$(echo /usr/lib/x86_64-linux-gnu/libasan.so.?):$(pwd)/libfake_dlclose.so" >> $GITHUB_ENV | |
echo "HWLOC_COMPONENTS=-cuda,-opencl,-rsmi" >> $GITHUB_ENV | |
- name: Run unit tests | |
timeout-minutes: 5 | |
working-directory: ${{ env.build-dir }} | |
run: ${{ env.container-workspace }}/ci/run-unit-tests.sh | |
- name: Run examples | |
timeout-minutes: 5 | |
# We build examples twice, but only run the installed version (which probably has more failure modes) | |
working-directory: ${{ env.examples-build-dir }} | |
run: ${{ env.container-workspace }}/ci/run-examples.sh /data/Lenna.png 1 2 4 | |
- name: Run system tests | |
working-directory: ${{ env.build-dir }} | |
run: ${{ env.container-workspace }}/ci/run-system-tests.sh 2 4 | |
- name: Run integration tests | |
working-directory: ${{ env.build-dir }} | |
run: ${{ env.container-workspace }}/test/integration/run-integration-tests.py . ${{ matrix.platform }} | |
- name: Upload stack traces (if any) | |
if: always() | |
uses: actions/upload-artifact@v2 | |
with: | |
name: ${{ env.build-name }} | |
path: | | |
${{ env.build-dir }}/*.trace | |
${{ env.examples-build-dir }}/*.trace | |
if-no-files-found: ignore | |
- id: set-head-results | |
name: Set outputs for HEAD builds | |
if: matrix.sycl-version == 'HEAD' | |
run: | | |
echo "::set-output name=${{ matrix.sycl }}-HEAD-${{ matrix.build-type }}-works::1" | |
echo "::set-output name=${{ matrix.sycl }}-HEAD-ubuntu-version::${{ matrix.ubuntu-version }}" | |
# Tag "HEAD" images that built and tested successfully as "latest". | |
# This is only done for nightly builds (or when specifying the "tag-latest" option on manually triggered runs). | |
tag-latest-containers: | |
needs: [find-duplicate-workflows, build-and-test] | |
# Run this step regardless of result of `build-and-test` (hence the `always()`), | |
# since we always want to tag images that were successful, even if others weren't. | |
if: always() && needs.find-duplicate-workflows.outputs.should_skip != 'true' && (github.event_name == 'schedule' || (inputs.test-head && inputs.tag-latest)) | |
runs-on: slurm-${{ matrix.platform }} | |
strategy: | |
fail-fast: false | |
matrix: | |
include: | |
- sycl: "dpcpp" | |
platform: "intel" | |
- sycl: "acpp" | |
platform: "nvidia" | |
env: | |
image-basename-dpcpp: ghcr.io/celerity/celerity-build/dpcpp:ubuntu${{ needs.build-and-test.outputs.dpcpp-HEAD-ubuntu-version }} | |
image-basename-acpp: ghcr.io/celerity/celerity-build/acpp:ubuntu${{ needs.build-and-test.outputs.acpp-HEAD-ubuntu-version }} | |
permissions: | |
packages: write | |
steps: | |
- if: matrix.sycl == 'dpcpp' | |
run: | | |
if [[ "${{ needs.build-and-test.outputs.dpcpp-HEAD-Debug-works }}" -eq 1 ]] && [[ "${{ needs.build-and-test.outputs.dpcpp-HEAD-Release-works }}" -eq 1 ]]; then | |
docker tag ${{ env.image-basename-dpcpp }}-HEAD ${{ env.image-basename-dpcpp }}-latest | |
else | |
exit 1 | |
fi | |
- if: matrix.sycl == 'acpp' | |
run: | | |
if [[ "${{ needs.build-and-test.outputs.acpp-HEAD-Debug-works }}" -eq 1 ]] && [[ "${{ needs.build-and-test.outputs.acpp-HEAD-Release-works }}" -eq 1 ]]; then | |
docker tag ${{ env.image-basename-acpp }}-HEAD ${{ env.image-basename-acpp }}-latest | |
docker push ${{ env.image-basename-acpp }}-latest | |
else | |
exit 1 | |
fi | |
report: | |
needs: [find-duplicate-workflows, build-and-test] | |
if: ${{ needs.find-duplicate-workflows.outputs.should_skip != 'true' }} | |
runs-on: [ self-hosted, slurm ] | |
env: | |
container-workspace: <placeholder> | |
container: | |
image: celerity-lint | |
steps: | |
- name: Set container workspace environment variable | |
run: echo "container-workspace=$GITHUB_WORKSPACE" > $GITHUB_ENV | |
- uses: actions/checkout@v2 | |
- name: Check code formatting | |
id: formatting | |
working-directory: ${{ env.container-workspace }} | |
shell: bash | |
run: | | |
unformatted=$("./ci/find-unformatted-files.sh") | |
unformatted=${unformatted//$'\n'/'%0A'} | |
echo "::set-output name=unformatted-files::$unformatted" | |
- uses: "celerity/ci-report-action@v6" | |
with: | |
gh-token: ${{ secrets.GITHUB_TOKEN }} | |
unformatted-files: ${{ steps.formatting.outputs.unformatted-files }} |