Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
12 changes: 9 additions & 3 deletions .github/actions/cpp-bazel/pre-merge/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ runs:
shell: bash
run: |
cd foreign/cpp
cargo clippy --manifest-path Cargo.toml --all-targets --all-features -- -D warnings
cargo clippy --all-targets --all-features -- -D warnings

- name: Build
if: inputs.task == 'build'
Expand All @@ -72,18 +72,24 @@ runs:
cd foreign/cpp
bazel build --config=ci //:iggy-cpp

- name: Install cargo-llvm-cov
if: inputs.task == 'test'
uses: taiki-e/install-action@v2.87.3
with:
tool: cargo-llvm-cov

- name: Setup server for tests
if: inputs.task == 'test'
uses: ./.github/actions/utils/server-start
with:
cargo-bin: iggy-server

- name: Test
- name: Test with coverage
if: inputs.task == 'test'
shell: bash
run: |
cd foreign/cpp
bazel test --config=ci //...
../../scripts/ci/cpp-coverage.sh

- name: Stop server after tests
if: always() && inputs.task == 'test'
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,18 @@ jobs:
with:
task: ${{ inputs.task }}

- name: Upload C++ coverage to Codecov
if: inputs.component == 'sdk-cpp' && inputs.task == 'test'
uses: codecov/codecov-action@v7.0.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: reports/cpp-coverage.lcov
disable_search: true
flags: cpp
fail_ci_if_error: false
verbose: true
override_pr: ${{ github.event.pull_request.number }}

- name: Upload Java coverage to Codecov
if: inputs.component == 'sdk-java' && inputs.task == 'test'
uses: codecov/codecov-action@v7.0.0
Expand Down
55 changes: 53 additions & 2 deletions .github/workflows/coverage-baseline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
# specific language governing permissions and limitations
# under the License.

# Coverage baseline for all 7 languages (Rust, Java, C#, Python, PHP,
# Node, Go). Runs on push to master so Codecov has data on master SHAs for
# Coverage baseline for all 8 languages (Rust, Java, C#, Python, PHP,
# Node, Go, C++). Runs on push to master so Codecov has data on master SHAs for
# carryforward on PR builds where only a subset of SDKs is tested.
#
# Jobs are path-gated: a language job runs only when the paths feeding its
Expand Down Expand Up @@ -61,6 +61,7 @@ jobs:
php: ${{ steps.affected.outputs.php }}
node: ${{ steps.affected.outputs.node }}
go: ${{ steps.affected.outputs.go }}
cpp: ${{ steps.affected.outputs.cpp }}
steps:
- uses: actions/checkout@v7.0.1
with:
Expand Down Expand Up @@ -581,6 +582,56 @@ jobs:
flags: go
fail_ci_if_error: false

cpp-coverage:
name: C++ coverage baseline
needs: detect
if: needs.detect.outputs.cpp == 'true'
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- uses: actions/checkout@v7.0.1

- name: Setup Bazel with cache
uses: ./.github/actions/utils/setup-cpp-with-cache

- name: Setup Rust with cache
uses: ./.github/actions/utils/setup-rust-with-cache
with:
save-cache: "false"

- name: Install cargo-llvm-cov
uses: taiki-e/install-action@v2.87.3
with:
tool: cargo-llvm-cov

# The e2e suite needs a live server; unit tests run standalone.
- name: Start Iggy server
id: iggy
uses: ./.github/actions/utils/server-start
with:
cargo-bin: iggy-server

- name: Run tests and generate coverage
run: |
cd foreign/cpp
../../scripts/ci/cpp-coverage.sh

- name: Stop Iggy server
if: always()
uses: ./.github/actions/utils/server-stop
with:
pid-file: ${{ steps.iggy.outputs.pid_file }}
log-file: ${{ steps.iggy.outputs.log_file }}

- name: Upload to Codecov
uses: codecov/codecov-action@v7.0.0
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: reports/cpp-coverage.lcov
disable_search: true
flags: cpp
fail_ci_if_error: false

warm-cache-macos:
name: Warm macOS cache
needs: detect
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/pre-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ jobs:
with:
component: ${{ matrix.component }}
task: ${{ matrix.task }}
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

# Other components
test-other:
Expand Down
7 changes: 7 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ flag_management:
- name: go
paths:
- foreign/go/
- name: cpp
paths:
- foreign/cpp/

component_management:
individual_components:
Expand Down Expand Up @@ -102,6 +105,10 @@ component_management:
name: "Go SDK"
paths:
- foreign/go/
- component_id: cpp
name: "C++ SDK"
paths:
- foreign/cpp/

comment:
layout: "header, diff, components, files"
Expand Down
36 changes: 34 additions & 2 deletions foreign/cpp/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,21 @@

load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_import", "cc_library", "cc_test")

config_setting(
name = "coverage_enabled",
values = {"define": "iggy_cpp_coverage=1"},
)

genrule(
name = "cargo_build",
srcs = glob(["src/**/*.rs"]) + [
"Cargo.toml",
"build.rs",
"@iggy_source//:cpp_rust_dependencies",
],
outs = [
"libiggy_cpp.a",
"libprofiler_builtins.a",
"include/lib.rs.h",
"cxxbridge/rust/cxx.h",
"cxxbridge/sources/lib.rs.cc",
Expand All @@ -37,6 +44,7 @@ genrule(
RUSTC="$$EXECROOT/$(execpath @rs_host_tools//:rustc)"
CARGO_TARGET_DIR="$$EXECROOT/$(@D)/cargo_target"
OUT_LIB="$$EXECROOT/$(location libiggy_cpp.a)"
PROFILER_RT_OUT="$$EXECROOT/$(location libprofiler_builtins.a)"
OUT_RS="$$EXECROOT/$(location include/lib.rs.h)"
OUT_CXX="$$EXECROOT/$(location cxxbridge/rust/cxx.h)"
OUT_CC="$$EXECROOT/$(location cxxbridge/sources/lib.rs.cc)"
Expand All @@ -55,10 +63,25 @@ genrule(
env -u PWD \
CARGO_TARGET_DIR="$$CARGO_TARGET_DIR" \
RUSTC="$$RUSTC" \
"$$CARGO" build $$FLAGS
"$$CARGO" build --quiet $$FLAGS

cp "$$CARGO_TARGET_DIR/$$PROFILE/libiggy_cpp.a" "$$OUT_LIB"

RT_SYSROOT="$$("$$RUSTC" --print sysroot)"
RT_HOST="$$("$$RUSTC" -vV | sed -n 's/^host: //p')"
RT_RLIB="$$(find "$$RT_SYSROOT/lib/rustlib/$$RT_HOST/lib" -maxdepth 1 -name 'libprofiler_builtins-*.rlib' -print -quit)"
if [ -z "$$RT_RLIB" ]; then
echo "ERROR: Failed to locate libprofiler_builtins rlib under $$RT_SYSROOT" >&2
exit 1
fi
cp "$$RT_RLIB" "$$PROFILER_RT_OUT"
for member in $$(ar t "$$PROFILER_RT_OUT"); do
case "$$member" in
*.o) ;;
*) ar d "$$PROFILER_RT_OUT" "$$member" ;;
esac
done

RS_HDR="$$(find "$$CARGO_TARGET_DIR/$$PROFILE/build" -name lib.rs.h -print -quit)"
if [ -z "$$RS_HDR" ]; then
echo "ERROR: Failed to locate generated lib.rs.h under $$CARGO_TARGET_DIR/$$PROFILE/build" >&2
Expand Down Expand Up @@ -93,6 +116,12 @@ cc_import(
static_library = ":libiggy_cpp.a",
)

cc_import(
name = "profiler_rt",
static_library = ":libprofiler_builtins.a",
alwayslink = True,
)

cc_library(
name = "iggy-cpp",
srcs = glob(
Expand Down Expand Up @@ -139,7 +168,10 @@ cc_library(
visibility = ["//visibility:public"],
deps = [
":iggy_cpp_static",
],
] + select({
":coverage_enabled": [":profiler_rt"],
"//conditions:default": [],
}),
)

cc_binary(
Expand Down
17 changes: 17 additions & 0 deletions foreign/cpp/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,23 @@ bazel_dep(name = "googletest", version = "1.18.0.bcr.1")
bazel_dep(name = "cucumber-cpp", version = "0.8.0.bcr.1")
bazel_dep(name = "rules_rust", version = "0.74.0")

iggy_source = use_repo_rule("@bazel_tools//tools/build_defs/repo:local.bzl", "new_local_repository")
iggy_source(
name = "iggy_source",
build_file_content = """
filegroup(
name = "cpp_rust_dependencies",
srcs = glob([
"core/binary_protocol/**",
"core/common/**",
"core/sdk/**",
]) + ["Cargo.toml"],
visibility = ["//visibility:public"],
)
""",
path = "../..",
)

rust_host_tools = use_extension("@rules_rust//rust:extensions.bzl", "rust_host_tools")
rust_host_tools.host_tools(
name = "rs_host_tools",
Expand Down
3 changes: 2 additions & 1 deletion scripts/ci/coverage-baseline-affected.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ set -euo pipefail
BASE="${1:-}"
HEAD="${2:-}"
ZERO="0000000000000000000000000000000000000000"
GATES=(rust java csharp python php node go)
GATES=(rust java csharp python php node go cpp)

emit_all() {
local gate
Expand Down Expand Up @@ -82,6 +82,7 @@ for gate in "${GATES[@]}"; do
node) paths=(foreign/node) ;;
# The go job also runs the bdd/go suite with foreign/go in -coverpkg.
go) paths=(foreign/go bdd/go) ;;
cpp) paths=(foreign/cpp) ;;
*)
echo "coverage-gate: no pathspecs defined for gate '$gate'" >&2
exit 1
Expand Down
81 changes: 81 additions & 0 deletions scripts/ci/cpp-coverage.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/usr/bin/env bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
CPP_ROOT="$REPO_ROOT/foreign/cpp"

cd "$CPP_ROOT"

OUTPUT="$REPO_ROOT/reports/cpp-coverage.lcov"
COVERAGE_DIR="$CPP_ROOT/target/cpp-coverage"
BUILD_PROFRAW_DIR="$COVERAGE_DIR/build"
PROFDATA="$COVERAGE_DIR/shim.profdata"
CPP_RAW="$CPP_ROOT/bazel-out/_coverage/_coverage_report.dat"

mkdir -p "$COVERAGE_DIR" "$BUILD_PROFRAW_DIR" "$(dirname "$OUTPUT")"
rm -f "$COVERAGE_DIR"/*.profraw "$BUILD_PROFRAW_DIR"/*.profraw "$PROFDATA" "$OUTPUT"

if ! LLVM_COV_ENV="$(cargo llvm-cov show-env --no-rustc-wrapper --sh)"; then
echo "cpp-coverage: 'cargo llvm-cov show-env' failed" >&2
exit 1
fi
eval "$LLVM_COV_ENV"
export LLVM_PROFILE_FILE="$COVERAGE_DIR/%p-%m.profraw"

LLVM_BIN="$(rustc --print target-libdir)/../bin"
LLVM_COV="$LLVM_BIN/llvm-cov"
LLVM_PROFDATA="$LLVM_BIN/llvm-profdata"

bazel coverage \
--config=debug \
--lockfile_mode=error \
--combined_report=lcov \
'--instrumentation_filter=//:iggy-cpp' \
--strategy=TestRunner=standalone \
--define=iggy_cpp_coverage=1 \
--action_env=RUSTFLAGS \
"--action_env=LLVM_PROFILE_FILE=$BUILD_PROFRAW_DIR/%p-%m.profraw" \
"--run_under=/usr/bin/env LLVM_PROFILE_FILE=$LLVM_PROFILE_FILE" \
//:unit //:e2e

"$LLVM_PROFDATA" merge -sparse \
"$COVERAGE_DIR"/*.profraw \
-o "$PROFDATA"

sed 's|^SF:|SF:foreign/cpp/|' "$CPP_RAW" >"$OUTPUT"

"$LLVM_COV" export \
--object bazel-bin/unit \
--object bazel-bin/e2e \
-instr-profile="$PROFDATA" \
-format=lcov \
-ignore-filename-regex='(\.cargo/|/rustc/|/core/|cxxbridge|/registry/)' |
awk '
/^SF:/ {
include = /foreign\/cpp\/src\/[^/]+\.rs$/
if (include) {
sub(/^SF:.*foreign\/cpp\//, "SF:foreign/cpp/")
}
}
include
' >>"$OUTPUT"

"$SCRIPT_DIR/validate-lcov.sh" "$OUTPUT"
Loading