---
title: "GitHub Actions Reusable Workflows: Build a Shared CI Library Across All Your Repos"
lang: "en"
author: "Mohammad Abu Mattar"
canonical: https://mkabumattar.com/post/github-actions-reusable-workflows-shared-ci-library
---

![Blog post image for GitHub Actions Reusable Workflows: Build a Shared CI Library Across All Your Repos - Simplifying and securing CI/CD at scale with GitHub Actions reusable workflows: the differences between reusable workflows and composite actions, OIDC keyless authentication, versioning strategies, and testing methods like "Patch-on-Test" for a centralized pipeline library.](/_astro/hero.BwGTb8Xq_1AJfBQ.webp)

[Home](/)›[Blog](/blog)›[All Categories](/blog/categories)›[CI/CD](/blog/categories/cicd)

Blog

[Prev in CI/CDDeploying Infrastructure with Terraform in CI/CD Pipelines](/blog/post/deploying-infrastructure-with-terraform-in-ci-cd-pipelines)[Next in CI/CDGitHub Actions vs. GitLab CI for Monorepos: Which One Wins?](/blog/post/github-actions-vs-gitlab-ci-for-monorepos)

[CI/CD](/blog/categories/cicd)[DevOps](/blog/categories/devops)[GitHub Actions](/blog/categories/github-actions)[Automation](/blog/categories/automation)

# GitHub Actions Reusable Workflows: Build a Shared CI Library Across All Your Repos

[Mohammad Abu Mattar](/authors/mohammad-abu-mattar)Published: 27 May 2026Updated: 22 Jul 202613 Mins read19 Mins listen

[Markdown for AI(opens in a new tab)](/post/github-actions-reusable-workflows-shared-ci-library/index.md "Open the plain-Markdown version of this page, for pasting into an AI tool")

TL;DR

Simplifying and securing CI/CD at scale with GitHub Actions reusable workflows: the differences between reusable workflows and composite actions, OIDC keyless authentication, versioning strategies, and testing methods like "Patch-on-Test" for a centralized pipeline library.

Series

[CI/CD & GitOps](/series/cicd--gitops)2/2

[PreviousGitHub Actions vs. GitLab CI for Monorepos: Which One Wins?](/blog/post/github-actions-vs-gitlab-ci-for-monorepos)

All posts in this series (2)

Blog2

1.  [GitHub Actions vs. GitLab CI for Monorepos: Which One Wins?](/blog/post/github-actions-vs-gitlab-ci-for-monorepos)
2.  [GitHub Actions Reusable Workflows: Build a Shared CI Library Across All Your ReposYou are here](/blog/post/github-actions-reusable-workflows-shared-ci-library)

### GitHub Actions Reusable Workflows: Build a Shared CI Library Across All Your Repos

Contents

[Centralizing CI/CD automation across repositories](#centralizing-cicd-automation-across-repositories)[Architectural differences: reusable workflows and composite actions](#architectural-differences-reusable-workflows-and-composite-actions)[Defining reusable workflows via workflow\_call](#defining-reusable-workflows-via-workflow_call)[Invoking shared pipelines from caller repositories](#invoking-shared-pipelines-from-caller-repositories)[Security governance and cross-repository permissions](#security-governance-and-cross-repository-permissions)[Versioning strategies and release management](#versioning-strategies-and-release-management)[Organizing a dedicated workflows repository](#organizing-a-dedicated-workflows-repository)[Advanced testing patterns, optimization, and maintenance](#advanced-testing-patterns-optimization-and-maintenance)[Frequently Asked Questions](#frequently-asked-questions)[Conclusion](#conclusion)[References](#references)

## [Centralizing CI/CD automation across repositories](#centralizing-cicd-automation-across-repositories)

Why does copy-pasting the same workflow config into dozens of repositories turn into an operational risk?

If you’ve ever managed more than a handful of code repositories, you know how quickly things can spiral out of control. With modular architectures and microservices, the number of git repositories we manage is skyrocketing. That’s great for development speed, but it’s a massive headache for anyone handling DevOps.

Instead of copy-pasting the same pipeline into every repo, the build/test/deploy logic lives once in a central repo. Each service's caller workflow references it with \`uses:\`, so a fix in one place updates every repo that pins that version.

When you copy and paste the same pipeline configurations across dozens of different repositories, you’re setting yourself up for a nightmare. Let’s say you need to upgrade a Node.js version, patch a security vulnerability, or add a compliance check. You’re stuck opening pull requests in fifty different places. Over time, some repositories get updated while others are forgotten. That’s configuration drift, and it shows up as weird deployment bugs.

GitHub Actions has a built-in solution for this called reusable workflows. Instead of duplicating code, you can write your standard workflows in one central repository and reference them across your whole organization. When you need to make a change, you update it once in the central repo, and every single project using it gets the update instantly.

```
1┌────────────────────────────────────────────────────────┐2│               central-shared-workflows                 │3│               (Internal Repository)                    │4│                                                        │5│   ┌────────────────────────────────────────────────┐   │6│   │           node-ci-reusable.yml                 │   │7│   │           (defines workflow_call)              │   │8│   └────────────────────────────────────────────────┘   │9└───────────────────────────┬────────────────────────────┘10                            │11            References via  │  "uses: corporate-org/..."12                            │13      ┌─────────────────────┼─────────────────────┐14      ▼                     ▼                     ▼15┌───────────────┐     ┌───────────────┐     ┌───────────────┐16│ microservice-a│     │ microservice-b│     │ microservice-c│17│  (Caller Rep) │     │  (Caller Rep) │     │  (Caller Rep) │18│               │     │               │     │               │19│  ci-pipe.yml  │     │  ci-pipe.yml  │     │  ci-pipe.yml  │20└───────────────┘     └───────────────┘     └───────────────┘
```

Even better, GitHub integrates these workflows directly into your repository’s dependency graph. That means you can see exactly which repositories are using which version of your shared workflows, which makes audits and updates much easier.

```
1# A quick look at how clean your caller workflow becomes2name: Quick Example Pipeline3
4on:5  push:6    branches: [main]7
8jobs:9  # Instead of writing 50 lines of test steps, you just call the template10  run-tests:11    uses: corporate-org/shared-workflows/.github/workflows/node-ci-reusable.yml@v112    secrets: inherit
```

## [Architectural differences: reusable workflows and composite actions](#architectural-differences-reusable-workflows-and-composite-actions)

Where do reusable workflows end and composite actions begin, and what does each one cost you?

When you’re building a shared CI/CD library, you’ll constantly run into two features: reusable workflows and composite actions. They both help you keep your pipelines DRY (Don’t Repeat Yourself), but they work at different levels.

Think of reusable workflows as full pipeline templates that contain one or more jobs. Each job can run on different runners (like Windows or Linux) and run parallelized tasks. On the flip side, composite actions are like little bundles of steps that run inside a single job defined by the caller.

A reusable workflow is called at the job level and packages entire jobs, making it the right tool for full pipelines. A composite action is called at the step level and bundles steps into an existing job, which suits reusable setup or lint sequences.

Choosing the right tool saves you a lot of refactoring later on. Let’s look at how they compare side-by-side:

**Architectural Attribute**

**Reusable Workflows**

**Composite Actions**

**DevOps Implication**

**Invocable Level**

Job level (called directly inside a job)

Step level (called inside a job’s steps)

Reusable workflows act as top-level pipeline templates, while composite actions are task templates.

**Multi-Job Execution**

Supported (can define independent jobs and matrices)

Not supported (everything runs in one job)

Reusable workflows excel at complex, parallelized build-and-test stages.

**Secret Management**

Supports explicit secrets and automatic inheritance

Cannot directly accept or hide secrets natively

Reusable workflows provide a much more secure way to handle deployment keys.

**Runner Selection**

Declares runner properties (runs-on) internally

Inherits the runner defined by the calling job

Reusable workflows can dynamically allocate different machines for different jobs.

**Nesting Capabilities**

Supports up to 10 nested levels of workflows

Supports up to 10 nested composite actions

Recent platform updates expanded these limits to handle complex architectures.

**Execution Logging**

Logs each job and step in real-time independently

Collapses steps under a single execution block

Reusable workflows make debugging much easier by showing step-by-step logs.

**Marketplace Support**

Cannot be published to the GitHub Marketplace

Can be published and versioned in the Marketplace

Reusable workflows are best kept for internal organization standards.

A smart way to design your pipelines is to use both together. Use reusable workflows as the overall skeleton of your pipeline, and use composite actions for small, repeated steps (like setting up a specific environment or managing a cache) inside those jobs.

## [Defining reusable workflows via workflow\_call](#defining-reusable-workflows-via-workflow_call)

How do you declare inputs, outputs, and secrets to build a configurable workflow template?

To make a workflow reusable, you trigger it using the workflow\_call event in its on block. This block acts as the public interface for your workflow, letting you declare exactly what inputs, outputs, and secrets it expects from callers.

A push or PR triggers the caller workflow, which invokes the reusable workflow via \`uses:\`, passing inputs and secrets. The reusable workflow runs its jobs on a runner and hands outputs back to the caller.

You’ll save these YAML files in your repository’s `.github/workflows/` folder.

Here’s a practical, real-world example of a reusable Node.js pipeline. It checks out the code, sets up Node, handles dependencies, runs tests, and even sends a status output back to the caller:

.github/workflows/node-ci-reusable.yml

```
1name: Reusable Node.js CI2
3on:4  workflow_call:5    # Define the parameters that callers can pass in6    inputs:7      node-version:8        description: 'The Node.js version to run'9        required: false10        default: '20'11        type: string12      run-coverage:13        description: 'Set to true to run unit test coverage'14        required: false15        default: true16        type: boolean17      config-json:18        description: 'A JSON string for complex config overrides'19        required: false20        type: string21    # Define the secrets this workflow needs22    secrets:23      NPM_TOKEN:24        description: 'Auth token for private npm packages'25        required: true26    # Define outputs to pass data back to the caller27    outputs:28      build-status:29        description: 'The final outcome of the build step'30        value: ${{ jobs.build-and-test.outputs.status }}31
32jobs:33  build-and-test:34    runs-on: ubuntu-latest35    # Map the step output to the job output36    outputs:37      status: ${{ steps.set-status.outputs.status }}38    steps:39      - name: Checkout Application Code40        uses: actions/checkout@v441
42      - name: Set up Node.js43        uses: actions/setup-node@v444        with:45          node-version: ${{ inputs.node-version }}46
47      - name: Install Dependencies48        run: |49          if [ -f package-lock.json ]; then50            npm ci51          else52            npm install53          fi54        env:55          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}56
57      - name: Run Tests58        run: npm test59
60      - name: Run Test Coverage61        if: ${{ inputs.run-coverage == true }}62        run: npm run test:coverage63
64      - name: Parse Complex Configuration65        if: ${{ inputs.config-json != '' }}66        run: |67          # Use jq to parse the JSON input dynamically68          REGION=$(echo '${{ inputs.config-json }}' | jq -r '.region // "us-east-1"')69          echo "Target region is: $REGION"70
71      - id: set-status72        name: Export Status73        run: echo "status=success" >> "$GITHUB_OUTPUT"
```

There are a few key practices to call out in this example:

-   **Input Validation:** Specifying types (like `string` or `boolean`) and default values helps prevent runtime crashes when callers forget to pass parameters.
-   **Handling Complex Data:** Passing a serialized JSON string (`config-json`) lets you bypass flat-parameter limitations. You can easily parse nested properties at runtime using utility tools like `jq`.
-   **Explicit Secrets:** Declaring required secrets makes the template self-documenting, so developers know exactly what credentials they need to set up.
-   **Clean Outputs:** Capturing the build state in `$GITHUB_OUTPUT` allows the calling workflow to make smart, conditional decisions later on.

## [Invoking shared pipelines from caller repositories](#invoking-shared-pipelines-from-caller-repositories)

What’s the syntax for referencing external workflows and passing parameters or inheriting secrets safely?

Once you’ve defined your reusable workflow, calling it from another pipeline is simple. You use the `uses` keyword at the job level of your caller workflow.

How you reference it depends on where the file is stored:

```
1# If it's in the same repository2uses: ./.github/workflows/node-ci-reusable.yml3
4# If it's in a different repository5uses: {owner}/{repo}/.github/workflows/{filename}@{ref}
```

To pass values, you use the with block for inputs and the `secrets` block for sensitive credentials. Remember that environment variables set at the top workflow level in the caller aren’t passed down to the called workflow. If you need variables inside the called workflow, you have to pass them explicitly as inputs or use repository-level variables through the vars context.

Here’s an example of a caller workflow (`.github/workflows/app-delivery.yml`) that runs our Node.js CI template and conditionally deploys the app if everything passes:

.github/workflows/app-delivery.yml

```
1name: Build and Release App2
3on:4  push:5    branches:6      - main7
8jobs:9  # Job 1: Call our centralized CI template10  run-ci:11    uses: corporate-org/shared-workflows/.github/workflows/node-ci-reusable.yml@v1.2.012    with:13      node-version: '22'14      run-coverage: true15      config-json: '{"region": "us-west-2", "environment": "production"}'16    secrets: inherit # Safely passes all repository secrets down17
18  # Job 2: Run a deployment step only if the CI template finishes successfully19  deploy-application:20    needs: run-ci21    if: ${{ needs.run-ci.outputs.build-status == 'success' }}22    runs-on: ubuntu-latest23    steps:24      - name: Deploy Artifacts25        run: echo "Deploying application to production..."
```

See how clean that caller file is? It orchestrates a multi-step pipeline with barely any code duplication.

While `secrets: inherit` is convenient and clean, explicit mapping (like `NPM_TOKEN: ${{ secrets.REGISTRY_TOKEN }}`) is often preferred in highly regulated environments to make audits easier and limit credential exposure.

## [Security governance and cross-repository permissions](#security-governance-and-cross-repository-permissions)

How do you enforce least-privilege access and keep private workflows private across repositories?

Sharing workflows within a single repo is easy, but sharing them securely across an entire enterprise requires a bit more care. To protect private build configurations and sensitive credentials, GitHub has strict permissions boundaries.

If your shared workflows live in a private repository, other repositories won’t be able to access them unless you explicitly allow it in the settings.

Here is how you configure this access:

1.  Go to the main page of your private repository hosting the workflows.
    
2.  Click **Settings** right under the repo name.
    
3.  In the left sidebar, click **Actions**, then click **General**.
    
4.  Scroll down to the **Access** section.
    
5.  Choose **Accessible from repositories in the ‘ORGANIZATION-NAME’ organization**. If you’re on an enterprise plan, you can choose to share across all organizations owned by your enterprise.
    
6.  Click **Save**.
    

```
1┌────────────────────────────────────────────────────────┐2│               Settings > Actions > General              │3├────────────────────────────────────────────────────────┤4│  Access Control Policies                               │5│                                                        │6│  ( ) Not accessible from other repositories            │7│                                                        │8│  (•) Accessible from repositories in the               │9│      'corporate-org' organization                      │10│                                                        │11│  ( ) Accessible from all organizations in the          │12│      Enterprise Account                                │13└────────────────────────────────────────────────────────┘
```

You should also keep in mind how outside collaborators interact with these shared workflows. If an outside collaborator has write access to a caller repository, they can run the workflow and view the logs. To prevent unauthorized access, GitHub passes a temporary, scoped token to the runner. This token automatically expires after one hour, so a leaked token buys an attacker very little.

If you’re working across separate organizations, the repository hosting the workflows must be public. The calling organization will also need to allow external workflows under **Organization settings -> Actions -> General**.

To make your security even tighter, you can use OpenID Connect (OIDC) with your cloud providers (like AWS, GCP, or Azure). Instead of storing long-lived, static cloud keys as GitHub secrets, GitHub issues short-lived JWT tokens on the fly.

Here’s what an OIDC-enabled step looks like inside a reusable workflow:

```
1# Example step inside your reusable workflow using OIDC for keyless auth2- name: Configure AWS Credentials via OIDC3  uses: aws-actions/configure-aws-credentials@v44  with:5    # Use a role ARN instead of storing access keys6    role-to-assume: arn:aws:iam::123456789012:role/github-actions-ci-role7    aws-region: us-east-18    # Request a JWT token from GitHub's OIDC provider9    audience: sts.amazonaws.com
```

## [Versioning strategies and release management](#versioning-strategies-and-release-management)

How do you publish and maintain workflow updates without breaking every pipeline that depends on them?

Because multiple teams depend on your shared CI/CD library, you have to treat your workflows like production code. If you push an untested change directly to your main branch, you could accidentally break builds across the entire company.

Publish immutable release tags (v1.3.0) and a moving major tag (v1) that advances with backward-compatible changes. Callers pin to @v1 to get safe updates automatically, or to a full commit SHA when they need maximum supply-chain safety. Never pin to main.

To keep things stable, you should adopt a clear versioning strategy. Most teams rely on three main pinning methods:

-   **Pinning to a Semantic Version (Best for Stability):** Referencing a patch version (like `@v1.2.0`) means nothing changes under the hood without you knowing. It is as stable as pinning gets.
-   **Pinning to a Major Version Tag:** Pinning to a major tag (like `@v1`) lets you push safe minor updates and security patches automatically without breaking anything for the end-user.
-   **Pinning to a Branch:** Referencing a branch (like `@main`) is great for testing features quickly, but it’s dangerous for production because any change can break your pipelines instantly.

If you’re managing a major version tagging strategy, you’ll need to update your tags via the command line when promoting releases:

Terminal window

```
1# Create and push a specific release tag2git tag -a v1.2.0 -m "Release version 1.2.0"3git push origin v1.2.04
5# Force-update your major tag to point to this new commit6git tag -fa v1 -m "Point v1 tag to v1.2.0"7git push origin v1 --force
```

In highly secure environments, pinning to a mutable Git tag can still be a risk, since tags can technically be rewritten. The safest option is pinning directly to an immutable Git commit SHA (like `@3a82c4...`). Since a SHA can’t be repointed, your callers always run exactly the code you reviewed, which closes off the retagging trick behind a lot of supply chain attacks. You can use tools like Dependabot to open PRs automatically when new versions are released, so you get that safety without doing the bumps by hand.

```
1# Secure caller using an immutable commit SHA2jobs:3  secure-ci:4    # Pinned to a specific commit SHA for security5    uses: corporate-org/shared-workflows/.github/workflows/node-ci-reusable.yml@3a82c4b8b6c4b2b2b2b2b2b2b2b2b2b2b2b2b2b26    secrets: inherit
```

## [Organizing a dedicated workflows repository](#organizing-a-dedicated-workflows-repository)

What repository layout and templating make shared CI/CD configs easy to hand out?

As your shared library grows, you should host your workflows in a dedicated, read-only repository, like `your-org/shared-workflows`. This keeps your pipelines separate from application code, makes access control simple, and keeps your project history clean.

One platform quirk to keep in mind: GitHub Actions forces all reusable workflows to live in the `.github/workflows/` directory. This flat layout can make independent versioning difficult for tools like Release Please, which usually depend on folder separation to detect independent packages. Because of this, most teams treat the entire repository as a single package and version all workflows under one release tag.

Here is a typical layout:

-   Directoryyour-org/shared-workflows
    
    -   Directory.github/
        
        -   Directoryworkflows/
            
            -   **node-ci-reusable.yml**
            -   python-ci-reusable.yml
            -   docker-publish-reusable.yml
            
        
    

To help developers adopt these standard pipelines quickly, you can set up starter templates in a repository named `.github` (e.g., `your-org/.github`). When someone creates a new repository in your organization, these templates will show up directly in their Actions initialization menu.

To set this up, create a folder named `workflow-templates` inside your `.github` repository. This folder should hold your template YAML file and a JSON metadata file that describes it.

The folder ends up looking like this:

-   Directoryyour-org/.github
    
    -   Directoryworkflow-templates/
        
        -   ci-nodejs.yml
        -   **ci-nodejs.properties.json**
        
    

Here is a sample properties file:

workflow-templates/ci-nodejs.properties.json

```
1{2  "name": "Node.js Enterprise CI",3  "description": "Standardized Node.js build pipeline using our approved reusable workflow.",4  "iconName": "nodejs",5  "categories": ["Continuous Integration", "Node"]6}
```

Inside your template file, you can use the `$default-branch` placeholder so GitHub dynamically swaps it with the repository’s default branch on setup:

workflow-templates/ci-nodejs.yml

```
1name: Node.js CI Pipeline2
3on:4  push:5    branches: [$default-branch]6  pull_request:7    branches: [$default-branch]8
9jobs:10  run-ci:11    # Automatically targets your organization's shared workflow12    uses: your-org/shared-workflows/.github/workflows/node-ci-reusable.yml@v113    secrets: inherit
```

## [Advanced testing patterns, optimization, and maintenance](#advanced-testing-patterns-optimization-and-maintenance)

How do you test workflow changes locally and keep execution fast inside the platform’s limits?

Testing updates to a shared workflow can be tricky. GitHub Actions validates your entire pipeline structure before it ever starts a runner. If you try to run a test workflow that points to an unmerged change on a remote branch, the pre-flight check will fail, crashing the run immediately.

To bypass this without cluttering your production code with messy test flags, you can use a “Patch-on-Test” strategy. This lets you keep your production files pointing to clean references, while dynamically swapping them for local relative paths on the runner during test runs.

Here is a test workflow (`.github/workflows/test-suite.yml`) that checks out the repository and uses a `sed` command to patch the references right before running them:

.github/workflows/test-suite.yml

```
1name: Test Shared Workflows2
3on:4  push:5    branches:6      - 'feature/*'7  pull_request:8
9jobs:10  test-workflow:11    runs-on: ubuntu-latest12    steps:13      - name: Checkout Code14        uses: actions/checkout@v415
16      # Use sed to temporarily swap the remote ref for the local relative file path17      - name: Patch Reusable Reference for Testing18        run: |19          sed -i 's|your-org/shared-workflows/.github/workflows/node-ci-reusable.yml@v1|./.github/workflows/node-ci-reusable.yml|g' .github/workflows/integration-test-caller.yml20
21      # Run the caller workflow using our local file changes22      - name: Run Integration Tests23        uses: ./.github/workflows/integration-test-caller.yml
```

To solve this natively, the GitHub Actions team proposed the relative path syntax prefix `$/`. When this is fully supported, writing `uses: $/path/to/action` tells the runner to resolve the path relative to the workflow file that called it, keeping references safe and clean across PRs and releases.

As your CI/CD platform scales, you should also focus on keeping execution times fast and costs low:

-   **Caching Dependencies:** Use deterministic installation commands (like `npm ci` or `yarn`/`pnpm` commands with `--frozen-lockfile`) to speed up builds. Keep an eye on storage limits, since GitHub caps caching at 10 GB per repository.
-   **Parallel Execution:** Run independent jobs in parallel instead of chaining them sequentially.
-   **Concurrency Controls:** Use concurrency keys to automatically cancel older, outdated runs when a developer pushes a new commit to the same branch.
-   **Bypassing Matrix Limits:** While GitHub limits job matrices to 256 combinations, you can bypass this by nesting reusable workflows. By nesting matrices up to three levels deep, you can theoretically run up to 256^3 (over 16 million) jobs per run, which is perfect for heavy matrix testing.

These patterns give you a CI/CD library that’s secure, fast, and easy for your team to maintain.

## [Frequently Asked Questions](#frequently-asked-questions)

No, environment variables defined in the env context of a caller workflow don’t propagate to the called reusable workflow. Similarly, any environment variables you set inside the called workflow won’t be accessible back in the caller workflow. You must pass data explicitly using inputs or return it to the caller via job outputs.

GitHub Actions supports up to 10 nested levels of reusable workflows. Additionally, you can call a maximum of 50 unique reusable workflows across your entire nested execution tree in a single run.

You can use the `secrets: inherit` directive inside your caller job. This automatically passes all of your caller repository’s secrets, along with your organization-level secrets, straight to the called reusable workflow.

No, you can’t publish reusable workflows to the GitHub Marketplace. They can only be shared by hosting them in public, internal, or private repositories and referencing them directly by their repository path and Git reference.

By default, your called workflow inherits the GITHUB\_TOKEN permissions of the caller. You can tighten those privileges inside your reusable workflow by declaring a custom permissions block under the workflow\_call trigger. A called workflow can only narrow what the caller granted, never widen it.

GitHub Actions runs a pre-flight static analysis on your entire pipeline graph before it actually runs anything. If your workflow references a remote branch or tag that doesn’t exist yet, this check fails and stops your pipeline in its tracks. This happens regardless of any conditional if statements, which is why we use the “Patch-on-Test” strategy.

## [Conclusion](#conclusion)

Reusable workflows turn CI/CD from a copy-paste chore into a single source of truth. By defining your standard pipelines once with `workflow_call`, calling them with a clean `uses` line, and locking everything down with explicit secrets and OIDC, you get pipelines that are easier to audit and far less prone to drift. Pair that with a clear versioning strategy (semantic tags or immutable SHAs), a dedicated workflows repository, and a “Patch-on-Test” approach for safe changes, and you’ve built a shared CI library that scales with your organization instead of fighting it.

## [References](#references)

1.  How to Create Reusable Workflows in GitHub Actions - OneUptime, accessed on May 27, 2026, [https://oneuptime.com/blog/post/2026-01-25-github-actions-reusable-workflows/view](https://oneuptime.com/blog/post/2026-01-25-github-actions-reusable-workflows/view)
2.  Reusing workflow configurations - GitHub Docs, accessed on May 27, 2026, [https://docs.github.com/en/actions/concepts/workflows-and-actions/reusing-workflow-configurations](https://docs.github.com/en/actions/concepts/workflows-and-actions/reusing-workflow-configurations)
3.  Organization best practices for reusable workflows and actions for an enterprise? - GitHub Community, accessed on May 27, 2026, [https://github.com/orgs/community/discussions/171037](https://github.com/orgs/community/discussions/171037)
4.  Best practices for structuring complex GitHub Actions workflows? - GitHub Community, accessed on May 27, 2026, [https://github.com/orgs/community/discussions/187543](https://github.com/orgs/community/discussions/187543)
5.  GitHub Actions Workflows: Patterns & Best Practices - DEV Community, accessed on May 27, 2026, [https://dev.to/thesius\_code\_7a136ae718b7/github-actions-workflows-github-actions-patterns-best-practices-pge](https://dev.to/thesius_code_7a136ae718b7/github-actions-workflows-github-actions-patterns-best-practices-pge)
6.  New releases for GitHub Actions - November 2025 - GitHub Changelog, accessed on May 27, 2026, [https://github.blog/changelog/2025-11-06-new-releases-for-github-actions-november-2025/](https://github.blog/changelog/2025-11-06-new-releases-for-github-actions-november-2025/)
7.  Reusable Workflow Depth Limit - GitHub Community, accessed on May 27, 2026, [https://github.com/orgs/community/discussions/8488](https://github.com/orgs/community/discussions/8488)

Was this useful?

## Tags

[#GitHub Actions](/blog/tags/github-actions)[#Reusable Workflows](/blog/tags/reusable-workflows)[#Composite Actions](/blog/tags/composite-actions)[#Workflow call](/blog/tags/workflow_call)[#CI/CD](/blog/tags/cicd)[#OIDC](/blog/tags/oidc)[#DevSecOps](/blog/tags/devsecops)[#Versioning](/blog/tags/versioning)[#Pipeline Templates](/blog/tags/pipeline-templates)[#DRY](/blog/tags/dry)

## Share

[Facebook](https://facebook.com/sharer/sharer.php?u=https%3A%2F%2Fmkabumattar.com%2Fblog%2Fpost%2Fgithub-actions-reusable-workflows-shared-ci-library "Share on Facebook")[Twitter](https://twitter.com/intent/tweet/?text=GitHub%20Actions%20Reusable%20Workflows%3A%20Build%20a%20Shared%20CI%20Library%20Across%20All%20Your%20Repos&url=https%3A%2F%2Fmkabumattar.com%2Fblog%2Fpost%2Fgithub-actions-reusable-workflows-shared-ci-library "Share on Twitter")[LinkedIn](https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fmkabumattar.com%2Fblog%2Fpost%2Fgithub-actions-reusable-workflows-shared-ci-library&title=GitHub%20Actions%20Reusable%20Workflows%3A%20Build%20a%20Shared%20CI%20Library%20Across%20All%20Your%20Repos&summary=Simplifying%20and%20securing%20CI%2FCD%20at%20scale%20with%20GitHub%20Actions%20reusable%20workflows%3A%20the%20differences%20between%20reusable%20workflows%20and%20composite%20actions%2C%20OIDC%20keyless%20authentication%2C%20versioning%20strategies%2C%20and%20testing%20methods%20like%20%22Patch-on-Test%22%20for%20a%20centralized%20pipeline%20library.&source=https://mkabumattar.com "Share on LinkedIn")[WhatsApp](https://wa.me/?text=GitHub%20Actions%20Reusable%20Workflows%3A%20Build%20a%20Shared%20CI%20Library%20Across%20All%20Your%20Repos%20https%3A%2F%2Fmkabumattar.com%2Fblog%2Fpost%2Fgithub-actions-reusable-workflows-shared-ci-library "Share on WhatsApp")[Telegram](https://t.me/share/url?url=https%3A%2F%2Fmkabumattar.com%2Fblog%2Fpost%2Fgithub-actions-reusable-workflows-shared-ci-library&text=GitHub%20Actions%20Reusable%20Workflows%3A%20Build%20a%20Shared%20CI%20Library%20Across%20All%20Your%20Repos "Share on Telegram")[Reddit](https://www.reddit.com/submit?url=https%3A%2F%2Fmkabumattar.com%2Fblog%2Fpost%2Fgithub-actions-reusable-workflows-shared-ci-library&title=GitHub%20Actions%20Reusable%20Workflows%3A%20Build%20a%20Shared%20CI%20Library%20Across%20All%20Your%20Repos "Share on Reddit")[Hacker News](http://news.ycombinator.com/submitlink?u=https%3A%2F%2Fmkabumattar.com%2Fblog%2Fpost%2Fgithub-actions-reusable-workflows-shared-ci-library&t=GitHub%20Actions%20Reusable%20Workflows%3A%20Build%20a%20Shared%20CI%20Library%20Across%20All%20Your%20Repos "Share on Hacker News")[Pinterest](https://pinterest.com/pin/create/button/?url=https%3A%2F%2Fmkabumattar.com%2Fblog%2Fpost%2Fgithub-actions-reusable-workflows-shared-ci-library&media=&description=Simplifying%20and%20securing%20CI%2FCD%20at%20scale%20with%20GitHub%20Actions%20reusable%20workflows%3A%20the%20differences%20between%20reusable%20workflows%20and%20composite%20actions%2C%20OIDC%20keyless%20authentication%2C%20versioning%20strategies%2C%20and%20testing%20methods%20like%20%22Patch-on-Test%22%20for%20a%20centralized%20pipeline%20library. "Share on Pinterest")[Email](<mailto:?subject=GitHub%20Actions%20Reusable%20Workflows%3A%20Build%20a%20Shared%20CI%20Library%20Across%20All%20Your%20Repos&body=Check out this article: https%3A%2F%2Fmkabumattar.com%2Fblog%2Fpost%2Fgithub-actions-reusable-workflows-shared-ci-library>)

## Comments

## You might also enjoy

More posts on similar topics

[![GitHub Actions vs. GitLab CI for Monorepos: Which One Wins?](/_astro/hero.7c9S_WKE_ZmGOGN.webp)](/blog/post/github-actions-vs-gitlab-ci-for-monorepos)

## [GitHub Actions vs. GitLab CI for Monorepos: Which One Wins?](/blog/post/github-actions-vs-gitlab-ci-for-monorepos)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [DevOps](/blog/categories/devops)
-   [CI/CD](/blog/categories/cicd)
-   [Monorepos](/blog/categories/monorepos)
-   [Software Development](/blog/categories/software-development)

The world of building software is always changing, and how teams organize their code can really affect how well they work. One way that's become pretty popular is using a monorepo. That's just keeping

[#GitHub Actions](/blog/tags/github-actions)[#GitLab CI](/blog/tags/gitlab-ci)[#Monorepo](/blog/tags/monorepo)+7 tags

[read more](/blog/post/github-actions-vs-gitlab-ci-for-monorepos)

[![Taming the Chaos: Let's Sort Out Those Flaky CI/CD Pipelines](/_astro/hero.CNGGank__Zjy3fe.webp)](/blog/post/troubleshooting-flaky-ci-cd-pipelines)

## [Taming the Chaos: Let's Sort Out Those Flaky CI/CD Pipelines](/blog/post/troubleshooting-flaky-ci-cd-pipelines)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [CI/CD](/blog/categories/cicd)
-   [Testing](/blog/categories/testing)
-   [DevOps](/blog/categories/devops)
-   [Automation](/blog/categories/automation)
-   [Pipeline Reliability](/blog/categories/pipeline-reliability)

Ever get super frustrated with your CI/CD pipeline? You know, the one that sometimes works perfectly and other times just throws a random tantrum? You push your code, the pipeline starts doing its thi

[#Flaky Tests](/blog/tags/flaky-tests)[#CI/CD Pipelines](/blog/tags/cicd-pipelines)[#Test Automation](/blog/tags/test-automation)+5 tags

[read more](/blog/post/troubleshooting-flaky-ci-cd-pipelines)

[![Database DevOps: Making PostgreSQL and MongoDB CI/CD Feel Natural](/_astro/hero.Dj-kXEQP_1Sx2F5.webp)](/blog/post/database-devops-ci-cd-postgresql-mongodb)

## [Database DevOps: Making PostgreSQL and MongoDB CI/CD Feel Natural](/blog/post/database-devops-ci-cd-postgresql-mongodb)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Database DevOps](/blog/categories/database-devops)
-   [CI/CD](/blog/categories/cicd)
-   [PostgreSQL](/blog/categories/postgresql)
-   [MongoDB](/blog/categories/mongodb)
-   [Automation](/blog/categories/automation)
-   [DevOps](/blog/categories/devops)

Ever feel like your app deployments are super slick, but then you hit the database part, and things just... stop? It's frustrating, right? You've got this smooth CI/CD pipeline for your code, but data

[#Database CI/CD](/blog/tags/database-cicd)[#PostgreSQL](/blog/tags/postgresql)[#MongoDB](/blog/tags/mongodb)+10 tags

[read more](/blog/post/database-devops-ci-cd-postgresql-mongodb)

[![What is a CI/CD?](/_astro/hero.ByLLqYEs_180Vvv.webp)](/blog/post/what-is-a-ci-cd)

## [What is a CI/CD?](/blog/post/what-is-a-ci-cd)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [DevOps](/blog/categories/devops)
-   [Software Development](/blog/categories/software-development)
-   [Automation](/blog/categories/automation)
-   [CI/CD](/blog/categories/cicd)

Introduction Continuous Integration and Continuous Delivery are two of the most important concepts in DevOps. This article covers what CI/CD is and how it fits into a software development process.

[#Continuous Integration](/blog/tags/continuous-integration)[#Continuous Delivery](/blog/tags/continuous-delivery)[#Continuous Deployment](/blog/tags/continuous-deployment)+7 tags

[read more](/blog/post/what-is-a-ci-cd)

[![Modular Terraform for Scalable Infrastructure as Code](/_astro/hero.kBsnpbcJ_1mG2Sh.webp)](/blog/post/modular-terraform-scalable-iac-guide)

## [Modular Terraform for Scalable Infrastructure as Code](/blog/post/modular-terraform-scalable-iac-guide)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Infrastructure as Code](/blog/categories/infrastructure-as-code)
-   [Terraform](/blog/categories/terraform)
-   [DevOps](/blog/categories/devops)
-   [Cloud Engineering](/blog/categories/cloud-engineering)
-   [Automation](/blog/categories/automation)

Businesses need infrastructure that's flexible and can grow fast, and managing it by hand doesn't scale. Infrastructure as Code, or IaC, changed how we build and manage those digital foundations. IaC

[#Terraform](/blog/tags/terraform)[#Infrastructure as Code](/blog/tags/infrastructure-as-code)[#IaC](/blog/tags/iac)+12 tags

[read more](/blog/post/modular-terraform-scalable-iac-guide)

[![Streamlining GitHub Organization Management with Terraform](/_astro/hero.DJ7g8CQA_Z1UlNiP.webp)](/blog/post/streamlining-github-organization-management-with-terraform)

## [Streamlining GitHub Organization Management with Terraform](/blog/post/streamlining-github-organization-management-with-terraform)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [DevOps](/blog/categories/devops)
-   [Infrastructure as Code](/blog/categories/infrastructure-as-code)
-   [GitHub](/blog/categories/github)
-   [Automation](/blog/categories/automation)
-   [Terraform](/blog/categories/terraform)

Managing a GitHub organization manually can become increasingly complex as teams grow and projects multiply. For DevOps and DevSecOps engineers, automation is how you keep things consistent and cut do

[#Terraform](/blog/tags/terraform)[#GitHub](/blog/tags/github)[#IaC](/blog/tags/iac)+7 tags

[read more](/blog/post/streamlining-github-organization-management-with-terraform)

6 related posts
