> ## Content Index
> Fetch the complete content index at: https://ghostbabble.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# One Pipeline to Break Them All
- URL: https://ghostbabble.com/one-pipeline-one-job/
- Published: 2026-10-17T05:10:26.000Z
- Updated: 2026-10-17T05:10:26.000Z
- Description: Generative AI made duplication cheap. That changes how we should build pipelines and playbooks: one pipeline, one job.
- Author: Ghost X

A lot of infrastructure looks clean right up until you have to change something.

One shared role. One pipeline. One place to update everything. It sounds efficient. Then somebody changes a default and three teams find out they were depending on behavior nobody knew they owned.

But at least we didn't repeat ourselves.

Take Ansible.

You start with a role that configures a web server. Another service needs almost the same thing, so you add a variable. Then a conditional. Then a `when:` block for the environment that is apparently too special to work like the other environments. Another team starts using it because it already exists.

Eventually you have thousands of playbooks leaning on shared roles, and changing one of those roles requires knowing what everybody else meant when they called it.

Nobody has that information. The code certainly doesn't explain it.

So you pull one string, fix your playbook, and break somebody else's deployment.

This is the part of reuse we don't put in the architecture diagram.

## Thirty checkboxes and a dropdown

The Jenkins version is even better.

One job that deploys the application, runs migrations, restarts workers, rebuilds caches, and does six other things depending on which boxes you checked.

Run the tests. Skip the tests. Run the migration. Don't run the migration. Restart the workers, but only in us-east-1\. Notify Slack. Don't notify Slack.

At some point this stopped being a pipeline and became an application with a terrible user interface.

The build history says `Deploy-Everything #4127`. Great. What did it actually do?

Now you're digging through parameters and logs before you can even start investigating the failure. The job name tells you almost nothing. The possible combinations keep multiplying. Testing the pipeline means testing all the ways somebody might decide to use it.

Compare that with `deploy-payments-api`, `run-payments-db-migration`, and `restart-payments-workers-us-east-1`.

You can tell what each one is supposed to do. Each has its own history. Each can have permissions limited to the work it actually performs. Changing how a cache gets rebuilt doesn't have to mean changing the pipeline somebody else uses to deploy an application.

The point is to make the boundaries real. Separate files don't help much if they all call the same unversioned script with the same credentials and can still break the same things.

## We saved typing and paid for it later

I understand why we built these systems.

Maintaining thirty pipelines by hand is annoying. Fixing the same thing in thirty places is worse. A shared role or pipeline gives you one place to make the change, and for plenty of problems that is exactly what you want.

The trouble starts when we treat that as an automatic improvement regardless of what we've connected together.

Two jobs use similar commands, so we put them in the same pipeline. Two services need slightly different behavior, so we add a flag. Then another flag. Eventually the abstraction needs a meeting to explain it.

We saved ourselves some repeated code. We also made a lot of unrelated work depend on the same change.

Those are both costs. Only one of them is obvious in a pull request.

## AI changes what is worth sharing

This is where I think generative AI changes the tradeoff.

Producing another small pipeline from an established example takes less effort than it used to. So does preparing the same targeted change across several pipelines. I can spend less time writing the repetitive parts and more time deciding what the thing should be allowed to do.

That doesn't make maintenance free.

Generating thirty files is easy. Proving you didn't generate the same bug thirty times still takes work. Somebody still has to review the change, test it, deploy it, and own what happens afterward.

But if the argument for a giant shared pipeline is that writing a few more small ones would be too much work, I think that argument deserves another look.

Especially when the alternative is asking a person, or an AI, to reason through a role with thousands of lines and years of conditional behavior.

Being able to generate more code doesn't excuse you from understanding it. It makes choosing a scope you can actually understand more important.

## Share the template. Control the change.

Here's how I want this to work.

Build one pipeline that does one job well. Give it a useful name. Test it. Make its permissions match its purpose.

Use that as the starting point for the next job. Let the AI handle the repetitive work. Review what changed and whether the new pipeline actually does what its name says.

You don't have to turn the original pipeline into a control panel for every similar job anyone might need later.

The template is the shared starting point. It doesn't have to become a runtime dependency underneath every deployment.

When the pattern changes, record which pipelines came from which version and roll the update out deliberately. Test the affected jobs. Know which ones have been updated and which ones haven't.

Otherwise you've just created thirty copies nobody knows how to maintain. That isn't much of an improvement.

I apply the same thinking to my side projects. Separate repos and deploy roles, with each role scoped to its own project's resources. More files, yes. But changing one project shouldn't require trusting myself to leave every other project alone.

The permissions should enforce that boundary.

Shared libraries still have a place. So do shared roles. I want them versioned, with callers choosing when to adopt a change. If fixing one consumer silently changes the behavior of every other consumer, the problem hasn't gone away because we called it a library.

And parameters are fine when they describe the job. An application version or a target environment doesn't automatically require another pipeline. A checkbox that switches from deploying an application to performing an unrelated maintenance operation is a different conversation.

One job can have inputs. It shouldn't need an identity crisis.

## Teams should talk. Their deployments shouldn't all break together.

We talk about breaking down silos as if isolation is always a bad thing.

People should communicate. Teams should share what they've learned. Nobody benefits from five teams independently discovering the same operational problem and never telling each other.

That doesn't mean their automation needs to share the same failure path.

Work horizontally. Give the pieces clear responsibilities. Make the dependencies explicit. Share the patterns that help, and control when changes cross those boundaries.

I don't care how little code we repeated if nobody can safely change any of it.

One pipeline. One job.