At UCLA Health, we rely heavily on Drupal and open-source software. One of the great strengths of open source is that fixes often become available long before they are officially released. These fixes are commonly shared as "patches."

For years, our Drupal projects have used patches from community issue queues, pull requests, and merge requests to solve problems while waiting for official releases.

Recently, the Composer Patches ecosystem evolved with the release of Composer Patches 2.x. While new version provides improvements and modernization, it  encouraged us to revisit how we manage patches across our projects while we schedule migrating to version 2.

That review exposed a problem.

The Risk of Remote Patches

Many development teams reference patch files directly from external sources as it is convenient. 

For example:

  • Drupal issue queues
  • GitHub pull requests
  • GitLab merge requests

At first glance, this seems convenient. Composer downloads the patch directly from the source and applies it automatically.

The challenge is that these sources can change.

  • A merge request can be updated.
  • A patch can be replaced.
  • A repository can be reorganized.
  • Or, in some cases, a patch can disappear entirely.

When that happens, builds that worked yesterday may suddenly fail today.

We experienced exactly this issue when relying on upstream merge request patch files. The URL remained the same, but the underlying patch changed, creating unexpected challenges for long-term stability.  To avoid this risk, we started downloading the files ourselves and committing these patches to the repository.  While this fixed the issues identified above, the process took away valuable time from our small development team on delivering new features. 

Our Goal

We wanted a solution that would:

  • Reduce maintenance overhead
  • Preserve the convenience of Composer patches
  • Protect projects from disappearing or changing patch files
  • Be easy for developers to understand
  • Work with existing local development environments

Most importantly, we wanted a process that allows teams to decide which patches should remain remote and which should be preserved locally.

The Solution

We created a lightweight patch synchronization workflow.

Instead of maintaining Composer patch definitions directly, developers maintain a simple YAML file that acts as the source of truth.

The system then:

  1. Validates the patch definitions.
  2. Downloads selected patches locally.
  3. Organizes patch files into a consistent folder structure.
  4. Generates the Composer-compatible JSON file automatically.
  5. Identifies unused patch files that may no longer be needed.

This creates a safer workflow while keeping patch management straightforward.

If you are interested in more technical exploration, please review our Gist - An Enterprise Approach to Drupal Composer Patching.

Why Local Copies Matter

Not every patch needs to be copied locally.

If a patch comes from a stable source and is expected to remain available, it can continue to be referenced remotely.

However, patches associated with merge requests or temporary development work are often good candidates for local copies.

By storing those files in the project repository:

  • The exact version of the patch is preserved.
  • Future builds remain consistent.
  • Team members can review patch contents.
  • Project history clearly shows what was applied and when.

In other words, the project becomes less dependent on external systems remaining unchanged.

Additional Safeguards

The workflow also introduces several quality-of-life improvements:

Validation

Patch definitions are checked before they are used.

This helps catch formatting problems and configuration mistakes early.

Consistent Naming

Downloaded patch files follow predictable naming rules, making them easier to find and review.

Orphan Detection

The tool can identify patch files that no longer appear in the configuration.

This helps keep repositories clean over time.

Automatic Retries

Network failures happen.

Downloads automatically retry when temporary connectivity issues occur.

Looking Ahead

This isn't intended to replace Composer Patches.

Instead, it's a small layer of automation built on top of it that helps teams manage risk while keeping patch maintenance simple.

For us, it provides a balance between the flexibility of community-provided fixes and the stability needed for enterprise Drupal development.

We hope it helps other organizations in the Drupal community (and our colleagues throughout UCLA working with Composer) simplify patch management while reducing unexpected build failures.