Skip to content

Commit 18611a1

Browse files
[actions] Add build-and-test github action (#1054)
Summary: Adds a github action to run builds and tests, including bpf tests. The action uses the configs defined in `ci/github/bazelrc` along with the `bazel_build_deps.sh` script to decide what tests to run and under what configurations to run them. Type of change: /kind test-infra Test Plan: Tested in this PR that all the tests (including BPF tests) work. Also, tested that failing tests are reported properly, by adding an `ASSERT_EQ(0, 1)` only in opt configs, and saw that only opt configs failed. Signed-off-by: James Bartlett <jamesbartlett@pixielabs.ai>
1 parent c061a3e commit 18611a1

11 files changed

Lines changed: 409 additions & 4 deletions

File tree

.bazelrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ build:qemu-bpf --//bazel/test_runners:test_runner=qemu_with_kernel
123123
build:qemu-bpf --run_under="bazel/test_runners/qemu_with_kernel/test_runner.sh"
124124
build:qemu-bpf --build_tag_filters=requires_bpf,-no_qemu
125125
test:qemu-bpf --test_tag_filters=requires_bpf,-disabled,-no_qemu
126+
test:qemu-bpf --test_timeout=180,600,1800,3600
126127

127128
# Build for GCC.
128129
# These are copts because they apply to both c++ and c files.
@@ -174,6 +175,7 @@ build:tsan --define tcmalloc=disabled
174175
# https://github.com/google/sanitizers/issues/953
175176
build:tsan --test_env=TSAN_OPTIONS=report_atomic_races=0
176177
build:tsan --features=tsan
178+
test:tsan --test_timeout=180,600,1800,3600
177179

178180
# Note that we are lumping tests that require root into the BPF tests below
179181
# to minimize number of configs.

.github/actions/bazelrc/action.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ inputs:
55
download_toplevel:
66
description: 'whether to download cached toplevel files during bazel builds'
77
default: 'false'
8+
dev:
9+
description: 'Whether to use DEV or CI settings for the bazelrc. defaults to dev'
10+
default: 'true'
811
runs:
912
using: "composite"
1013
steps:
@@ -21,3 +24,14 @@ runs:
2124
run: |
2225
echo "build --remote_download_outputs=toplevel" >> github.bazelrc
2326
shell: bash
27+
- name: Add DEV settings
28+
if: inputs.dev == 'true'
29+
run: |
30+
echo "build --remote_upload_local_results=false" >> github.bazelrc
31+
echo "build --build_metadata=ROLE=DEV" >> github.bazelrc
32+
shell: bash
33+
- name: Add CI settings
34+
if: inputs.dev != 'true'
35+
run: |
36+
echo "build --build_metadata=ROLE=CI" >> github.bazelrc
37+
shell: bash
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
---
2+
name: build-and-test
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- 'main'
8+
schedule:
9+
# Run at 23:09 PST (07:09 UTC) every day. Github suggests not running actions on the hour.
10+
- cron: '9 7 * * *'
11+
permissions:
12+
contents: read
13+
jobs:
14+
get-dev-image:
15+
uses: ./.github/workflows/get_image.yaml
16+
with:
17+
image-base-name: "dev_image_with_extras"
18+
clang-tidy:
19+
needs: get-dev-image
20+
runs-on: [self-hosted, nokvm]
21+
container:
22+
image: ${{ needs.get-dev-image.outputs.image-with-tag }}
23+
volumes:
24+
- /etc/bazelrc:/etc/bazelrc
25+
options: --cpus 16
26+
steps:
27+
- uses: actions/checkout@v3
28+
with:
29+
fetch-depth: 0
30+
- name: Add pwd to git safe dir
31+
run: git config --global --add safe.directory `pwd`
32+
- name: get bazel config
33+
uses: ./.github/actions/bazelrc
34+
- name: Save Diff Info
35+
run: ./ci/save_diff_info.sh
36+
- name: Run Clang Tidy
37+
shell: bash
38+
# yamllint disable rule:indentation
39+
run: |
40+
diff_file="diff_origin_main_cc"
41+
if [[ "${{ github.event_name }}" == "push" ]] || [[ "${{ github.event_name }}" == "schedule" ]]; then
42+
diff_file="diff_head_cc"
43+
fi
44+
./ci/run_clang_tidy.sh -f "${diff_file}"
45+
# yamllint enable rule:indentation
46+
generate-matrix:
47+
needs: get-dev-image
48+
runs-on: [self-hosted, nokvm]
49+
container:
50+
image: ${{ needs.get-dev-image.outputs.image-with-tag }}
51+
volumes:
52+
- /etc/bazelrc:/etc/bazelrc
53+
options: --cpus 16
54+
outputs:
55+
matrix: ${{ steps.set-matrix.outputs.matrix }}
56+
steps:
57+
- uses: actions/checkout@v3
58+
with:
59+
fetch-depth: 0
60+
- name: Add pwd to git safe dir
61+
run: git config --global --add safe.directory `pwd`
62+
- name: get bazel config
63+
uses: ./.github/actions/bazelrc
64+
- name: Set matrix
65+
id: set-matrix
66+
shell: bash
67+
run: |
68+
echo '${{ toJSON(github) }}' > github.json
69+
matrix="$(./ci/github/matrix.sh github.json)"
70+
echo "Build & Test matrix: ${matrix}"
71+
echo "matrix=${matrix}" >> $GITHUB_OUTPUT
72+
- name: Upload Target Files
73+
uses: actions/upload-artifact@v3
74+
with:
75+
name: target_files
76+
path: |
77+
bazel_buildables_*
78+
bazel_tests_*
79+
build-and-test:
80+
needs: [get-dev-image, generate-matrix]
81+
runs-on:
82+
- self-hosted
83+
- ${{ matrix.runner }}
84+
container:
85+
image: ${{ needs.get-dev-image.outputs.image-with-tag }}
86+
volumes:
87+
- /etc/bazelrc:/etc/bazelrc
88+
- /var/run/docker.sock:/var/run/docker.sock
89+
options: --privileged
90+
if: needs.generate-matrix.outputs.matrix
91+
strategy:
92+
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
93+
fail-fast: false
94+
name: ${{ matrix.name }}
95+
steps:
96+
- uses: actions/checkout@v3
97+
- name: Add pwd to git safe dir
98+
run: git config --global --add safe.directory `pwd`
99+
- uses: actions/download-artifact@v3
100+
- name: get dev bazel config
101+
if: github.event_name != 'push'
102+
uses: ./.github/actions/bazelrc
103+
with:
104+
dev: 'true'
105+
- name: get ci bazel config
106+
if: github.event_name == 'push'
107+
uses: ./.github/actions/bazelrc
108+
with:
109+
dev: 'false'
110+
- name: Build ${{ matrix.name }}
111+
shell: bash
112+
# yamllint disable rule:indentation
113+
run: |
114+
./scripts/bazel_ignore_codes.sh build \
115+
${{ matrix.args }} \
116+
--target_pattern_file=target_files/${{ matrix.buildables }} \
117+
2> >(tee bazel_stderr)
118+
# yamllint enable rule:indentation
119+
- name: Test ${{ matrix.name }}
120+
if: ${{ matrix.tests }}
121+
shell: bash
122+
# yamllint disable rule:indentation
123+
run: |
124+
# Github actions container runner creates a docker network without IPv6 support. We enable it manually.
125+
sysctl -w net.ipv6.conf.lo.disable_ipv6=0
126+
./scripts/bazel_ignore_codes.sh test ${{ matrix.args }} --target_pattern_file=target_files/${{ matrix.tests }} \
127+
2> >(tee bazel_stderr)
128+
# yamllint enable rule:indentation
129+
- name: Buildbuddy URL
130+
if: always()
131+
run: |
132+
[[ -f bazel_stderr ]] || (echo "Error before bazel ran" && exit 1)
133+
bb_url="$(cat bazel_stderr | grep -Po "(?<=Streaming build results to: ).*" | tail -n 1)"
134+
echo "${bb_url}"
135+
shell: bash

bazel/test_runners/qemu_with_kernel/run_qemu.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ check_env_set QEMU_DISK_BASE_RO
3030
check_env_set MONITOR_SOCK
3131

3232
QEMU_MEMORY=${QEMU_MEMORY:-4096M}
33-
QEMU_CPU_COUNT=${QEMU_CPU_COUNT:-1}
33+
QEMU_CPU_COUNT=${QEMU_CPU_COUNT:-2}
3434

3535
# This needs to match what is in the exit c file.
3636
QEMU_EXIT_BASE="0xf4"

ci/bazel_build_deps.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ function compute_targets() {
103103
for file in $(git diff --name-only "${commit_range}" ); do
104104
for pat in "${poison_patterns[@]}"; do
105105
if [[ "$file" =~ ${pat} ]]; then
106-
echo "File ${file} with ${pat} modified. Triggering full build"
106+
echo "File ${file} with ${pat} modified. Triggering full build" >&2
107107
targets=("//...")
108108
return 0
109109
fi
@@ -130,7 +130,7 @@ function check_bpf_trigger() {
130130
for file in $(git diff --name-only "${commit_range}" ); do
131131
for pat in "${bpf_patterns[@]}"; do
132132
if [[ "$file" =~ ${pat} ]]; then
133-
echo "File ${file} with ${pat} modified. Triggering bpf targets"
133+
echo "File ${file} with ${pat} modified. Triggering bpf targets" >&2
134134
run_bpf_targets=true
135135
return 0
136136
fi

ci/github/bazelrc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ common --keep_going
88
build --build_metadata=HOST=github-actions
99
build --build_metadata=USER=github-actions
1010
build --build_metadata=REPO_URL=https://github.com/pixie-io/pixie
11-
build --build_metadata=ROLE=DEV
1211
build --build_metadata=VISIBILITY=PUBLIC
1312
build --verbose_failures
1413

@@ -39,3 +38,10 @@ test --local_cpu_resources=14
3938

4039
build --jobs 16
4140
test --jobs 16
41+
42+
# For qemu, we allocate 46 cpus instead of 16.
43+
build:qemu-bpf --local_cpu_resources=46
44+
test:qemu-bpf --local_cpu_resources=46
45+
46+
build:qemu-bpf --jobs=48
47+
test:qemu-bpf --jobs=48

ci/github/matrix.sh

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
#!/bin/bash -e
2+
3+
# Copyright 2018- The Pixie Authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
# SPDX-License-Identifier: Apache-2.0
18+
19+
# This script outputs a github actions matrix with each of the configs we want to build and test
20+
# It takes a file with the github context as its first argument: https://docs.github.com/en/actions/learn-github-actions/contexts#github-context
21+
github_context="$1"
22+
23+
event_name="$(jq -r '.event_name' < "${github_context}")"
24+
pr_body="$(jq -r '.event.pull_request.body' < "${github_context}")"
25+
commit_message="$(git log "$(git merge-base origin/main HEAD)"..HEAD --format="%B")"
26+
combined_message="${pr_body} \n${commit_message}"
27+
28+
nightly_regression_test_iterations="${NIGHTLY_REGRESSION_TEST_ITERATIONS:-5}"
29+
30+
all_kernel_versions=(
31+
"4.14.254"
32+
"4.19.254"
33+
"5.10.173"
34+
"5.15.101"
35+
"5.4.235"
36+
"6.1.18"
37+
)
38+
default_kernel_versions=(
39+
"4.14.254"
40+
"6.1.18"
41+
)
42+
kernel_versions=( "${default_kernel_versions[@]}" )
43+
44+
check_tag() {
45+
tag="$1"
46+
echo "${combined_message}" | grep -P "${tag}([^\-a-zA-Z]|$)" > /dev/null
47+
}
48+
49+
build_deps_flags=()
50+
extra_bazel_args=()
51+
# Build and test everything and BPF for main runs.
52+
if [[ "${event_name}" == "push" ]]; then
53+
echo "Main run. Building all targets and bpf" >&2
54+
build_deps_flags+=("-a" "-b")
55+
elif [[ "${event_name}" == "schedule" ]]; then
56+
echo "Nightly run. Building all targets and all kernel versions of bpf" >&2
57+
build_deps_flags+=("-a" "-b")
58+
extra_bazel_args+=("--runs_per_test=${nightly_regression_test_iterations}")
59+
kernel_versions=( "${all_kernel_versions[@]}" )
60+
elif [[ "${event_name}" == "pull_request" ]]; then
61+
# Ignore bazel dependency tracking and run all targets if #ci:ignore-deps is in the pr body/commit message.
62+
if check_tag '#ci:ignore-deps'; then
63+
echo "Found #ci:ignore-deps tag. Building all targets" >&2
64+
build_deps_flags+=("-a")
65+
fi
66+
# Build/Test bpf targets if #ci:bpf-build{-all-kernels} is in the pr body/commit message.
67+
if check_tag '#ci:bpf-build-all-kernels'; then
68+
echo "Found #ci:bpf-build tag. Building bpf targets" >&2
69+
build_deps_flags+=("-b")
70+
kernel_versions=( "${all_kernel_versions[@]}" )
71+
elif check_tag '#ci:bpf-build'; then
72+
echo "Found #ci:bpf-build-all-kernels. Building bpf targets on all kernel versions" >&2
73+
build_deps_flags+=("-b")
74+
fi
75+
fi
76+
77+
# Create the target pattern files, passthrough flags to bazel_build_deps.
78+
./ci/bazel_build_deps.sh "${build_deps_flags[@]}"
79+
# TODO(james): generate the target pattern files directly from ci/github/matrix.yaml instead of using bazel_build_deps,
80+
# so that we don't have to edit bazel_build_deps.sh for new configs.
81+
82+
remove_targetless_configs() {
83+
f="$1"
84+
# Remove any configs that don't have buildables.
85+
while read -r build_target_file;
86+
do
87+
if [ -s "${build_target_file}" ]; then
88+
continue
89+
fi
90+
yq -i e 'del(.configs[] | select(.buildables=="'"${build_target_file}"'"))' "${f}"
91+
done < <(yq e '.configs[].buildables' "${f}" | sort | uniq)
92+
93+
# Remove the `tests` key from any configs where the test target file is empty.
94+
while read -r test_target_file;
95+
do
96+
if [ -s "${test_target_file}" ]; then
97+
continue
98+
fi
99+
yq -i e 'del(.configs[].tests | select(.=="'"${test_target_file}"'"))' "${f}"
100+
done < <(yq e '.configs[].tests' "${f}" | sort | uniq)
101+
}
102+
103+
remove_disabled_configs() {
104+
yq -i e 'del(.configs[] | select(.disabled))' "$1"
105+
yq -i e 'del(.configs[].disabled)' "$1"
106+
}
107+
108+
merge_yamls() {
109+
# shellcheck disable=SC2016
110+
yq eval-all '. as $item ireduce ({}; . *+ $item)' "$@"
111+
}
112+
113+
extend_with_kernel_versions() {
114+
f="$1"
115+
kernel_matrix_configs="$(mktemp)"
116+
no_kernel="$(mktemp)"
117+
yq e 'del(.configs[] | select(.use_kernel_matrix != true))' "$f" > "${kernel_matrix_configs}"
118+
yq e 'del(.configs[] | select(.use_kernel_matrix))' "$f" > "${no_kernel}"
119+
120+
version_files=()
121+
for version in "${kernel_versions[@]}"
122+
do
123+
version_configs="$(mktemp)"
124+
yq e '.configs[].args += " --//bazel/test_runners/qemu_with_kernel:kernel_version='"${version}"'"' "$kernel_matrix_configs" > "${version_configs}"
125+
yq -i e '.configs[].name += " ('"${version}"')"' "${version_configs}"
126+
version_files+=("${version_configs}")
127+
done
128+
129+
merge_yamls "${version_files[@]}" "${no_kernel}" > "$f"
130+
yq -i e 'del(.configs[].use_kernel_matrix)' "$f"
131+
132+
rm "${kernel_matrix_configs}"
133+
rm "${no_kernel}"
134+
for f in "${version_files[@]}"
135+
do
136+
rm "$f"
137+
done
138+
}
139+
140+
add_extra_bazel_args() {
141+
f="$1"
142+
if [[ "${#extra_bazel_args[@]}" -gt 0 ]]; then
143+
yq -i e '.configs[].args += " '"${extra_bazel_args[*]}"'"' "$f"
144+
fi
145+
}
146+
147+
process_matrix() {
148+
in="$1"
149+
out="$2"
150+
151+
cp "${in}" "${out}"
152+
remove_disabled_configs "${out}"
153+
remove_targetless_configs "${out}"
154+
add_extra_bazel_args "${out}"
155+
extend_with_kernel_versions "${out}"
156+
}
157+
158+
matrix="$(mktemp)"
159+
process_matrix "ci/github/matrix.yaml" "${matrix}"
160+
161+
162+
if [[ "$(yq e '.configs|length' "${matrix}")" != 0 ]]; then
163+
yq e '.include = .configs | del(.configs)' -I=0 -o=json "${matrix}"
164+
fi
165+
166+
rm "${matrix}"

0 commit comments

Comments
 (0)