Skip to content

ci: run the C++ unit tests in the release configuration - #821

Merged
rkennke merged 2 commits into
mainfrom
ci/gtest-release-coverage
Sep 25, 2026
Merged

rkennke merged 2 commits into
mainfrom
ci/gtest-release-coverage

Conversation

@rkennke

@rkennke rkennke commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #819, which fixed a test fixture that only broke under -O3. This closes the gap that let it merge green and sit on main undetected.

The gap

No CI job compiles the gtests with optimisation.

Job Optimisation
gtest-asan-{amd64,arm64} -fno-optimize-sibling-calls, no -O
gtest-tsan-{amd64,arm64} -fno-optimize-sibling-calls, no -O
Java test-matrix release cells behind a test:release label; does not build gtests

So any defect that appears only once the optimiser runs has nothing to catch it on an ordinary pull request. #819 was exactly that: a trampoline whose frame -O3 folded away via a tail call. Its own CI was green, because #786 carried no test:release label and every cell read (<jdk>, debug, regular).

The change

Two jobs, extending .sanitizer_job with nothing else altered:

gtest-release-amd64:
  extends: .sanitizer_job
  tags: [ "arch:amd64" ]
  image: $BUILD_IMAGE_X64
  variables:
    SANITIZER_CONFIG: Release
    SANITIZER_LC: release

That works because buildGtestRelease already exists alongside the sanitizer variants, and emits binaries under the same bin/gtest/<config>_<test>/ layout the runner loop already globs for — so the template needs no modification at all.

I left the template named .sanitizer_job rather than renaming it to something config-neutral: the rename touches all four existing jobs and is unrelated to closing the gap. There is a comment at the new jobs noting the SANITIZER_* variable names are a misnomer for them. Say the word if you would rather have the rename.

Also fixed

nightly.yml claimed C++ gtests "run on every PR via native-sanitizer-tests in ci.yml". No such job exists — ci.yml has no sanitizer job at all; they run from .gitlab/sanitizer-tests on branch pushes. That is the same misreading that made this gap invisible, so it is worth correcting rather than leaving. The comment appears twice in that file, not once; both are updated.

Verification, and its limits

  • Both files parse (yq).
  • All six jobs resolve to the expected configs: asan/asan, tsan/tsan (×2 arches), release/release (×2 arches).
  • The two assumptions the template relies on were checked against a real build: buildGtestRelease exists, and it produces bin/gtest/release_<test>/, which the grep "/release_" in the runner matches.
  • Ran the full release suite locally as a risk probe — 67 binaries, 0 failures — on the theory that turning this on might surface a backlog of -O3-only breakage across tests that have never run optimised in CI. Nothing surfaced.

What I have not verified: this against GitLab's schema, or the jobs actually executing. The local probe was macOS/arm64, so Linux-gated fixtures were skipped there — including, ironically, the one from #819. The first pipeline run on this PR is the real test, and it is the cheapest place to find out.

Expected cost: two additional jobs per branch push, comparable in runtime to the existing sanitizer jobs (30m timeout, local full-suite build+run was ~90s).

🤖 Generated with Claude Code

No job compiled the gtests with optimisation. Both sanitizer presets pass
-fno-optimize-sibling-calls and no -O, and the release gtests the Java matrix
could reach are behind a test:release label, so a defect that only appears once
the optimiser runs had nothing to catch it on an ordinary pull request.

That is not hypothetical: a fixture whose frame -O3 folded away via a tail call
merged green and stayed broken on main until someone happened to build release
locally.

The two new jobs extend .sanitizer_job unchanged -- buildGtestRelease already
exists next to the sanitizer variants and emits binaries under the same
bin/gtest/<config>_<test>/ layout the runner loop globs for, so only the two
variables differ.

The nightly comment claiming gtests run per-PR from a sanitizer job in ci.yml
described a job that does not exist; it is the same misreading that left the
gap open, so both copies now say where they actually run.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
@rkennke
rkennke requested a review from a team as a code owner September 25, 2026 08:37

@datadog-prod-us1-6 datadog-prod-us1-6 Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bits Code Review: PASS

More details

The new amd64 and arm64 jobs use the existing release gtest build task and output path. The change has no reportable defect.

Was this helpful? React 👍 or 👎

Open Bits AI session

🤖 Bits Code Review · Commit 565c35c · @DataDog review to ask questions

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 565c35c1e3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +99 to +100
gtest-release-amd64:
extends: .sanitizer_job

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Gate artifact publication on release gtests

When either new release job fails after the existing sanitizer dependencies complete, build-artifact can still run because its DAG needs list names only the four ASan/TSan jobs; deploy-artifact then needs only build-artifact and the native builds. Thus an O3-only failure—the precise case these jobs are meant to catch—can still publish the affected artifact before the pipeline turns red. Add both release jobs to the publication gate.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Confirmed and fixed in 691178f.

Checked it against the config rather than taking it on trust: build-artifact's needs block named exactly the four sanitizer jobs, and because that is an explicit DAG rather than a stage dependency, it starts as soon as those pass. The release jobs would have run alongside publication instead of ahead of it — so an -O3-only failure would still have turned the pipeline red, but only after the affected artifact was built, and deploy-artifact needs build-artifact. That would have left these jobs advisory, which defeats the point of adding them.

Both are now in the gate:

gtest-asan-amd64      optional=false
gtest-tsan-amd64      optional=true
gtest-asan-arm64      optional=false
gtest-tsan-arm64      optional=true
gtest-release-amd64   optional=false   <- added
gtest-release-arm64   optional=false   <- added

Two notes on the shape of the fix:

Non-optional, matching the ASan entries rather than the TSan ones. All six jobs come from .sanitizer_job and share its rules, so whenever build-artifact exists they exist too. optional: true would tolerate a future rules change, but it would also let the coverage disappear silently — the same invisibility this PR is closing — so a loud failure is the better mode here.

Only build-artifact needed changing; deploy-artifact names it in its own needs, so it is gated transitively. Verified rather than assumed.

build-artifact declares an explicit needs DAG rather than waiting on the
sanitizer stage, so it starts the moment the four jobs it names have passed.
The two release jobs were not among them, which left them running alongside
publication instead of ahead of it: an -O3-only failure would eventually turn
the pipeline red, but only after the artifact it affects had been built, and
deploy-artifact needs build-artifact, so publication followed.

That is the exact failure these jobs were added to catch, so leaving them
outside the gate would have made them advisory.

Non-optional, matching the ASan entries: all six come from .sanitizer_job and
share its rules, so whenever build-artifact exists they exist too.

Reported by Codex review on #821.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
@dd-octo-sts

dd-octo-sts Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

CI Test Results

Run: #36114778247 | Commit: c90ddcd | Duration: 15m 44s (longest job)

✅ All 32 test jobs passed

Status Overview

JDK glibc-aarch64/debug glibc-amd64/debug musl-aarch64/debug musl-amd64/debug
8 - ✅ - -
8-ibm - ✅ - -
8-j9 ✅ ✅ - -
8-librca - - ✅ ✅
8-orcl - ✅ - -
11 - ✅ - -
11-j9 ✅ ✅ - -
11-librca - - ✅ ✅
17 ✅ ✅ - -
17-graal ✅ ✅ - -
17-j9 ✅ ✅ - -
17-librca - - ✅ ✅
21 ✅ ✅ - -
21-graal ✅ ✅ - -
21-librca - - ✅ ✅
25 ✅ ✅ - -
25-graal ✅ ✅ - -
25-librca - - ✅ ✅

Legend: ✅ passed | ❌ failed | ⚪ skipped | 🚫 cancelled

Summary: Total: 32 | Passed: 32 | Failed: 0


Updated: 2026-09-25 09:05:42 UTC

@dd-octo-sts

dd-octo-sts Bot commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

✅ All 40 integration tests passed

📊 Dashboard · 👷 Pipeline · 📦 691178f3

@rkennke
rkennke merged commit e8c7c86 into main Sep 25, 2026
113 checks passed
@rkennke
rkennke deleted the ci/gtest-release-coverage branch September 25, 2026 10:04
@github-actions github-actions Bot added this to the 1.51.0 milestone Sep 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant