I found a problem with a deployment gate before it caused an incident, while documenting the path from a Markdown change to Kubernetes.
At the component level, the process looked clear. A pipeline validates and builds the documentation, publishes a container image, and Flux applies the new state to Kubernetes.
But this model lists the participants and says almost nothing about the connections between them. It does not explain when the change becomes available to Flux, whether GitOps CI must finish first, or what blocks further deployment after a failure.
Those shortcuts were not enough for a public article. I had to reconstruct the actual order of events, define the responsibility of each stage, and verify the important transitions between components.
This exposed a missing dependency in the system.
A compressed model hides dependencies
A team can use a short description of a system for a long time. Its members know the purpose of the repositories, pipelines, and individual jobs, so they fill in the missing context themselves.
The phrase “CI builds, Flux deploys” is useful for quickly naming the roles of the components. But it does not show who selects an image version for the environment, where the deployment decision is recorded, or whether Flux can receive a change before validation has finished.
The problem begins when a compressed diagram is treated as a complete model of the process.
Internal context hides the gaps. People supplement the description with what they already know or assume. Two consecutive items in a diagram can therefore look connected even when no technical dependency exists between them.
An external reader does not have that context. When a transition is not explained, the author must either reconstruct it or admit that the system has not yet been described precisely enough.
Every arrow needs a cause
The documentation delivery path can be represented like this:
Markdown
→ pipeline
→ container image
→ GitOps repository
→ Flux
→ Kubernetes
This is enough for an overview. Testing the solution requires examining every arrow.
What initiates the transition? What state changes? What must finish before the next stage can begin? What happens after a failure? What observable fact confirms success?
While these answers remain implicit, the diagram shows the expected result rather than the actual system.
During the preparation of “How CI/CD and Flux Split Responsibilities in My DocOps Project”, this analysis helped clarify the process boundaries. The pipeline did more than build a container image. It also selected an image version for the environment. Flux received the desired state that had already been recorded and applied it to Kubernetes.
That finding matters not only as a description of CI/CD. It showed that a list of component roles had to be replaced with an ordered sequence of events.
How the explanation exposed a missing dependency
Further analysis showed that the pipeline pushed its change directly to the main branch of the GitOps repository. Flux watched the same branch.
One commit started GitOps CI and became available to Flux at the same time:
push to the main branch
├── starts GitOps CI
└── becomes available to Flux
The presence of CI created the impression of validation before deployment. In reality, the pipeline result did not determine whether Flux could receive the new revision.
The key question was simple:
What prevents Flux from receiving the change before CI finishes successfully?
Nothing did. The checks might finish first during most runs, but speed does not create a causal dependency.
The process was changed:
before:
push to the main branch → CI and Flux independently
after:
temporary branch → CI → merge → Flux
Automation started creating a temporary branch and a Merge Request. A new revision appeared in the watched branch only after a successful pipeline.
The implementation and limitations of this design are covered separately in “Why CI in a GitOps Repository Is Not a Deployment Gate”.
The important result here is different. The problem became visible not because of a failure, but because the causal relationship between the stages had to be explained.
Removing internal names tests the model
An internal description can refer to specific projects, jobs, and file names. Team members know what they mean and fill in the missing information.
A public article has to replace internal names with roles: source repository, GitOps repository, build pipeline, watched branch, and reconciliation controller.
This separation removes accidental implementation names from the model of the solution.
If the process becomes impossible to explain after the internal identifiers are removed, the description depended on knowledge of the environment. It was not a self-contained model.
The phrase “automation handles the rest” may be understandable inside a team, but it says little to an external reader. It does not identify which component performs the action, what state it changes, or where it passes the result.
Public writing forces these shortcuts to be replaced with a concrete sequence.
Guarantees must be limited
In a working discussion, a solution is often described through its main scenario. A public article requires a more precise definition of what the solution actually guarantees.
For example, the implemented deployment gate guarantees the order in which a change is published. It does not prove that the checks are complete or that the application was deployed successfully.
These are different properties:
the change passed the defined checks
≠
the checks detect every possible error
≠
the change works successfully in the environment
Without this distinction, a reader can assign properties to the solution that it does not have.
The requirement to state the boundaries precisely is also useful to the author. It separates verified facts from expected behavior and organizational agreements.
The phrase “the solution works” almost always needs a continuation: for which scenario, under which permissions, at which stage, and according to which observable signal.
A coherent explanation is not proof
A coherent description can still be wrong. An author can explain an assumed architecture in detail without comparing it with the configuration and actual system behavior.
Writing therefore has to be combined with technical verification.
Pipelines must be read. Branch settings and job conditions must be checked. The expected order must be compared with observed events.
When an article says that an action occurs after validation, the implementation must contain the corresponding dependency. It is not enough for one process to usually finish faster than another.
A public article does not replace an architecture review or testing. It shows which statements still lack evidence.
Passages that cannot be written without words such as “usually,” “should,” and “after that” are particularly useful. They do not necessarily contain an error, but they need separate verification.
A draft can serve as an architecture review
A solution can be tested through explanation before the work is complete. The text does not have to be polished or ready for publication.
A self-contained draft is enough if an external engineer can use it to reconstruct the process without verbal clarification.
The review should answer several questions:
- What state exists before the process begins
- What event starts each stage
- Which component changes the state
- What prevents the next stage from starting too early
- What happens after a failure, conflict, or repeated run
- What observable fact confirms success
- What that fact does not confirm
This analysis is especially useful at boundaries between systems.
In CI/CD, GitOps, and other asynchronous automation, one event can start several independent processes. Their order cannot be inferred from average duration or a polling interval.
The word “after” must represent a technical dependency. A successful result may unlock the next stage, or a change may appear in the watched branch only after validation.
If two actions merely begin at roughly the same time, there is no guaranteed order between them.
Publication is not required
The same gaps can be found during an architecture review or while preparing an ADR, a runbook, or internal documentation.
A public format has no unique technical property. Its value comes from the fact that an external reader does not know the history of the system and cannot reconstruct missing connections from team context.
Public writing therefore places stricter requirements on a self-contained explanation. It forces the author to remove internal shortcuts, separate facts from assumptions, and state limitations explicitly.
The verification comes not from publication itself, but from the way the material is prepared:
sequential explanation
→ comparison with the implementation
→ verification of causal relationships
→ limitation of the stated guarantees
Publication provides an additional reason to do this work, but it does not replace it.
Conclusion
A public article does not make a solution correct by itself. It creates an additional verification point.
Explaining a process to an external reader requires reconstructing the causal chain, assigning responsibility to each stage, checking failure behavior, and limiting conclusions to verified guarantees.
When I examined the documentation delivery process this way, it helped clarify the boundaries between CI, CD, and Flux, and then exposed a missing dependency before deployment. The result was not only a more accurate description, but a change to the delivery process itself.
The value of the public text was not publication as such. It came from the need to prove the important connections in the system being described.
Words such as “usually,” “then,” and “the system handles it” do not always indicate an error. But they identify places where the engineering model deserves closer examination.
