<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jan Duris</title>
    <description>The latest articles on DEV Community by Jan Duris (@dulvarn).</description>
    <link>https://dev.to/dulvarn</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4026392%2F70189d84-bdfe-4c8e-9fcc-85529ea976a2.png</url>
      <title>DEV Community: Jan Duris</title>
      <link>https://dev.to/dulvarn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dulvarn"/>
    <language>en</language>
    <item>
      <title>Your Tests Passed. That Still Doesn’t Mean You Should Release.</title>
      <dc:creator>Jan Duris</dc:creator>
      <pubDate>Tue, 25 Aug 2026 04:42:05 +0000</pubDate>
      <link>https://dev.to/dulvarn/your-tests-passed-that-still-doesnt-mean-you-should-release-184o</link>
      <guid>https://dev.to/dulvarn/your-tests-passed-that-still-doesnt-mean-you-should-release-184o</guid>
      <description>&lt;p&gt;Your tests passed.&lt;/p&gt;

&lt;p&gt;CI is green.&lt;/p&gt;

&lt;p&gt;The build succeeded.&lt;/p&gt;

&lt;p&gt;So you release.&lt;/p&gt;

&lt;p&gt;Seems reasonable, right?&lt;/p&gt;

&lt;p&gt;Not necessarily.&lt;/p&gt;

&lt;p&gt;One of the most dangerous assumptions in modern software delivery is that a successful test suite automatically means a release is ready for production.&lt;/p&gt;

&lt;p&gt;It doesn't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passing tests tell us that the checks we wrote passed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A release decision asks a much larger question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Do we have enough evidence to accept the risk of shipping this change?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those are not the same thing.&lt;/p&gt;




&lt;h2&gt;
  
  
  What does a passing test actually prove?
&lt;/h2&gt;

&lt;p&gt;Every automated test checks a specific expectation.&lt;/p&gt;

&lt;p&gt;A unit test might verify that a function returns the expected result.&lt;/p&gt;

&lt;p&gt;An API test might verify that an endpoint responds with &lt;code&gt;200&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;An end-to-end test might confirm that a user can complete checkout.&lt;/p&gt;

&lt;p&gt;All of these are useful.&lt;/p&gt;

&lt;p&gt;But every test is created around assumptions.&lt;/p&gt;

&lt;p&gt;Someone decided:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what should be tested,&lt;/li&gt;
&lt;li&gt;which scenarios matter,&lt;/li&gt;
&lt;li&gt;which data should be used,&lt;/li&gt;
&lt;li&gt;which environments should be covered,&lt;/li&gt;
&lt;li&gt;and which failure modes were worth checking.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So when a test passes, what we really know is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Under the conditions we tested, the expected behavior occurred.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is valuable evidence.&lt;/p&gt;

&lt;p&gt;But it is not the same as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This release is safe.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  A release contains more risk than your test suite can see
&lt;/h2&gt;

&lt;p&gt;Imagine this release:&lt;/p&gt;

&lt;p&gt;Unit tests          PASS&lt;br&gt;
Integration tests   PASS&lt;br&gt;
E2E tests           PASS&lt;br&gt;
Lint                PASS&lt;br&gt;
Build               PASS&lt;/p&gt;

&lt;p&gt;Everything looks perfect.&lt;/p&gt;

&lt;p&gt;But the same release also includes:&lt;/p&gt;

&lt;p&gt;Database migration        HIGH IMPACT&lt;br&gt;
Authentication changes    YES&lt;br&gt;
Dependency upgrade        YES&lt;br&gt;
Rollback recently tested  NO&lt;br&gt;
Observability coverage    PARTIAL&lt;br&gt;
Deployment blast radius   HIGH&lt;/p&gt;

&lt;p&gt;None of those conditions necessarily need to make a test fail.&lt;/p&gt;

&lt;p&gt;Yet every one of them can influence whether releasing is a good idea.&lt;/p&gt;

&lt;p&gt;This is where we often confuse two different activities:&lt;/p&gt;

&lt;p&gt;verification and decision-making.&lt;/p&gt;

&lt;p&gt;Tests verify behavior.&lt;/p&gt;

&lt;p&gt;Release decisions evaluate risk.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Green CI is a signal&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A common delivery model effectively looks like this:&lt;/p&gt;

&lt;p&gt;Tests pass&lt;br&gt;
    +&lt;br&gt;
Build succeeds&lt;br&gt;
    +&lt;br&gt;
Artifact exists&lt;br&gt;
    =&lt;br&gt;
Deploy&lt;/p&gt;

&lt;p&gt;For small systems and simple changes, this can work remarkably well.&lt;/p&gt;

&lt;p&gt;But the larger the system becomes, the weaker that assumption gets.&lt;/p&gt;

&lt;p&gt;A release can have a perfectly healthy CI pipeline and still be operationally risky.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;green pipeline&lt;br&gt;
+&lt;br&gt;
critical service change&lt;br&gt;
+&lt;br&gt;
large migration&lt;br&gt;
+&lt;br&gt;
weak rollback confidence&lt;br&gt;
+&lt;/p&gt;

&lt;h1&gt;
  
  
  limited observability
&lt;/h1&gt;

&lt;p&gt;???&lt;/p&gt;

&lt;p&gt;The individual checks are green.&lt;/p&gt;

&lt;p&gt;The combined risk might not be.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tests should be evidence, not the final decision&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I think a better mental model is this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;             RELEASE DECISION
                    ▲
                    │
    ┌───────────────┼───────────────┐
    │               │               │
 Tests           Changes        Operations
    │               │               │
 Security       Dependencies     Rollback
    │               │               │
    └──────────── Evidence ─────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Tests remain one of the strongest signals we have.&lt;/p&gt;

&lt;p&gt;But they are one signal among several.&lt;/p&gt;

&lt;p&gt;A release decision may also need to consider:&lt;/p&gt;

&lt;p&gt;change size,&lt;br&gt;
affected services,&lt;br&gt;
security findings,&lt;br&gt;
dependency changes,&lt;br&gt;
database migrations,&lt;br&gt;
production incident history,&lt;br&gt;
deployment timing,&lt;br&gt;
rollback readiness,&lt;br&gt;
observability,&lt;br&gt;
required approvals.&lt;/p&gt;

&lt;p&gt;Not every team needs every signal.&lt;/p&gt;

&lt;p&gt;The important part is the distinction:&lt;/p&gt;

&lt;p&gt;Test results are evidence presented to a release decision. They are not the release decision itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This gets more important with AI-generated code&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;AI coding tools are making software creation dramatically faster.&lt;/p&gt;

&lt;p&gt;They can generate implementation code.&lt;/p&gt;

&lt;p&gt;They can generate tests.&lt;/p&gt;

&lt;p&gt;They can fix failing tests.&lt;/p&gt;

&lt;p&gt;And they can do all of that very quickly.&lt;/p&gt;

&lt;p&gt;That creates an interesting situation:&lt;/p&gt;

&lt;p&gt;More code&lt;br&gt;
More tests&lt;br&gt;
More automation&lt;br&gt;
More green checks&lt;/p&gt;

&lt;p&gt;But potentially:&lt;/p&gt;

&lt;p&gt;Less human understanding of every individual change&lt;/p&gt;

&lt;p&gt;An AI-generated implementation can satisfy the tests while still introducing:&lt;/p&gt;

&lt;p&gt;a new architectural assumption,&lt;br&gt;
an unexpected dependency,&lt;br&gt;
different runtime behavior,&lt;br&gt;
operational complexity,&lt;br&gt;
or a failure mode nobody encoded into the tests.&lt;/p&gt;

&lt;p&gt;The solution is not to stop using AI.&lt;/p&gt;

&lt;p&gt;And it isn't simply to generate even more tests.&lt;/p&gt;

&lt;p&gt;The solution is to become better at evaluating evidence around the release.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI systems are excellent at execution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Modern CI/CD systems are incredibly capable.&lt;/p&gt;

&lt;p&gt;They can:&lt;/p&gt;

&lt;p&gt;run thousands of tests,&lt;br&gt;
scan dependencies,&lt;br&gt;
build containers,&lt;br&gt;
validate infrastructure,&lt;br&gt;
generate artifacts,&lt;br&gt;
and deploy applications.&lt;/p&gt;

&lt;p&gt;But there is one question many pipelines are surprisingly bad at answering:&lt;/p&gt;

&lt;p&gt;Why are we comfortable releasing this version?&lt;/p&gt;

&lt;p&gt;Ask that question after a deployment.&lt;/p&gt;

&lt;p&gt;You may get answers like:&lt;/p&gt;

&lt;p&gt;"Everything was green."&lt;/p&gt;

&lt;p&gt;or:&lt;/p&gt;

&lt;p&gt;"The PR was approved."&lt;/p&gt;

&lt;p&gt;or:&lt;/p&gt;

&lt;p&gt;"The pipeline allowed it."&lt;/p&gt;

&lt;p&gt;Those answers describe what happened.&lt;/p&gt;

&lt;p&gt;They don't necessarily explain the actual release decision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What would a release decision layer look like?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of:&lt;/p&gt;

&lt;p&gt;CI green → deploy&lt;/p&gt;

&lt;p&gt;we could think about delivery like this:&lt;/p&gt;

&lt;p&gt;Code change&lt;br&gt;
     ↓&lt;br&gt;
CI / QA / Security / Operational signals&lt;br&gt;
     ↓&lt;br&gt;
Evidence collection&lt;br&gt;
     ↓&lt;br&gt;
Risk evaluation&lt;br&gt;
     ↓&lt;br&gt;
Policy&lt;br&gt;
     ↓&lt;br&gt;
Release decision&lt;br&gt;
     ↓&lt;br&gt;
Deploy&lt;/p&gt;

&lt;p&gt;That decision does not always need to be binary.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;GO&lt;/p&gt;

&lt;p&gt;The evidence is sufficient and the risk is acceptable.&lt;/p&gt;

&lt;p&gt;CONDITIONAL GO&lt;/p&gt;

&lt;p&gt;The release can proceed, but only with an approval, mitigation, feature flag, additional monitoring, or another condition.&lt;/p&gt;

&lt;p&gt;NO GO&lt;/p&gt;

&lt;p&gt;The available evidence or risk does not justify releasing yet.&lt;/p&gt;

&lt;p&gt;This is much closer to how experienced engineers already think.&lt;/p&gt;

&lt;p&gt;The difference is making that reasoning explicit instead of leaving it inside someone's head.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Green should have a precise meaning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is nothing wrong with green CI.&lt;/p&gt;

&lt;p&gt;We want green builds.&lt;/p&gt;

&lt;p&gt;We want passing tests.&lt;/p&gt;

&lt;p&gt;We want fast feedback.&lt;/p&gt;

&lt;p&gt;The problem begins when we give those signals more meaning than they actually contain.&lt;/p&gt;

&lt;p&gt;A green pipeline should mean:&lt;/p&gt;

&lt;p&gt;The checks we defined passed.&lt;/p&gt;

&lt;p&gt;A release decision should mean:&lt;/p&gt;

&lt;p&gt;Given the available evidence and our risk policy, we are willing to ship this change.&lt;/p&gt;

&lt;p&gt;Those statements are related.&lt;/p&gt;

&lt;p&gt;But they are not identical.&lt;/p&gt;

&lt;p&gt;And as software development becomes faster, more distributed, and increasingly AI-assisted, I think that distinction is going to matter much more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does your team decide that something is ready to release?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Is a green pipeline enough?&lt;/p&gt;

&lt;p&gt;Or is there another decision layer after CI?&lt;/p&gt;

</description>
      <category>devops</category>
      <category>testing</category>
      <category>cicd</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>CI Is Green. What Could Still Go Wrong?</title>
      <dc:creator>Jan Duris</dc:creator>
      <pubDate>Fri, 21 Aug 2026 13:41:28 +0000</pubDate>
      <link>https://dev.to/dulvarn/ci-is-green-what-could-still-go-wrong-4g0k</link>
      <guid>https://dev.to/dulvarn/ci-is-green-what-could-still-go-wrong-4g0k</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg5h3qkowlahny4ump0p3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg5h3qkowlahny4ump0p3.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;A green CI pipeline is a nice feeling.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The build passed.&lt;br&gt;
Tests are green.&lt;br&gt;
Linting is clean.&lt;br&gt;
Nothing obvious is on fire.&lt;/p&gt;

&lt;p&gt;For a few seconds, it feels like the release question has already been answered.&lt;/p&gt;

&lt;p&gt;It hasn't.&lt;/p&gt;

&lt;p&gt;A green pipeline tells you something useful: the checks you configured have passed under the conditions in which they were executed.&lt;/p&gt;

&lt;p&gt;That is not the same thing as saying the release is safe.&lt;/p&gt;

&lt;p&gt;And the gap between those two ideas is where a lot of production problems begin.&lt;/p&gt;

&lt;p&gt;I touched on this in my previous article about why a green CI pipeline can create a false sense of security. But there is another question that deserves more attention:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If CI is green, what can still go wrong?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Quite a lot, actually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI only knows what you taught it to check&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is probably the most important limitation.&lt;/p&gt;

&lt;p&gt;CI is not intelligent by default.&lt;/p&gt;

&lt;p&gt;It does not understand your product, your users, your business risk, or the weird operational history of your system.&lt;/p&gt;

&lt;p&gt;It runs instructions.&lt;/p&gt;

&lt;p&gt;If those instructions cover the right risks, great.&lt;/p&gt;

&lt;p&gt;If they don't, the pipeline can be perfectly green while the release is still dangerous.&lt;/p&gt;

&lt;p&gt;This is not really a failure of CI.&lt;/p&gt;

&lt;p&gt;It is a failure of interpretation.&lt;/p&gt;

&lt;p&gt;We often treat CI as if it has answered a bigger question than it actually has.&lt;/p&gt;

&lt;p&gt;The pipeline says:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"The checks I know about passed."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Humans often hear:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"This release is safe."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Those are very different statements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The code can be correct and the release can still fail&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine a change that passes every unit test and every integration test.&lt;/p&gt;

&lt;p&gt;The code itself is fine.&lt;/p&gt;

&lt;p&gt;Then it reaches production and fails because of configuration.&lt;/p&gt;

&lt;p&gt;Wrong environment variable.&lt;/p&gt;

&lt;p&gt;Missing secret.&lt;/p&gt;

&lt;p&gt;Different feature flag state.&lt;/p&gt;

&lt;p&gt;A service points to the wrong endpoint.&lt;/p&gt;

&lt;p&gt;A timeout is configured differently in production.&lt;/p&gt;

&lt;p&gt;A permission exists in staging but not in production.&lt;/p&gt;

&lt;p&gt;None of those problems necessarily mean your tests were bad.&lt;/p&gt;

&lt;p&gt;They mean the release depended on conditions outside the scope of those tests.&lt;/p&gt;

&lt;p&gt;This is one of the reasons I think we should stop treating release readiness as purely a testing problem.&lt;/p&gt;

&lt;p&gt;Testing is part of it.&lt;/p&gt;

&lt;p&gt;It is not the whole thing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Database migrations are a good example&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Database changes are one of those areas where "green" can be misleading.&lt;/p&gt;

&lt;p&gt;The migration itself may be syntactically correct.&lt;/p&gt;

&lt;p&gt;Tests may pass against a fresh database.&lt;/p&gt;

&lt;p&gt;Everything can look completely normal.&lt;/p&gt;

&lt;p&gt;But production has something your test environment often does not have:&lt;/p&gt;

&lt;p&gt;history.&lt;/p&gt;

&lt;p&gt;Real data.&lt;/p&gt;

&lt;p&gt;Old records.&lt;/p&gt;

&lt;p&gt;Unexpected null values.&lt;/p&gt;

&lt;p&gt;Large tables.&lt;/p&gt;

&lt;p&gt;Long-running transactions.&lt;/p&gt;

&lt;p&gt;Different indexes.&lt;/p&gt;

&lt;p&gt;Different traffic patterns.&lt;/p&gt;

&lt;p&gt;A migration that takes two seconds in CI can behave very differently against a production dataset that has existed for six years.&lt;/p&gt;

&lt;p&gt;The pipeline can be green because nothing it executed was technically wrong.&lt;/p&gt;

&lt;p&gt;The release can still be risky because the environment changed the meaning of that change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependencies can change the picture&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Modern software rarely runs in isolation.&lt;/p&gt;

&lt;p&gt;A release can depend on:&lt;/p&gt;

&lt;p&gt;another internal service&lt;br&gt;
a third-party API&lt;br&gt;
a package update&lt;br&gt;
a cloud service&lt;br&gt;
a message queue&lt;br&gt;
a payment provider&lt;br&gt;
a database&lt;br&gt;
an authentication system&lt;/p&gt;

&lt;p&gt;Your own repository may be completely healthy.&lt;/p&gt;

&lt;p&gt;The dependency chain around it may not be.&lt;/p&gt;

&lt;p&gt;Maybe another service has not deployed the expected API yet.&lt;/p&gt;

&lt;p&gt;Maybe a backwards-compatibility assumption is wrong.&lt;/p&gt;

&lt;p&gt;Maybe one dependency is already degraded.&lt;/p&gt;

&lt;p&gt;Maybe the release introduces a combination of versions that nobody has actually tested together.&lt;/p&gt;

&lt;p&gt;Again, CI may remain perfectly green.&lt;/p&gt;

&lt;p&gt;It tested what it could see.&lt;/p&gt;

&lt;p&gt;The release depends on more than that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passing tests do not mean the right tests ran&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This one is uncomfortable, because it sounds obvious once you say it.&lt;/p&gt;

&lt;p&gt;A test suite can have a 100% pass rate while still telling you very little about the change you are about to release.&lt;/p&gt;

&lt;p&gt;The interesting question is not:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;How many tests passed?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Did we test the things that matter for this release?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Those are not equivalent.&lt;/p&gt;

&lt;p&gt;If somebody changes a critical authentication flow and your pipeline runs 3,000 tests mostly covering catalog functionality, the number &lt;em&gt;"3,000 passed"&lt;/em&gt; looks impressive.&lt;/p&gt;

&lt;p&gt;But what does it actually tell you about authentication risk?&lt;/p&gt;

&lt;p&gt;Not much.&lt;/p&gt;

&lt;p&gt;This is why I find the concept of risk coverage more useful than simply looking at test coverage or test count.&lt;/p&gt;

&lt;p&gt;What changed?&lt;/p&gt;

&lt;p&gt;What can that change affect?&lt;/p&gt;

&lt;p&gt;Which checks give us evidence about those areas?&lt;/p&gt;

&lt;p&gt;That context matters more than a big green number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Feature flags do not magically remove risk&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Feature flags are useful.&lt;/p&gt;

&lt;p&gt;Very useful.&lt;/p&gt;

&lt;p&gt;But sometimes they become another source of false confidence.&lt;/p&gt;

&lt;p&gt;The thinking becomes:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"It's behind a flag, so the release is safe."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Maybe.&lt;/p&gt;

&lt;p&gt;But the code still shipped.&lt;/p&gt;

&lt;p&gt;The flag configuration itself can be wrong.&lt;/p&gt;

&lt;p&gt;The disabled path may affect initialization.&lt;/p&gt;

&lt;p&gt;The new code may introduce dependencies before the flag is evaluated.&lt;/p&gt;

&lt;p&gt;The wrong audience may receive the feature.&lt;/p&gt;

&lt;p&gt;The rollback path may not behave the way you expect.&lt;/p&gt;

&lt;p&gt;Feature flags reduce certain kinds of risk.&lt;/p&gt;

&lt;p&gt;They do not eliminate release risk.&lt;/p&gt;

&lt;p&gt;That distinction matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rollback is not a guarantee either&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another sentence I hear in software teams is some version of:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"If something goes wrong, we'll just roll it back."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That can be a perfectly reasonable risk strategy.&lt;/p&gt;

&lt;p&gt;But "rollback exists" and "rollback is safe" are not the same thing.&lt;/p&gt;

&lt;p&gt;What happens if the release includes a destructive migration?&lt;/p&gt;

&lt;p&gt;What happens if new data has already been written in a new format?&lt;/p&gt;

&lt;p&gt;What happens if another service starts depending on the new behavior?&lt;/p&gt;

&lt;p&gt;What happens if the release changes an external contract?&lt;/p&gt;

&lt;p&gt;Rollback sounds simple when we imagine software as a single binary moving backwards.&lt;/p&gt;

&lt;p&gt;Real systems are messier.&lt;/p&gt;

&lt;p&gt;Sometimes the release creates state that cannot be cleanly reversed.&lt;/p&gt;

&lt;p&gt;A green CI pipeline usually does not tell you whether your rollback strategy actually works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Production traffic is different&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is also a class of failures that only appears under real usage.&lt;/p&gt;

&lt;p&gt;Concurrency.&lt;/p&gt;

&lt;p&gt;Traffic spikes.&lt;/p&gt;

&lt;p&gt;Unusual request sequences.&lt;/p&gt;

&lt;p&gt;Large payloads.&lt;/p&gt;

&lt;p&gt;Rare account states.&lt;/p&gt;

&lt;p&gt;Slow upstream services.&lt;/p&gt;

&lt;p&gt;Network instability.&lt;/p&gt;

&lt;p&gt;Real users are extremely good at discovering combinations that test environments never produce.&lt;/p&gt;

&lt;p&gt;This is not an argument against automation.&lt;/p&gt;

&lt;p&gt;It is an argument for understanding what automation can and cannot prove.&lt;/p&gt;

&lt;p&gt;A test suite can give you evidence.&lt;/p&gt;

&lt;p&gt;It cannot give you certainty.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Observability matters before the release, not only after it&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One thing I think teams often underestimate is operational readiness.&lt;/p&gt;

&lt;p&gt;Suppose the release does contain a problem.&lt;/p&gt;

&lt;p&gt;Will you notice?&lt;/p&gt;

&lt;p&gt;How quickly?&lt;/p&gt;

&lt;p&gt;Do you have the right metrics?&lt;/p&gt;

&lt;p&gt;Do you have logs around the changed area?&lt;/p&gt;

&lt;p&gt;Will an alert actually fire?&lt;/p&gt;

&lt;p&gt;Can you distinguish expected noise from a real regression?&lt;/p&gt;

&lt;p&gt;A release with some uncertainty but excellent observability can sometimes be safer than a release with more passing tests but poor visibility.&lt;/p&gt;

&lt;p&gt;Because release safety is not only about preventing every possible failure.&lt;/p&gt;

&lt;p&gt;It is also about limiting the damage when a failure happens.&lt;/p&gt;

&lt;p&gt;That changes the release decision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Human context still matters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not every release risk is technical.&lt;/p&gt;

&lt;p&gt;Sometimes the biggest risk is simply that nobody has the full picture.&lt;/p&gt;

&lt;p&gt;QA knows about one unresolved issue.&lt;/p&gt;

&lt;p&gt;A developer knows the fix was rushed.&lt;/p&gt;

&lt;p&gt;Operations knows a dependent system has been unstable all afternoon.&lt;/p&gt;

&lt;p&gt;Product knows a feature absolutely must not reach one customer segment yet.&lt;/p&gt;

&lt;p&gt;Security raised a concern that is technically "non-blocking."&lt;/p&gt;

&lt;p&gt;Each piece of information exists.&lt;/p&gt;

&lt;p&gt;But it exists in different places, owned by different people.&lt;/p&gt;

&lt;p&gt;Then the pipeline turns green.&lt;/p&gt;

&lt;p&gt;And everyone assumes somebody else must have checked the rest.&lt;/p&gt;

&lt;p&gt;This is where release processes become dangerous.&lt;/p&gt;

&lt;p&gt;Not because there was no information.&lt;/p&gt;

&lt;p&gt;Because the information never became part of the decision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So what does green CI actually mean?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I still want green CI.&lt;/p&gt;

&lt;p&gt;Obviously.&lt;/p&gt;

&lt;p&gt;A red pipeline is useful information too, but I would much rather start from green.&lt;/p&gt;

&lt;p&gt;The problem is not the green status.&lt;/p&gt;

&lt;p&gt;The problem is giving that status more authority than it deserves.&lt;/p&gt;

&lt;p&gt;For me, a green pipeline should mean something closer to:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;The automated checks we currently require did not detect a blocking problem.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is a strong signal.&lt;/p&gt;

&lt;p&gt;It is not yet a release decision.&lt;/p&gt;

&lt;p&gt;A real release decision needs more context.&lt;/p&gt;

&lt;p&gt;Depending on the system, I would want to know things like:&lt;/p&gt;

&lt;p&gt;What changed?&lt;br&gt;
How risky is that area?&lt;br&gt;
Which relevant tests actually ran?&lt;br&gt;
Are there unresolved defects?&lt;br&gt;
Are dependencies healthy and compatible?&lt;br&gt;
Are migrations involved?&lt;br&gt;
Are security checks clean?&lt;br&gt;
Do we have sufficient observability?&lt;br&gt;
Can we roll back safely?&lt;br&gt;
Is there any known operational or business risk?&lt;/p&gt;

&lt;p&gt;Only then does the question become interesting:&lt;/p&gt;

&lt;p&gt;Do we have enough evidence to release?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maybe the problem is the way we frame CI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We built CI to automate verification.&lt;/p&gt;

&lt;p&gt;Over time, many teams started using it as a proxy for release readiness.&lt;/p&gt;

&lt;p&gt;That shortcut works surprisingly often.&lt;/p&gt;

&lt;p&gt;Which is exactly why it is dangerous.&lt;/p&gt;

&lt;p&gt;Most releases with a green pipeline are probably fine.&lt;/p&gt;

&lt;p&gt;Then one isn't.&lt;/p&gt;

&lt;p&gt;And when you investigate what happened, the answer is often not:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"CI failed."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It is:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"CI never knew that this was something it needed to evaluate."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That is the gap I keep coming back to.&lt;/p&gt;

&lt;p&gt;The future of release engineering, in my opinion, is not just more tests and faster pipelines.&lt;/p&gt;

&lt;p&gt;It is better decision-making.&lt;/p&gt;

&lt;p&gt;More context.&lt;/p&gt;

&lt;p&gt;Better evidence.&lt;/p&gt;

&lt;p&gt;A clearer understanding of what we know before we put a change in front of users.&lt;/p&gt;

&lt;p&gt;Green CI should absolutely make us more confident.&lt;/p&gt;

&lt;p&gt;It just shouldn't make us stop asking questions.&lt;/p&gt;

</description>
      <category>cicd</category>
      <category>qa</category>
      <category>devops</category>
      <category>testing</category>
    </item>
    <item>
      <title>CI is green. Your release may still be risky.</title>
      <dc:creator>Jan Duris</dc:creator>
      <pubDate>Sun, 12 Jul 2026 20:15:10 +0000</pubDate>
      <link>https://dev.to/dulvarn/ci-is-green-your-release-may-still-be-risky-3c7m</link>
      <guid>https://dev.to/dulvarn/ci-is-green-your-release-may-still-be-risky-3c7m</guid>
      <description>&lt;p&gt;Every team has a moment like this: CI passes, the PR gets merged, the deploy goes out — and two hours later someone's asking why checkout is throwing 500s in production.&lt;/p&gt;

&lt;p&gt;Nobody skipped a step. The pipeline was green the whole time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The false comfort of green CI&lt;/strong&gt;&lt;br&gt;
Green CI feels like permission. It's a checkmark, it's fast, and it's automated — so it's easy to treat it as the final word on whether a release is safe. For a lot of teams, "tests passed" and "safe to ship" have quietly become the same sentence.&lt;/p&gt;

&lt;p&gt;They're not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What CI actually checks&lt;/strong&gt;&lt;br&gt;
Most CI pipelines are built to catch a specific, narrow slice of problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the code compile / build?&lt;/li&gt;
&lt;li&gt;Do unit tests pass?&lt;/li&gt;
&lt;li&gt;Does lint pass?&lt;/li&gt;
&lt;li&gt;Maybe: does a small integration suite pass?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's genuinely useful. It catches typos, broken imports, obvious logic errors, regressions in covered code paths. It's necessary.&lt;/p&gt;

&lt;p&gt;It's just not the same thing as "this release is safe to put in front of users."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What CI doesn't tell you&lt;/strong&gt;&lt;br&gt;
CI has no opinion on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Downstream dependencies&lt;/strong&gt; — does the third-party API you call still behave the way your integration test mocked it to?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manual steps&lt;/strong&gt; — did someone actually run the DB migration on staging before merging, or is that still "to do"?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deploy-time risk&lt;/strong&gt; — blue-green cutover, cache invalidation, feature flag state — none of that is exercised by a test suite that runs against a branch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Human process gaps&lt;/strong&gt; — did the person who approved this PR actually understand the blast radius, or did they approve because the CI badge was green?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this shows up as a failing check. It shows up as an incident.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Release risk is a different question than test pass/fail&lt;/strong&gt;&lt;br&gt;
"Did the tests pass" is a yes/no question about code. "Is this release safe to ship" is a probabilistic question about a system: what changed, how big is the diff, does it touch a critical path, is there a rollback plan, has this kind of change caused problems before.&lt;/p&gt;

&lt;p&gt;Most teams answer that second question with vibes — a Slack message, a shrug, "looks fine to me." That works fine until it doesn't, and by the time it doesn't, you're writing a postmortem instead of a checklist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What a release risk gate actually looks like&lt;/strong&gt;&lt;br&gt;
The teams that don't get burned by this usually have some version of the same thing, whether they call it that or not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A policy layer that blocks release on concrete conditions (required approvals, coverage thresholds, freeze windows) — not vibes, actual enforced rules.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A signal aggregator that pulls test results, error rates, and coverage into one release health view instead of five open tabs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An audit trail — an immutable record of what was actually in a release, so when something breaks you're debugging from evidence, not memory.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this requires an enterprise platform. Small teams can build a lightweight version of this with GitHub Actions, a policy file, and some discipline. The point isn't the tooling — it's separating "code compiles" from "release is safe" as two distinct questions with two distinct answers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where to start if you don't have this yet&lt;/strong&gt;&lt;br&gt;
You don't need to build a whole release control system this week. Start smaller:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Write down the 3–5 things that, if skipped, have caused an incident before. Turn them into a checklist that's actually enforced, not just documented.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add one non-negotiable gate to your PR template — coverage on touched files, or a manual QA sign-off for anything touching payments/auth.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Capture a snapshot of what shipped in each release (commit list, who approved, what tests ran) so your next postmortem starts with facts instead of "let me check Slack."&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want a starting point instead of building it from scratch, I put together a Release Checklist Pack and a GitHub QA Gates Pack — practical templates for exactly this, no platform lock-in required.&lt;/p&gt;

&lt;p&gt;I'm building Dulvarn, a release control system for GitHub-first teams, plus a set of standalone QA/release tools and templates. This post reflects my own experience shipping software, not any employer's views or confidential information.&lt;/p&gt;

</description>
      <category>qa</category>
      <category>devops</category>
      <category>testing</category>
      <category>github</category>
    </item>
  </channel>
</rss>
