Repository navigation
Summarize each tests run in one report and keep only release artifacts - #263
Merged
Merged
Conversation
Motivation
----------
The source job uploads the scripts and the tests as two artifacts so
that later jobs can download them. They show up in every run beside
the gems and docs, although nothing needs them once the run ends.
The failure logs list test/**/*.{log,xml}. upload-artifact globs do
not expand braces, so the JUnit reports and test logs are missing
from every failure artifact.
The server and CNG test jobs check out the repository and then run
the tests with lib/ on the load path. Those jobs test the Ruby
sources against the installed gem's native extension, not the gem
as it is packaged.
Modifications
-------------
- Every job that needs scripts or tests checks out the commit. The
repackage jobs use a sparse checkout of bin/jenkins.
- The Alpine job checks out before restoring ccache, because checkout
empties the workspace that holds the cache.
- Test jobs remove lib/ before running, so every suite loads the
installed gem.
- The Alpine job applies the build number that the source job
computed, so build-gem.sh finds the source gem by version.
- mock_windows disables core.autocrlf, so test data keeps LF line
endings as it had in the artifact.
- Failure logs list test/**/*.log and test/reports/.
Results
-------
A run no longer produces the scripts and tests artifacts. Failure
artifacts carry the JUnit reports. The server and CNG suites now
test the packaged gem.
Motivation ---------- No CI job publishes test coverage. The test jobs load the installed gem, so SimpleCov, which tracks files under the project root, records no coverage of lib/ in them. Modifications ------------- - A coverage job on ubuntu-26.04 builds the extension from the checkout with rake compile and runs the tests twice with lib/ on the load path: against the mock, then against a cbdinocluster cluster. The cluster run goes ahead after failed mock tests. - SimpleCov names each run by COVERAGE_NAME and merges runs up to three hours old into one report. It counts only lib/ and couchbase-opentelemetry/lib/. The Gemfile requires simplecov 1.x, which has the skip filter this uses. - The job fails unless coverage.xml was written and the result set holds both runs. It uploads coverage.xml (Cobertura) and the result set as the "coverage" artifact, and both JUnit reports as junit-coverage. The summary job waits for it. - .github/actionlint.yaml lists ubuntu-26.04, which actionlint does not know yet. - The summary treats a step named "Test <something>" as a test step: a failure there is a test failure, and a job with one must leave a report. A configuration whose job did not succeed is marked even when its report holds no failure. The coverage job counts as a test job, so it gets a row when skipped. - The summary finds reports in subdirectories of a lone report artifact, and an uploaded report that was not downloaded is a report problem. - A test that fails in both coverage runs lists the coverage configuration once. Results ------- Every run of the tests workflow keeps one coverage report of the Ruby code of both gems, across the mock and a cluster. The C++ extension is not measured.
Motivation ---------- The spec reporter prints a test's line when the test ends. When a run hangs, the log shows the tests that finished, but not the one that was running or since when. Modifications ------------- The test reporter prints each test's name and UTC start time when the test starts, and its status and duration on the same line when it ends. The failure summary at the end of the run is unchanged. A CI log keeps a line only once it ends, so a watchdog thread ends the line of a test still running after 60 seconds with "still running after 60s". Results ------- A hung test shows in the log with its start time. A hung run without that line stopped while holding the GVL, where no Ruby thread runs.
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
scripts-*andtests-*artifacts that only its own jobs read.test/**/*.{log,xml}.upload-artifactdoes not expand braces, so the JUnit reports and test logs are never in them.lib/on the load path. They test the Ruby sources, not the packaged gem.${{ }}. The gem versions come fromlib/couchbase/version.rb, which a pull request controls..git/configfor the rest of the job.cbdinoclusteris downloaded without a checksum.Change
Jobs that need scripts or tests check out the commit. Test jobs remove
lib/so every suite loads the installed gem.Test jobs upload their JUnit reports as
junit-<job name>artifacts.The test log prints each test's name and UTC start time when it starts, and its result when it ends. A hung test is the last, unfinished line.
Each
Teststep has its own timeout: 8 minutes in mock jobs, 20 minutes in cluster jobs. A hung test fails its step, so the logs are still uploaded.The test jobs and the
summaryjob have a job timeout above the sum of their step timeouts, so a step times out before its job does.A
summaryjob runs after all others, including on a cancelled run.bin/ci-summary.rbwrites one step summary for the run:The summary annotates the first ten failed tests at the line of the test file where they failed. These annotations replace the
mikepenz/action-junit-reportsteps.A
tests-cleanupworkflow, triggered byworkflow_run, runsbin/ci-cleanup.rb. It deletes each per-Ruby gem once its fat gem exists, and the JUnit reports when the run succeeded. Reports stay after a failure, so "Re-run failed jobs" can still summarize the jobs it skips.workflow_run, GitHub takes the workflow and its checkout from the default branch. Pull request code therefore never runs with itsactions: writetoken. It downloads no artifact from the run it cleans.gh, so no gem is installed next to the token.The
summaryjob, which runs pull request code, has read permissions only.Job outputs reach run scripts through environment variables rather than
${{ }}, and no checkout keeps the token in.git/config.Causes, from the first failed or cancelled step and the job's annotations:
Testfailed and the report has failed testsTestfailed with no failed tests, or with no current reportInstallfailedPrecompile,Build …,Repackageor documentation failedA failed step keeps its cause when a later step times out or the run is cancelled.
The report survives a failed checkout, artifact download, Ruby setup or API outage. Unavailable sections are replaced by a note, and without a report the job results from
needsare written. The summary job fails whenever its report is incomplete.RuboCop also writes its offenses with the
githubformatter, so they appear as annotations.Every action and reusable workflow from another repository is pinned to a commit, commented with the most specific tag or the branch it was resolved from. The Alpine image is pinned to its digest. The nightly FIT runs are the exception.
fit-tests.ymlfollowsfit-cli'scirelease tag, its latest stable release. It is also the channel the nightly installs.bin/check-action-pins.rbruns in linters:uses:not pinned that way, or on a container image without a digest.Pinned actions are updated to their latest releases, including major bumps of
actions/setup-go(v7, instart-cng) andactions/checkout(v7, invalidate-fit-performer).create-clusterverifies the checksum of thecbdinoclusterbinary it downloads, installs it into/usr/local/bin, and writes neitherGITHUB_PATHnorGITHUB_ENV.The linters workflow runs zizmor and fails on findings of medium severity or above. The Bundler cache of the
sourcejob is an accepted finding: GitHub scopes caches by branch, so a pull request cannot write a cache thatmainorrelease*reads.The musl gem is built on the oldest Alpine release with security support, now 3.21. An older musl than the build one may lack symbols the extension uses.
A
coveragejob onubuntu-26.04builds the extension from the checkout and runs the tests withlib/on the load path, against the mock and against a cluster. SimpleCov merges both runs into one Cobertura report oflib/andcouchbase-opentelemetry/lib/, uploaded as thecoverageartifact. The C++ extension is not measured.bin/check-alpine-image.rbruns in linters. It warns when the pinned release is past end of life or is not the oldest supported one. It also warns when its tag points at another image.Known gaps
uses:only. Actions that pinned actions fetch at run time are not covered:sdk-docker-build-actionusesactions/checkout@v6.fit-cli'scirelease, in a job that can assume a cloud role.fit-clifetches its installer from its ownmainbranch.tests-cleanupruns only from the default branch, so this pull request cannot exercise it. After merge it can be run by hand on a run id throughworkflow_dispatch.