TriBITSTriBITS
Docs
Guides
Reference
Pipelines
Downloads
About
Changelog
Docs
Guides
Reference
Pipelines
Downloads
About
Changelog
  • Legacy Documentation

    • Legacy Documentation - TriBITS
    • TriBITS Developers Guide
    • TriBITS Maintainers Guide
    • TriBITS Build Reference

TriBITS Maintainers Guide

This guide is for the people who keep TriBITS-based projects healthy over months and years. If the Developers Guide is about "how do I build and test today," this guide is about "how do I make sure the project is still buildable and testable six months from now."

Maintenance work is less glamorous than feature development. It is also more valuable per hour spent. A well-maintained build system saves every developer on the team time on every commit. A neglected one costs everyone time constantly.

Maintenance workflow showing dependency graph health monitoring and CI stability tracking

Maintaining Package Boundaries

The most important maintenance task is keeping package boundaries clean. Over time, dependencies tend to grow. Developers add a quick include, link against a convenient library, and do not update the dependency declaration. Left unchecked, the dependency graph degrades into a tangle where everything depends on everything.

Signs of Boundary Erosion

  • Packages that cannot be built independently anymore, even though they could a year ago.
  • Circular dependencies appearing in the graph.
  • Build times increasing faster than the amount of code being added.
  • Tests that fail when an unrelated package changes.

Prevention Strategies

Regular dependency graph review. Generate the dependency graph visualization at least monthly. Look for edges that should not be there. Question every new dependency.

cmake -D MyProject_DEPS_DEFAULT_DOT_FILE=deps.dot -B build
dot -Tpng deps.dot -o deps.png

Enforce the direction of dependencies. In most projects, there is a natural layering: utilities at the bottom, domain logic in the middle, applications at the top. Dependencies should flow downward. If a utility package starts depending on domain logic, something is wrong.

Use subpackages to limit scope. If a package is getting too many dependencies, it might be doing too much. Split it into subpackages where each subpackage has a focused dependency set.

Treat dependency additions like API changes. A new dependency is a commitment. It increases coupling and build times. Review new dependencies the way you review API changes: is this really necessary, and is this the right package to depend on?

Dependency Hygiene

Dependency hygiene goes beyond keeping the graph clean. It includes managing external dependencies (TPLs), handling version compatibility, and keeping the build deterministic.

TPL Management

External libraries are the most fragile part of a build system. They change independently, and a new version can break things silently. Recommended practices:

  • Pin TPL versions in CI. Use specific version numbers, not "latest."
  • Document the minimum and maximum supported versions for each TPL.
  • Test with at least two versions (oldest supported and newest supported) in the nightly matrix.
  • When a TPL version is dropped, update the find module and the documentation together.

Removing Unused Dependencies

Dead dependencies slow down builds and confuse developers. Periodically audit the dependency graph against actual usage:

  1. Disable a suspected unused dependency.
  2. Build the package.
  3. If it builds and tests pass, the dependency was dead. Remove it.
  4. If something breaks, re-enable it and investigate whether the usage is intentional.

This is tedious but pays for itself in reduced build times and clearer architecture.

Handling Diamond Dependencies

When package C depends on both A and B, and both A and B depend on a common package D, you have a diamond dependency. This is not inherently a problem, but it becomes one if A and B expect different versions of D or different configurations of D.

TriBITS resolves this naturally when D is an internal package (there is only one version in the project). For TPLs, you need to ensure that the TPL find module works consistently regardless of which package triggers the find.

CI Stability Practices and Flake Handling

A green CI dashboard is a prerequisite for everything else. If CI is unreliable, developers stop trusting it. Once trust is lost, people start merging without waiting for CI, and the main branch degrades.

Flake Management

Flaky tests are tests that fail intermittently without code changes. Every large project has them. The question is how you manage them.

Step 1: Detect. Track test results over time. A test that fails more than 2% of the time without corresponding code changes is flaky.

Step 2: Categorize. Common flake causes:

  • Timing-dependent logic (race conditions, timeouts).
  • Shared state between tests (file system, environment variables).
  • Resource contention (port conflicts, disk space).
  • Platform-specific behavior (floating point precision, sort order).

Step 3: Quarantine. Move confirmed flaky tests to the NIGHTLY category so they do not gate PR merges. Tag them with a tracking issue. Do not just disable them and forget.

Step 4: Fix. Quarantine is not a permanent state. Fix the root cause. Most flakes have deterministic fixes once you understand the cause.

CI Configuration Discipline

  • Pin compiler versions in CI. Do not use "latest" for compilers. A compiler update should be a deliberate event, not a surprise.
  • Pin TPL versions. Same reason.
  • Use clean builds for nightly. Incremental builds in CI can mask problems. Run at least one full clean build per day.
  • Monitor CI resource usage. Slow CI often means the build outgrew the CI machines. Address it before it becomes critical.

Managing CI Across Repositories

For multi-repo projects, CI stability requires that all repos are tested together. A change that passes CI in one repo but breaks the superbuild is worse than a change that fails immediately, because the breakage is discovered later and is harder to bisect.

Use Git branch protection and require that the superbuild CI passes before merging into any repo's main branch.

Versioning Patterns

Versioning in a TriBITS project operates at multiple levels: the project version, individual package versions, and framework compatibility.

Project Versioning

The project version is set in the top-level CMake configuration. Use semantic versioning or a date-based scheme consistently. The key is that the version number is meaningful and documented:

  • What changes constitute a major version bump?
  • What is the compatibility promise between minor versions?
  • How do version numbers map to Git tags?

Document these decisions. The worst versioning scheme is the undocumented one.

Package Versioning

Individual packages can have their own version numbers, but this adds complexity. In projects where all packages are released together, a single project version is simpler. In projects where packages are released independently, per-package versioning is necessary but requires tooling to track compatibility.

Compatibility Tracking

Keep a compatibility matrix that shows which package versions work together. This is especially important for multi-repo projects where repos may be at different versions. The matrix does not need to be exhaustive, but it should cover the combinations that are actually tested in CI.

Release Checklist

Releases are stressful when improvised. They are routine when checklisted. Here is a starting point:

Pre-Release

  1. All CI pipelines green on the release branch.
  2. NIGHTLY and HEAVY tests passing.
  3. Dependency versions pinned and documented.
  4. Changelog updated with user-visible changes.
  5. Documentation reflects the current state of the code.
  6. No known critical bugs open.

Release Build

  1. Tag the release in version control.
  2. Build from a clean checkout of the tag. Do not use an existing build directory.
  3. Run the full test suite (including HEAVY tests).
  4. Build and verify the install target.
  5. Verify that downstream consumers can find and use the installed packages.

Post-Release

  1. Announce the release through appropriate channels.
  2. Update the compatibility matrix if applicable.
  3. Create the next development branch or increment the version for ongoing work.
  4. Review and close resolved issues.

Documentation Conventions and Review Discipline

Documentation is a maintenance task. Code without documentation is a future support burden. Documentation without review is a reliability risk.

What to Document

  • Every package should have a README or a top-level comment explaining what it does and why it exists.
  • Public APIs should have comments that explain usage, not just signatures.
  • Dependency changes should be documented in commit messages.
  • Build configuration options should be documented in a central reference.

Review Standards

  • Documentation changes should be reviewed like code changes.
  • Check for accuracy. Out-of-date documentation is worse than no documentation because it misleads.
  • Check for completeness. If a new macro is added, its documentation should be added in the same commit.

Keeping Documentation Current

Link documentation to the code it describes. If a macro signature changes, the documentation should be updated in the same commit. Treat "update docs" as part of "done."

Release checklist workflow showing pre-release, build, and post-release stages

FAQ

Q: How often should I review the dependency graph? A: At least monthly for active projects. Set a calendar reminder. It takes 15 minutes and saves hours of debugging dependency problems later.

Q: Should I fix flaky tests or quarantine them? A: Both. Quarantine immediately so they do not block other developers. Fix within the next sprint. If a flaky test stays quarantined for more than two months, escalate it.

Q: How do I handle a package that wants to depend on everything? A: This usually means the package is doing too much. Break it into smaller packages with focused responsibilities. If that is not practical, use subpackages to limit the dependency scope of each component.

Q: When should I bump the major version? A: When you break backward compatibility for downstream consumers. This includes removing packages, changing public APIs in incompatible ways, or changing the minimum required version of a TPL in a way that forces consumers to upgrade.

Q: How do I onboard a new maintainer? A: Have them do a release. Nothing teaches the build system faster than going through the release checklist with real code and real deadlines. Pair with them the first time.

Q: What is the most common maintenance mistake? A: Letting CI stay red for "just a day or two." It never stays red for just a day. Fix it immediately or revert the breaking change. A red CI normalizes ignoring test failures, and that is how projects lose quality.

Prev
TriBITS Developers Guide
Next
TriBITS Build Reference