Skip to content

Design to Be Built (formerly: CI)

Chapter Info

Calculating... Writing Progress: 50%

Every code change must eventually answer the same question: can this version be trusted enough to move forward? A good build system turns that question into a repeatable process. It takes a specific change, validates it, builds the software, runs the necessary checks, packages the result, and produces an artifact that can be traced and promoted with confidence.

alt text

Build Fundamentals [Fundamentals]

A reliable build moves every change along a trusted path to production: integrate frequently, validate automatically, produce reproducible results, and return feedback quickly. The following principles establish those foundations.

The Path to Production [Path to Production]

The path to production is the controlled route that takes a code change from source to a deployable artifact and eventually to production. Every production-bound change should follow the same trusted path, with each step adding evidence that the change is safe to progress.

alt text

Integrate Continuously [Integrate]

Continuous Integration originally meant exactly what its name says: integrating changes continuously. Developers merge small changes into shared code frequently instead of allowing branches to diverge for long periods. Frequent integration exposes conflicts and incompatibilities while changes are still small and easy to understand. For historical reasons, the term Continuous Integration is now commonly used more broadly to include the automated build, testing, and validation that accompany each change.

alt text

Automate Every Change [Automation]

Every change should automatically trigger the build and its essential checks. Developers should not have to remember when or how to validate their code. Automation ensures that every change goes through the same process and receives consistent feedback.

alt text

Automate Routine Decisions [Routine Decisions]

Routine build decisions should be made automatically whenever the required rules can be expressed clearly. Human approval should be reserved for decisions that genuinely require judgment, not inserted into every integration as a default checkpoint. Automation keeps the feedback loop moving while leaving people responsible for the decisions machines cannot make.

alt text

Build Reproducibly [Reproducibility]

A build should depend only on explicit, controlled inputs: source code, declared dependencies, tools, and configuration. The same inputs should produce the same result every time, regardless of where the build runs. Hidden dependencies on local files, machine state, network resources, or previous builds make results unpredictable and difficult to reproduce. When every input is known and controlled, failures are easier to diagnose and artifacts can be rebuilt with confidence.

alt text

Build Once, Deploy Anywhere [Build Once]

Build an artifact once, then promote that exact artifact through testing, staging, and production. Rebuilding for each environment introduces differences between what was tested and what is eventually deployed. Environment-specific configuration should be supplied at deployment time, not baked into separate builds. Containers, popularized by Docker, made this model practical by packaging the application with its runtime and dependencies into a portable artifact that can move consistently across environments.

alt text

Every artifact should retain an unbroken link to the exact source revision and build that produced it. The source commit SHA, build record, and artifact identity form a chain that makes it possible to understand exactly what is running, reproduce a version, investigate failures, and roll back with confidence.

alt text

Validate Every Change [Automated Validation]

Compilation only proves that code can be built. Every change should automatically collect enough evidence to show that it is safe to integrate. Tests, static analysis, security checks, and other validations answer different questions about the change and should run before it progresses.

alt text

Detect Early, Fail Fast [Fail Fast]

Design the build to detect failures as early as possible. Order checks so that fast, high-signal validations run first and problems are discovered before expensive work begins. Once a blocking failure is known, stop immediately: continuing cannot change the outcome and only wastes time and compute. Early detection also gives developers feedback while the context of their change is still fresh.

alt text

Keep Feedback Fast [Fast Feedback]

The build must return useful results quickly enough for developers to remain in the context of their change. Feedback should be clear and specific, showing what failed and why so the problem can be fixed quickly. Fast, actionable feedback encourages small integrations and rapid correction; slow, vague, or unreliable feedback encourages batching and workarounds.

alt text

Never Bypass the Path to Production [Never Bypass]

Every production change should travel through the same trusted path to production. That path creates the evidence that makes an artifact trustworthy: builds, tests, security checks, and other required validations. Manual builds or alternative routes bypass those guarantees. Experimentation can use lighter workflows, but anything intended for production must eventually return to the trusted path.

alt text

Keep the Path to Production Green [Mainline Green]

The path to production must remain healthy and trustworthy so changes can continue moving forward. A failure anywhere on that path can block builds, integrations, and delivery for the entire team. It also makes every result less trustworthy: developers can no longer know whether a failure comes from their own change or from an already broken system. When the path breaks, restoring it becomes the priority: fix the problem quickly or revert the offending change before normal work continues.

alt text

Make Health Visible [Build Health]

The health of master and proposed changes should be immediately visible to everyone. Build failures, blocked validations, and other signals that make a revision unsafe should be difficult to miss. Visibility turns build health into a shared responsibility and prevents failure from becoming accepted background noise.

alt text

The Build Process [Build Process]

To see how these principles work in practice, follow a single change through the build. A specific source revision triggers an isolated execution, passes through a sequence of checks, and becomes a validated, identifiable artifact ready for deployment.

Build Triggers [Trigger]

A build trigger is the event that starts a build execution. A push, pull request, merge, tag, or explicit request can initiate different build workflows depending on what needs to be validated or produced.

alt text

Run in a Clean Environment [Clean Environment]

A build runs on compute infrastructure commonly called a runner or agent. Each execution should start from a clean, predictable environment with the required operating system and tools. Ephemeral runners or containers prevent uncontrolled machine state, globally installed dependencies, or leftovers from previous builds from affecting the result.

alt text

Build Stages [Build Stages]

A build is organized as a sequence of stages, each adding evidence about the change. A typical flow is checkout → validate → build → test → package → artifact test → publish. The exact stages vary by system. The sections that follow walk through this flow from a specific source revision to a validated artifact.

alt text

Checkout the Exact Change [Exact Change]

The build first retrieves the exact source revision it is expected to validate. Identifying the source by commit SHA makes every build traceable and prevents later repository changes from silently changing what is being tested.

alt text

Run Cheap Checks First [Validate Early]

Order build checks so that inexpensive, high-signal validation runs before costly work. Linters, configuration validation, and static analysis can reject many problems before compilation, packaging, or integration testing begins. This reduces both feedback time and wasted compute.

alt text

Build the Software [Build Software]

The build transforms source code into the form needed for execution or packaging. Depending on the technology, this may mean compiling binaries, generating bytecode, transpiling code, or creating application bundles. This stage also verifies that the source and its declared dependencies can be assembled successfully.

alt text

Run Fast Tests [Fast Tests]

Fast automated tests verify behavior before an artifact progresses further through the build. Unit tests usually form the first testing layer because they are quick, isolated, and provide precise feedback when a change breaks existing behavior. A blocking failure should stop later stages immediately.

alt text

Package the Artifact [Package Artifact]

Once the software has been built and its fast checks have passed, package it into an immutable artifact, such as a binary, archive, or container image. From this point on, the artifact becomes the unit being validated and promoted. Later tests, staging, and deployment should all use this exact artifact rather than rebuilding the source.

alt text

Test the Packaged Artifact [Artifact Tests]

Some problems appear only when the packaged application interacts with real dependencies. Integration tests can start the artifact alongside databases, queues, or other services and verify that those interactions work correctly. Testing the packaged artifact increases confidence that the same unit can later be deployed.

alt text

Publish the Validated Artifact [Publish Artifact]

Once the required checks have passed, the artifact is published to a repository or registry where deployment systems can retrieve it. Publishing should preserve its immutable identity and its link to the source commit and validation results. The build is now complete: source code has become a traceable, validated artifact ready for deployment.

alt text

How AI Changes the Build Process [AI Build Process]

AI does not replace the build process. It changes the speed and scale at which work enters it. Code, tests, configuration, and infrastructure changes can now be generated in seconds, but every change must still earn trust through the same path from source to validated artifact.

AI Increases the Flow of Changes [AI Change Rate]

AI agents can generate code, tests, configuration, and infrastructure changes far faster than developers could produce them manually. The build therefore receives a much larger and more continuous stream of proposed changes. CI can no longer be designed around human coding speed; it must be able to absorb, filter, and validate changes at machine-generated volume.

alt text

Validation Becomes the Bottleneck [AI Build Throughput]

As generating changes becomes cheap and fast, validation becomes the limiting factor. The challenge shifts from producing more code to deciding quickly which changes deserve to progress. Build throughput, parallelism, prioritization, caching, and early high-signal checks become critical. The capacity to generate code matters little if trusted changes cannot move through validation at the same pace.

alt text

Review Shifts Toward Intent [AI Review]

As AI becomes better at producing syntactically correct implementations, reviewing the mechanics of every change becomes less central. Human review shifts toward intent, architecture, risk, and whether the proposed change is the right solution to the right problem.

alt text

The Build Establishes Trust [AI Validation]

When producing plausible code becomes cheap, authorship itself provides little evidence that a change is safe. Trust must come from independent evidence produced by the build: reproducibility, tests, security checks, contract validation, and traceable artifacts. Whether a change was written by a person or an agent, it should earn trust through the same path.

alt text

Testing Shifts from Writing to Defining [AI Testing]

AI can generate far more tests than humans can reasonably write or review. The harder problem becomes defining which behaviors matter, which risks deserve attention, and what evidence is sufficient to let a change progress. Test strategy therefore shifts from producing test code to defining the rules, properties, boundaries, and failure modes that the generated tests must protect.

alt text

Agents Close the Feedback Loop [AI Feedback Loop]

AI agents can read build failures, modify the change, and try again without waiting for a developer to perform each iteration. This makes build feedback an API for both humans and machines. Failures should therefore be structured, specific, and actionable enough for an agent to understand what failed, why it failed, and how to correct it without bypassing the trusted path to production.

alt text

Keeping Master Clean [Keeping Master Clean]

Master is the shared integration point for ongoing development. When it breaks, it can block the entire path to production and prevent everyone else from moving forward. How do we keep master clean without turning it into an obstacle to development?

alt text

What Makes Master Healthy [Broken Master]

A healthy master is one for which the available evidence still supports trust. A successful build establishes that trust initially, but later evidence can invalidate it: an asynchronous test may fail, an integration environment may expose a problem, or a vulnerability may be discovered. Master health therefore extends beyond the moment the build turns green. When new evidence makes a revision unsafe, master should be treated as broken until trust is restored.

alt text

Provide a Safe Space for Experimentation [Safe Experimentation]

Developers need a safe way to build, deploy, and validate unfinished changes without putting master at risk. A separate experimentation environment lets them test freely without using the path to production as their testing ground. Providing this space removes one of the root causes of a broken master.

alt text

Protect Master from Unvalidated Changes [Protect Main]

Once developers have a safe place to experiment, master should accept only changes that have passed the required validation. Branch protection can enforce successful builds, automated checks, and review before merge. Master should never become the place where a change is tested for the first time.

alt text

Review Before Changes Reach Master [Code Review]

Automated checks can verify many properties of a change, but they cannot fully judge intent, design, or maintainability. Code review adds human judgment before a change reaches master. Reviews are most effective when changes are small and automation has already handled what machines can verify.

alt text

Keep Changes Small [Small Changes]

When many changes land together, a broken master becomes difficult to diagnose. The failure may come from several changes, ownership becomes unclear, and recovery can turn into a long investigation. Small changes make problems easier to identify, understand, fix, or revert. The smaller the change, the faster master can return to green.

alt text

Keep Isolation Short [Branching]

Every branch creates temporary isolation from master. The longer that isolation lasts, the more both sides can change independently and the harder reintegration becomes. Keep branches short-lived so divergence is discovered and resolved while it is still small.

alt text

Integrate Small Changes Frequently [Trunk Based]

Trunk-based development combines these ideas: keep changes small and keep isolation short. Developers integrate directly into master or through very short-lived branches, exposing incompatibilities early. Feature flags allow unfinished functionality to remain hidden without keeping the code isolated.

alt text

Validate Against Master Before Merge [Merge Validation]

A pull request can pass all of its checks and still break master when merged. Master may have changed since the pull request was validated, and the merged state may trigger validations that do not run on the pull request itself. Before merge, validate the change against the master state it will actually join. The goal is to test the future merged state, not only the change in isolation. Merge queues can automate this validation in the expected merge order.

alt text

Limit the Blast Radius of Build Failures [Failure Isolation]

A failure should block only the parts of the system that depend on it. Define build boundaries so unrelated components and teams can continue moving when one part fails. Separate pipelines, independent artifacts, and dependency-aware builds can isolate failures whether the code lives in one repository or many.

alt text

Restore Master Immediately [Restore Mainline]

Prevention will never eliminate every failure. When master breaks, restoring it becomes the priority: fix the cause immediately or revert the offending change before normal work continues. A broken master should be a short-lived exception, never a state the team learns to work around.

alt text

Quality in the Build [Quality]

A build should collect enough evidence to decide whether a change is safe to progress. Different checks answer different questions, so the goal is not to run everything everywhere, but to combine fast feedback with deeper validation where it matters.

Match Tests to the Risk [Match Tests]

Different tests provide different kinds of confidence. Fast unit tests check individual components, integration tests verify that components work together, and end-to-end tests validate critical user flows. Choose each type according to the risk being addressed, the confidence it provides, and the cost of running it.

alt text

Test in a Credible Environment [Production-Like Tests]

Test results are only useful when the environment is credible enough for the claim being made. Fast checks can run in isolated environments, while integration tests should exercise the packaged application with realistic dependencies, configuration, and network behavior. The goal is not to reproduce production exactly, but to avoid confidence based on conditions that are too artificial.

alt text

Keep Tests Independent [Independent Tests]

Tests should not depend on the order in which they run or on state left behind by other tests. Each test should create the conditions it needs and clean up after itself. Independent tests can run in parallel, fail for understandable reasons, and produce results that remain trustworthy as the suite grows.

alt text

Keep Tests Trustworthy [Trustworthy Tests]

A test that sometimes passes and sometimes fails without a code change makes the entire build less trustworthy. Flaky tests should be identified, isolated, and fixed rather than accepted as normal noise. Developers must be able to assume that a failed check represents a real problem.

alt text

Use Coverage as a Signal [Coverage Signal]

Coverage shows which code was exercised by tests, but it does not prove that the right behavior was verified. Use coverage as a signal, especially on new or modified code, rather than as a target to maximize blindly. A healthy policy encourages meaningful tests without rewarding tests that merely execute lines.

alt text

Protect Service Boundaries with Contract Tests [Contract Tests]

In distributed systems, a change can break another service even when both services work correctly in isolation. Contract tests verify that providers and consumers still agree on the shape and behavior of their interface. They catch incompatible API changes early without requiring a full end-to-end environment.

alt text

Turn Quality Rules into Gates [Quality Gates]

Some checks should prevent a change from progressing, while others are better treated as warnings. Quality gates turn the most important rules into automated go/no-go decisions without blocking delivery on every imperfect signal. Gates should be few, understandable, and reserved for failures that genuinely make progression unsafe.

alt text

Security in the Build [Security]

Security checks should provide reliable evidence that a change is safe to progress. The build can inspect code, dependencies, and artifacts automatically, while its own inputs and credentials must remain controlled.

Treat the Build as a Security Checkpoint [Security Checkpoint]

The build is a security boundary between a proposed change and a trusted artifact. Security checks should run automatically before unsafe code, dependencies, or configuration can progress. This makes security part of the same evidence used to decide whether a change is safe to move forward, rather than a separate review performed at the end.

alt text

Secure Who Can Change Code [Code Access Control]

Security starts before the build runs: only authorized people and systems should be able to change the code that enters it. Repository access should follow least privilege, sensitive areas can require approval from designated owners, and strong authentication should protect write access. The goal is to control who can introduce a change before the build begins deciding whether that change can be trusted.

alt text

Safe Collaboration with External Contributors [External Contributors]

External contributions introduce untrusted code into the build process and therefore require a stronger boundary. Fork-based workflows can let contributors propose changes without write access to the repository, while their builds run with restricted permissions and without access to secrets or protected resources. Collaboration remains open without giving untrusted code the privileges of an internal build.

alt text

Detect Secrets Before They Spread [Secret Scanning]

Credentials, API keys, private keys, and other secrets should never become part of source history or build artifacts. Automated secret scanning should detect them as early as possible and block unsafe changes. Once a secret has entered version control, it should be treated as exposed and rotated rather than simply removed from the latest commit.

alt text

Control Third-Party Dependencies [Third-Party Dependencies]

Third-party libraries and packages are part of the build input and must be controlled like your own code. Scan dependencies for known vulnerabilities, pin the versions being consumed, and retrieve them through trusted sources whenever possible. A reproducible and trustworthy build requires knowing not only which dependencies it uses, but exactly where they came from and which versions entered the artifact.

alt text

Analyze Code for Security Flaws [Code Analysis]

Static security analysis examines source code without executing it and can detect classes of vulnerabilities such as injection flaws, unsafe APIs, and insecure cryptography. These checks are useful early in the build, but they must be tuned carefully: noisy rules and false positives quickly become ignored. Blocking policies should focus on findings that represent meaningful risk.

alt text

Test Runtime Security [Runtime Security]

Static analysis cannot detect every security problem. Dynamic security testing exercises the running application to uncover vulnerabilities that appear only at runtime, such as authentication failures, unsafe configuration, or unexpected input handling. Because these checks are usually slower, they can run later in the pipeline while remaining linked to the exact artifact being validated.

alt text

Give the Build Only the Access It Needs [Build Permissions]

Build runners and service accounts often have access to source code, secrets, registries, and cloud resources, making them valuable attack targets. Apply least privilege: each job should receive only the permissions and credentials it needs, for only as long as it needs them. A compromised build step should not automatically provide access to the rest of the infrastructure.

alt text

Protect Artifact Integrity [Artifact Integrity]

Once an artifact has passed the build, consumers must be able to verify that it is still the exact artifact that was approved and that it has not been modified afterward. A cryptographic digest identifies the artifact content, while a digital signature binds that digest to a trusted signing identity. Deployment systems should verify both before running the artifact, preserving integrity and provenance from build to production.

alt text

Protect the Software Supply Chain [Software Supply Chain]

Security checks protect the build from unsafe inputs, but the build itself must also be protected. Its tools, dependencies, runners, credentials, and outputs form part of the software supply chain and should be controlled and auditable. If the build infrastructure is compromised, even correctly written source code can produce an untrusted artifact.

alt text

Artifact Management [Artifacts]

Artifact management keeps validated build outputs available, identifiable, and trustworthy after the build completes. It provides the repository, identity, metadata, and retention policies that let deployment systems retrieve the right artifact with confidence.

Build Outputs Take Different Forms [Artifact Forms]

A build artifact is an immutable output produced and validated for later use. It may be a binary, container image, infrastructure package, machine image, deployment chart, or configuration bundle. Whatever its form, it becomes an identifiable unit that can be stored, traced, promoted, and consumed without being rebuilt.

alt text

Store Artifacts in a Repository [Artifact Repository]

Validated build outputs should be stored in a dedicated artifact repository or registry rather than left on build machines or mixed with source code. A central repository gives deployment systems a stable place to retrieve approved artifacts and provides consistent access control, retention, and auditability.

alt text

Give Every Artifact an Immutable Identity [Immutable Identity]

Every artifact needs an immutable identity so teams can know exactly what was tested, deployed, or rolled back. A release version such as 1.4.2 identifies a logical release; a build identifier distinguishes a particular build; a cryptographic digest identifies the exact artifact content. These identifiers serve different purposes. An identifier that is meant to identify immutable content must never be reassigned to different content. Together they provide human-readable versioning and precise machine-verifiable identity.

alt text

Keep Artifact Metadata and Provenance [Artifact Provenance]

An artifact should preserve enough metadata to explain where it came from and what evidence allowed it to progress. This typically includes the source revision, build identifier, creation time, and relevant test and security results. Provenance connects the final artifact back to the process that established its trust, making troubleshooting, auditing, and deployment decisions much easier.

alt text

Define Artifact Retention [Artifact Retention]

Artifact repositories grow continuously, so retention must be intentional. Keep artifacts as long as they are needed for production rollback, audit, compliance, or active development, and remove obsolete outputs automatically. Retention policies should reflect operational needs rather than fixed time periods applied uniformly to every artifact.

alt text

The Platform Role [Platform Role]

A build platform should remove infrastructure complexity from application teams while preserving the standards needed for security, reliability, and consistency. Its role is to provide a paved path: easy defaults for common cases, enough flexibility for exceptional needs, and shared capabilities that teams should not have to rebuild themselves.

Choose the Right Build Infrastructure [Build Infrastructure]

Build infrastructure can be provided as a managed service, operated internally, or combine both approaches. Managed platforms reduce operational burden and scale easily, while self-hosted runners provide greater control over networking, hardware, security, and compliance. The right model depends on workload requirements; the platform should hide most of that choice from developers whenever possible.

alt text

Provide a Paved Path [Paved Path]

The common path should require very little configuration. Reusable templates, sensible defaults, and built-in quality and security controls let teams start with a reliable build without designing a pipeline from scratch. Developers should customize the build only when their application genuinely requires something different.

alt text

Keep Build Configuration as Code [Build Configuration]

Build configuration should live in version control alongside the software it builds. Changes then become reviewable, traceable, and reversible like any other code change. Avoid critical build behavior that exists only as mutable configuration in a web interface, where its history and intent are difficult to understand.

alt text

Enable Self-Service with Guardrails [Self-Service]

Developers should be able to modify and extend their own build configuration without depending on a platform team for every change. The platform should provide reusable templates, policies, and safe defaults, while application teams remain free to adapt the build to their needs. Self-service scales ownership without giving up consistency or security.

alt text

Build Platforms Become Agent Platforms [Agent Platforms]

Build platforms were designed primarily for developers and automation scripts. AI agents now become another class of user, requiring programmable interfaces, structured feedback, scoped permissions, and strong guardrails. Agents should be able to inspect failures, trigger work, and iterate autonomously without gaining a way around the trusted path to production.

alt text

Build Performance [Performance]

Fast builds preserve the feedback loop that continuous integration depends on. Performance should be measured by how quickly developers receive useful feedback, not simply by how quickly every build task finishes. As the build grows, optimize the work that lies on that critical feedback path.

Optimize the Critical Path [Critical Path]

Build performance is determined by the work that blocks useful feedback. Measure the critical path, identify the slowest stages, and optimize the parts that developers must wait for first. Faster non-blocking work is useful, but reducing the blocking path has the greatest impact on developer flow.

alt text

Run Independent Work in Parallel [Parallel Work]

Build stages that do not depend on each other should run concurrently rather than sequentially. Tests, static analysis, packaging steps, and configuration checks can often execute in parallel, reducing elapsed time without removing validation. Parallelism should be applied where it shortens the critical path without creating excessive cost or complexity.

alt text

Defer Expensive Checks Without Losing Control [Async Testing]

Some valuable checks are too slow to block every change. Long-running end-to-end, performance, or external-system tests can run asynchronously against the exact artifact produced by the build. They should not delay fast developer feedback, but they must still be able to prevent that artifact from reaching production if a serious problem is found.

alt text

Reuse Work Safely with Caching [Caching]

Caching avoids repeating work whose inputs have not changed, such as downloading dependencies, rebuilding unchanged components, or rerunning tests whose relevant inputs are identical. Cache keys should be derived from all inputs that can affect the cached result so stale results are invalidated automatically. A cache is an optimization, never a hidden dependency: clearing it should make the build slower, not change whether it succeeds.

alt text

Test Only the Configurations That Matter [Build Matrix]

Some software must be validated across multiple operating systems, language versions, architectures, or dependency combinations. A build matrix makes these variations explicit and allows them to run in parallel, but every additional combination increases cost and feedback time. Test the configurations that represent real compatibility requirements rather than every theoretical combination.

alt text

Developer Experience [DX]

Developer experience determines whether developers trust and embrace the build or try to work around it. A good build stays out of the way when things work, provides clear guidance when they do not, and makes common development workflows simple and predictable.

Make the Build Disappear into the Workflow [Workflow]

A good build should require as little attention as possible when everything works. Developers should be able to commit, receive feedback, and continue working without thinking about build infrastructure. The build becomes visible only when it has useful information to provide.

alt text

Make Failures Actionable [Actionable Failures]

When a build fails, the developer should quickly understand what failed, why it failed, and where to look next. Error messages should identify the failing check, provide relevant context, and link to the information needed to investigate. A failure that requires searching through thousands of log lines is a build-system usability problem.

alt text

Let Developers Reproduce Checks Locally [Local Checks]

Developers should be able to run the important build checks before pushing a change. Local execution does not need to reproduce the entire build infrastructure, but the same commands, dependencies, and validation rules should behave consistently. This shortens feedback loops and makes build failures easier to reproduce.

alt text

Keep the Build Easy to Understand [Understandable Build]

Developers should be able to understand what the build does without becoming experts in the build platform. Prefer a small number of clear stages, sensible defaults, and conventions over large amounts of custom configuration. Complexity that is unavoidable should be hidden behind reusable platform capabilities rather than repeated in every project.

alt text

Send Feedback to the Right People [Feedback Routing]

Build notifications should reach the people who can act on them without creating background noise. A pull-request failure usually belongs to its author, while a broken main branch concerns the team. Notifications should include enough context to act immediately and should avoid broadcasting routine failures to people who cannot help.

alt text

Metrics and Observability [Metrics & Observability]

Build observability makes the build itself measurable. It should reveal where developers wait, why builds fail, and whether the build system is becoming slower or less reliable over time.

Measure Time to Feedback [Time to Feedback]

Measure how long developers wait for useful feedback, not only how long the entire pipeline takes. Separate queue time from execution time and break execution down by stage to reveal where delays originate. Percentiles and trends are often more useful than averages because they reveal the slow experiences that developers actually feel.

alt text

Separate Build Failures from Infrastructure Failures [Failure Causes]

A failed build does not necessarily mean the build system is unhealthy: rejecting a broken change is exactly what it should do. Distinguish failures caused by the change from flaky tests, runner failures, network problems, and other infrastructure issues. This separation shows whether developers can trust the build itself.

alt text

Measure Build-System Reliability [Build Reliability]

Developers need predictable feedback from the build infrastructure itself. Track runner failures, unexpected retries, network errors, service outages, and other cases where the pipeline fails independently of the code change. A reliable build platform should produce the same outcome for the same inputs without requiring developers to retry failed jobs.

alt text

Individual measurements show what is happening now; trends reveal whether the build is getting better or worse. Track feedback time, queue time, infrastructure failures, and reliability over time so gradual regressions become visible early. When a metric changes, observability should help identify where the regression originated.

alt text

Human Judgment in the Age of AI [Human & AI]

AI does not remove the principles described in this chapter. It increases their importance. Changes arrive faster, validation becomes the bottleneck, human judgment moves toward intent and risk, and the build platform increasingly serves both developers and autonomous agents.

Humans Define the Intent [AI Human Judgment]

AI can generate implementations, tests, fixes, and configuration, but it cannot decide what the system should ultimately achieve. Humans remain responsible for defining intent, constraints, acceptable risk, and the evidence required before a change can progress.

alt text

AI Explores the How [AI Generation]

Once the intent and constraints are clear, AI can explore many possible implementations quickly: generating code, tests, refactorings, and fixes, then using build feedback to improve them. The value shifts from producing one answer to searching a much larger solution space.

alt text

Generate More, Trust Through Evidence [AI Trust]

As generating changes becomes cheaper, generation itself becomes less meaningful as evidence of quality. Trust must come from the build: reproducible execution, review, testing, security checks, and traceable artifacts. AI can increase the volume of change, but every change must still earn the right to progress.

alt text

From Change to Trusted Artifact [Conclusion]

A reliable build turns an untrusted change into a trusted artifact. It does this by controlling inputs, validating behavior and security, preserving traceability, and producing one immutable output that can move safely toward production. The tools will evolve, but this responsibility remains the same: every change must earn the evidence required to move forward.