Free — no signup required

Actions vs. Reusable Workflows

3 min read

Don't Repeat Yourself (DRY) at Scale

As your organization grows, you will find yourself copy-pasting the same deployment logic into 50 repositories. When a security team mandates a new scanning step, you now have 50 files to update. GitHub provides two complementary mechanisms to share and standardize logic: Composite Actions and Reusable Workflows.

1. Composite Actions (action.yml)

A Composite Action is a reusable bundle of steps stored in its own repository (or a subdirectory of a repository). Think of it as a function you can call from any workflow.

  • What it abstracts: A sequence of steps — shell commands and other action calls.
  • Use case: "Set up our internal Python environment, authenticate to our private PyPI feed, and install dependencies." This is a 5-step sequence that every Python project needs.
  • How it's called: a single uses: line referencing the action's repository and version.
  • Inputs and outputs: Composite Actions accept inputs: and can set outputs: for the calling workflow to consume.

A composite action's action.yml declares a name, description, its typed inputs (like a Python version with a default), and a runs block of type composite listing the steps it bundles — for example, invoking the standard Python setup action with the given version, then running a shell step that points pip at an internal private package feed.

2. Reusable Workflows (workflow_call)

A Reusable Workflow is an entire workflow file that can be invoked by other workflows. It is not just steps — it includes full jobs with their own runner environments, environment protection rules, and secret handling.

  • What it abstracts: An entire deployment pipeline, including security gates, approval environments, and post-deployment verification.
  • Use case: "Every team that deploys to production must use the company-approved pipeline that includes SAST scanning, image signing, and a manual approval gate."
  • How it's called: a job in the calling repository's workflow sets uses: to the reusable workflow's path and version instead of runs-on:, passes typed with: inputs, and can inherit all of the caller's secrets in one line. The reusable workflow itself, on the other end, declares a workflow_call trigger with its own typed inputs and required secrets — the contract that callers must satisfy.

Choosing between them:

Concern Composite Action Reusable Workflow
Abstraction level Steps Jobs
Has its own runner No (shares caller's runner) Yes (fresh runner per job)
Can enforce environment gates No Yes
Versioned independently Yes Yes
Best for Setup scripts, utility tasks Full deployment pipelines

The organizational recommendation: Use Composite Actions for shared tooling (setup, lint, test utilities). Use Reusable Workflows to enforce company-wide deployment policies that teams cannot bypass.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free