mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 22:02:23 +01:00
There is still a lot more we should try to do here, but this gets us a decent start and should be enough for some of the developers working on Carbon to use for simple cases, or tools like Compiler Explorer. This first factors most of the complex setup for our CI workflow into local actions that we can reuse in other workflows. It's actually a fairly nice cleanup I think even without the specific use case of a nightly release process. These use "composite" actions which is the cleanest model for factoring out a subsequence of steps from a workflow. I've tried to keep the inputs fairly minimal and easy to spot. Next, it adds a cron-scheduled action that builds and creates a nightly release. It also supports explicitly running the workflow, which can be useful if the nightly release is broken in some way: a fix can be landed and then a force run used. Tested the `tests` workflow using our `action-test` branch: https://github.com/carbon-language/carbon-lang/actions/runs/9545546278 Also tested the nightly release action by hacking in a `push` trigger and using *draft* release. If you have admin rights, you can see an example draft nightly build here: https://github.com/carbon-language/carbon-lang/releases/tag/untagged-6a85cdce7b3a784a2e6b Note that the GitHub releases are easily deleted, and even the tags created in the repository can be cleaned up as needed so it should be fairly harmless to fix this forward if needed.
195 lines
7.6 KiB
YAML
195 lines
7.6 KiB
YAML
# Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
# Exceptions. See /LICENSE for license information.
|
|
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
name: test
|
|
|
|
on:
|
|
push:
|
|
branches: [trunk, action-test]
|
|
pull_request:
|
|
merge_group:
|
|
|
|
permissions:
|
|
contents: read # For actions/checkout.
|
|
pull-requests: read # For dorny/paths-filter to read pull requests.
|
|
|
|
# Cancel previous workflows on the PR when there are multiple fast commits.
|
|
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
test:
|
|
strategy:
|
|
matrix:
|
|
# On PRs and in the merge queue test a recent version of each supported
|
|
# OS. On push (post-submit), also run on `macos-12` to get Intel macOS
|
|
# coverage.
|
|
runner:
|
|
${{ fromJSON(github.event_name != 'push' && '["ubuntu-22.04",
|
|
"macos-14"]' || '["ubuntu-22.04", "macos-14", "macos-12"]') }}
|
|
build_mode: [fastbuild, opt]
|
|
include:
|
|
# The clang-tidy config doesn't work on macos (missing `truncate`).
|
|
- runner: ubuntu-22.04
|
|
build_mode: clang-tidy
|
|
runs-on: ${{ matrix.runner }}
|
|
|
|
steps:
|
|
- name: Harden Runner
|
|
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
|
|
with:
|
|
egress-policy: audit
|
|
|
|
# Checkout the pull request head or the branch.
|
|
- name: Checkout pull request
|
|
if: github.event_name == 'pull_request'
|
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
|
with:
|
|
ref: ${{ github.event.pull_request.head.sha }}
|
|
|
|
- name: Checkout branch
|
|
if: github.event_name != 'pull_request'
|
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
|
|
|
# Tests should only run on applicable paths, but we still need to have an
|
|
# action run for the merge queue. We filter steps based on the paths here,
|
|
# and condition steps on the output.
|
|
- id: filter
|
|
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
|
with:
|
|
filters: |
|
|
has_code:
|
|
- '!{**/*.md,LICENSE,CODEOWNERS,.git*}'
|
|
|
|
# Disable uploads when the remote cache is read-only.
|
|
- name: Set up remote cache access (read-only)
|
|
if:
|
|
steps.filter.outputs.has_code == 'true' && github.event_name ==
|
|
'pull_request'
|
|
run: |
|
|
echo "remote_cache_upload=--remote_upload_local_results=false" \
|
|
>> $GITHUB_ENV
|
|
|
|
# Provide a cache key when the remote cache is read-write.
|
|
- name: Set up remote cache access (read-write)
|
|
if:
|
|
steps.filter.outputs.has_code == 'true' && github.event_name !=
|
|
'pull_request'
|
|
env:
|
|
REMOTE_CACHE_KEY: ${{ secrets.CARBON_BUILDS_GITHUB }}
|
|
run: |
|
|
echo "$REMOTE_CACHE_KEY" | base64 -d > $HOME/remote_cache_key.json
|
|
echo "remote_cache_upload=--google_credentials=$HOME/remote_cache_key.json" \
|
|
>> $GITHUB_ENV
|
|
|
|
- uses: ./.github/actions/build-setup-common
|
|
if: steps.filter.outputs.has_code == 'true'
|
|
with:
|
|
matrix_runner: ${{ matrix.runner }}
|
|
remote_cache_upload: ${{ env.remote_cache_upload }}
|
|
|
|
# Just for visibility, print space before and after the build.
|
|
- name: Disk space before build
|
|
if: steps.filter.outputs.has_code == 'true'
|
|
run: df -h
|
|
|
|
- name: Verify MODULE.bazel.lock
|
|
if: steps.filter.outputs.has_code == 'true'
|
|
run: |
|
|
exit_code=0
|
|
./scripts/run_bazel.py \
|
|
--attempts=5 \
|
|
mod deps --lockfile_mode=error || exit_code=$?
|
|
if (( $exit_code != 0 )); then
|
|
./scripts/run_bazel.py \
|
|
--attempts=5 \
|
|
mod deps --lockfile_mode=update
|
|
echo "MODULE.bazel.lock is out of date! Use below file for update."
|
|
echo "Platforms may require merging output, for example by applying"
|
|
echo "an update, re-running triggers, and applying the next update."
|
|
echo "============================================================"
|
|
cat MODULE.bazel.lock
|
|
echo "============================================================"
|
|
exit 1
|
|
fi
|
|
|
|
# Build and run all targets on branch pushes to ensure we always have a
|
|
# clean tree. We don't expect this to be an interactive path and so don't
|
|
# optimize the latency of this step.
|
|
- name: Compute impacted pull request targets (for push)
|
|
if:
|
|
steps.filter.outputs.has_code == 'true' && github.event_name == 'push'
|
|
env:
|
|
TARGETS_FILE: ${{ runner.temp }}/targets
|
|
run: |
|
|
echo "//..." >$TARGETS_FILE
|
|
|
|
# Compute the set of possible rules impacted by this change using
|
|
# Bazel-based diffing. This lets PRs and the merge queue have a much more
|
|
# efficient test CI action by avoiding even enumerating (and downloading)
|
|
# all of the unaffected Bazel targets.
|
|
- name: Compute impacted pull request targets
|
|
if:
|
|
steps.filter.outputs.has_code == 'true' && github.event_name != 'push'
|
|
env:
|
|
# Compute the base SHA from the different event structures.
|
|
GIT_BASE_SHA:
|
|
${{ github.event_name == 'pull_request' &&
|
|
github.event.pull_request.base.sha ||
|
|
github.event.merge_group.base_sha }}
|
|
TARGETS_FILE: ${{ runner.temp }}/targets
|
|
run: |
|
|
# First fetch the relevant base into the git repository.
|
|
git fetch --depth=1 origin $GIT_BASE_SHA
|
|
|
|
# Then use `target-determinator` as wrapped by our script.
|
|
./scripts/target_determinator.py $GIT_BASE_SHA >$TARGETS_FILE
|
|
|
|
# Bazel requires a test target to run the test command. There may be
|
|
# no targets or there may only be non-test targets that we want to
|
|
# build, so simply inject an explicit no-op test target.
|
|
echo "//scripts:no_op_test" >> $TARGETS_FILE
|
|
|
|
# Build and run just the tests impacted by the PR or merge group.
|
|
- name: Test (${{ matrix.build_mode }})
|
|
if:
|
|
steps.filter.outputs.has_code == 'true' && matrix.build_mode !=
|
|
'clang-tidy'
|
|
env:
|
|
# 'libtool_check_unique failed to generate' workaround.
|
|
# https://github.com/bazelbuild/bazel/issues/14113#issuecomment-999794586
|
|
BAZEL_USE_CPP_ONLY_TOOLCHAIN: 1
|
|
TARGETS_FILE: ${{ runner.temp }}/targets
|
|
run: |
|
|
# Decrease the jobs sharply if we see repeated failures to try to
|
|
# work around transient network errors even if it makes things
|
|
# slower.
|
|
./scripts/run_bazel.py \
|
|
--attempts=5 --jobs-on-last-attempt=4 \
|
|
test -c ${{ matrix.build_mode }} \
|
|
--target_pattern_file=$TARGETS_FILE
|
|
|
|
# Run in the clang-tidy config. This is done as part of tests so that we
|
|
# aren't duplicating bazel/llvm setup.
|
|
#
|
|
# The `-k` flag is used to print all clang-tidy errors.
|
|
- name: clang-tidy
|
|
if:
|
|
steps.filter.outputs.has_code == 'true' && matrix.build_mode ==
|
|
'clang-tidy'
|
|
env:
|
|
TARGETS_FILE: ${{ runner.temp }}/targets
|
|
run: |
|
|
./scripts/run_bazel.py \
|
|
--attempts=5 \
|
|
build --config=clang-tidy -k \
|
|
--target_pattern_file=$TARGETS_FILE
|
|
|
|
# See "Disk space before build".
|
|
- name: Disk space after build
|
|
if: steps.filter.outputs.has_code == 'true'
|
|
run: df -h
|