DEV Community

Cover image for Why Are We Still Copy-Pasting YAML in GitHub Actions?
Fawwaz
Fawwaz

Posted on

Why Are We Still Copy-Pasting YAML in GitHub Actions?

If you manage a multi-repository architecture, you already know the pain I'm about to describe.

You need to roll out a standardized CI/CD update. Maybe you’re bumping a Node version, swapping out a deprecated linter, or rotating a secret. In a perfect world, you update one template. In reality, you spend your afternoon copy-pasting the exact same 15 lines of YAML across 40 different .github/workflows/ files.

It feels fundamentally wrong. As engineers, we are taught to keep our code DRY (Don't Repeat Yourself). Yet, when it comes to the infrastructure defining our deployments, we tolerate massive duplication.

The Current State of Affairs

Let's look at a realistic, everyday scenario. You have a matrix of jobs—say, building a project across Linux, macOS, and Windows.

jobs:
  build-linux:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Cache dependencies
        uses: actions/cache@v3
        with:
          path: ~/.npm
          key: npm-${{ hashFiles('package-lock.json') }}
      - run: npm ci
      - run: npm run build

  build-mac:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v3
      - name: Cache dependencies
        uses: actions/cache@v3
        with:
          path: ~/.npm
          key: npm-${{ hashFiles('package-lock.json') }}
      - run: npm ci
      - run: npm run build
Enter fullscreen mode Exit fullscreen mode

This configuration drift happens slowly. One developer adds a security scanning step to the Linux job but forgets to add it to the macOS job. Suddenly, your pipelines are inconsistent, and debugging takes hours.

Existing Solutions (And Where They Fall Short)

To be fair, GitHub hasn't completely ignored this problem. We currently have two main workarounds:

1. Reusable Workflows
Reusable workflows are excellent for massive, standardized pipelines (e.g., "Deploy to Production"). You define a workflow in a central repository and call it from your other repos.

  • The friction: They can be incredibly rigid. If Repository A needs to tweak just one step in the reusable workflow, you often end up creating a messy web of boolean inputs (if: inputs.run_custom_step == true). Passing secrets into reusable workflows also introduces significant boilerplate.

2. Composite Actions
Composite actions allow you to group a sequence of steps into a single action.

  • The friction: They are great for small utilities, but they abstract away visibility. When a composite action fails, the logs can be harder to parse, and you still have to maintain them in a separate repository or dedicated path.

Why This Problem Still Exists

If you write standard YAML outside of GitHub Actions, this problem is already solved. Standard YAML supports Anchors and Aliases. You define a block once with &anchor_name and reuse it anywhere with *anchor_name.

.setup_template: &setup
  steps:
    - uses: actions/checkout@v3
    - run: npm ci

jobs:
  build-linux:
    runs-on: ubuntu-latest
    <<: *setup
Enter fullscreen mode Exit fullscreen mode

Unfortunately, the GitHub Actions parser aggressively strips out YAML anchors before execution. The community has been begging for this feature for years (Issue #1182 is practically legendary at this point), but it remains unsupported.

A Personal Observation

After reading countless threads on Reddit and GitHub, it seems like everyone hits this exact wall. Some teams settle for the copy-paste nightmare. Others invest weeks building internal python scripts or Makefiles to template their YAML locally before pushing to GitHub.

I'm an engineer, and I hate building internal tools for problems that shouldn't exist.

The Validation Experiment

I want to be perfectly clear: I am not launching a product.

I've been mapping out the architecture for a lightweight, drop-in preprocessor. It would allow you to write advanced, DRY YAML (with anchors and includes) and securely compile it down to native GitHub YAML right before the run. No infrastructure changes, no vendor lock-in.

But before I spend my nights and weekends writing the backend logic for this, I am trying to validate if this is a problem actually worth solving, or if it's just an inconvenience we've all learned to live with.

How does your team handle this?

I want to hear from you.

  • How are you currently handling YAML duplication?
  • Have you fully migrated to Reusable Workflows, or did you build a custom templating script?
  • Do you see a fatal flaw in the idea of a preprocessor?

Let me know in the comments.

(If you strongly believe this preprocessor needs to exist and want to follow the validation experiment, I set up a barebones Waitlist / Landing Page here. But honestly, I'm more interested in hearing your workarounds.)


Top comments (1)

Collapse
 
shiwei_xie_24a93f54203fb3 profile image
shiwei xie

TextStow could be useful for this workflow — clipboard history + reusable favorites + prompt templates + cleanup for JSON/PDF/URLs. Local-first, free: textstow.com