GitHub

What Are GitHub Actions? A Quick Guide

What Are GitHub Actions? A Quick Guide

GitHub Actions runs automated workflows from inside a GitHub repository. Each workflow is a YAML file, and it starts when something happens in the repo, such as a push or a pull request, or a schedule you set.

Teams build, test and deploy code with it on Linux, Windows and macOS runners, so there’s no separate CI server to host. The same workflows also handle small repository chores, like labeling new issues.

Billing has a quirk worth knowing early. Anyone with write access can trigger a run, but on private repositories the minutes are charged to the repository owner, not to whoever started it (GitHub Docs, 2026).

What Are GitHub Actions?

YouTube player

Workflows start from repository events. Opening a pull request, pushing a commit, filing an issue, hitting a schedule or clicking a button by hand all work as triggers.

GitHub Docs describe the platform as a way to automate the build, test and deployment pipeline. Their examples are building and testing every pull request, or deploying merged ones to production.

Most teams begin with the continuous integration routine of building and testing every change before it merges. Deployment steps get added once the tests prove reliable.

The scope goes past delivery, though. GitHub’s overview notes that a workflow can add a label the moment an issue opens, which sits well outside traditional DevOps work.

GitHub treats the name as a singular noun for the platform (“GitHub Actions is…”). Lowercase “actions” means the reusable units inside a workflow.

GitHub made the CI/CD version generally available on November 13, 2019, according to its own 2019 announcement, and Microsoft’s Azure team posted a matching update the same day.

Standard hosted runners are free and unlimited on public repositories (GitHub Docs, as of October 2026). Private repositories draw on a plan allowance of free minutes first.

Why is GitHub the heart of open source?

Uncover GitHub statistics: developer community growth, repository trends, collaboration patterns, and the platform that powers modern software development.

Explore GitHub Data →

It isn’t a CI server you install and patch, and it doesn’t replace GitHub, since it runs on top of the repository. It also isn’t limited to builds and tests.

How Do the Parts of GitHub Actions Fit Together?

YouTube player

An event triggers a workflow, the workflow holds one or more jobs, each job runs on a single runner, and each job is a sequence of steps that either run a script or call an action.

Workflows and events

A workflow is the automated process itself, defined by a YAML file checked into the repository. One repository can hold several, say one for pull request tests and another for release deployments.

The event is whatever repository activity starts a run. Opening a pull request, pushing a commit, creating an issue, a schedule, a REST API post and a manual trigger all count (GitHub Docs).

Jobs and steps

A job is a set of steps executed on the same runner. Jobs have no dependencies by default, so they run in parallel. The needs keyword changes that by making one job wait for another, which is how a packaging job ends up following several parallel builds.

Looking to sharpen your Git skills? Branching, merging, rebasing, and everything else you need - including git rebase, git stash, and commit workflows - is on one page in the Git Cheat Sheet.

Steps run in order on a shared filesystem, and each one is either a shell script or an action. Environment variable changes don’t carry from one step to the next, because every step runs in its own process.

The failure rule trips people up. If a job fails or is skipped, every job that needs it is skipped too, unless a conditional such as always() overrides that.

Actions and runners

An action is a reusable unit that replaces repeated script code. Checking out the repository and setting up a toolchain are the usual uses. Authenticating to a cloud provider is another.

An action is one piece of the process. The runner is the server that executes a job, one job at a time.

On GitHub-hosted runners, every workflow run gets a freshly provisioned virtual machine. The hosting options are compared further down.

How Do You Write a Workflow File?

These files live in the .github/workflows directory of the repository and end in .yml or .yaml. A minimal file needs a trigger under on and at least one job under jobs. That job needs a runs-on value naming the machine.

Nothing else is mandatory. Filters, permissions, environment variables and concurrency rules get added as the workflow grows.

YAML punishes sloppy spacing, so a YAML cheat sheet is worth keeping open for the first few files.

Which events trigger a workflow?

EventStarts a run whenLimit to know
pushA commit lands on a branch or tagBranch, tag and path filters narrow it
pull\_requestActivity happens on a pull requestA skipped run leaves required checks Pending
scheduleA cron time arrivesRuns on the default branch only
workflow\_dispatchSomeone starts it by handWorks only if the file is on the default branch

Scheduled workflows use POSIX cron syntax with five fields and run in UTC unless a timezone is set. The shortest interval is once every 5 minutes (GitHub Docs, October 2026).

List several events and any one of them starts a run. If two fire at the same moment, two runs start.

How do you create a first workflow?

  1. Create the .github/workflows directory in the repository root.
  2. Add a YAML file there, such as ci.yml, and give the workflow a name.
  3. Set the trigger under on, for example push to the main branch.
  4. Define a job with runs-on: ubuntu-latest.
  5. Add steps: actions/checkout first, then a run step with your test command.
  6. Commit and push, then open the Actions tab to watch the run.

GitHub Docs recommend referencing an action by Git ref, SHA or Docker tag, and they call the commit SHA the safest option for stability and security.

The usual failure is a path or branch filter that skips the workflow. Its checks stay Pending, and a pull request that requires them can’t merge. Indentation slips are the other frequent culprit, and a YAML validator catches them before the push.

Where Do GitHub Actions Jobs Run?

Every job lands on a runner. GitHub-hosted ones are Ubuntu, Windows or macOS machines provisioned fresh for each job, and self-hosted ones are machines you run yourself. The runs-on value in the workflow file picks which.

Hosted or self-hosted

FactorGitHub-hostedSelf-hosted
MachineNew VM per jobYour hardware or cloud
UpkeepGitHub handles upgradesYou patch and maintain
SystemsUbuntu, Windows, macOSAny OS or hardware you provide
Job time limit6 hours5 days
runs-on labelubuntu-latest[self-hosted, linux]

The standard ubuntu-latest runner gets 4 CPUs and 16 GB of RAM on public repositories, and 2 CPUs and 8 GB on private ones (GitHub Docs, October 2026).

Linux and Windows hosted runners sit on virtual machines in Microsoft Azure, and the runner application is a fork of the Azure Pipelines Agent. Single-CPU runners are the exception, hosted in a container on a shared VM.

Pros and cons of each runner type

GitHub-hosted runners need no maintenance and hand you a clean machine every job. The preinstalled tools are refreshed weekly.

The downsides are real, though. Hardware is fixed unless you move to larger runners (Team and Enterprise Cloud plans), and minutes are metered on private repositories. During a service outage, a workflow run is discarded if it can’t be queued within 30 minutes of being triggered (a queued run that no hosted runner picks up within 45 minutes is discarded too).

Self-hosted runners allow custom hardware and any operating system, and jobs can run up to 5 days. Patching and cleanup fall to you, along with access control.

Going self-hosted means running your own build server. For a small team on public repositories, the free hosted runners are usually enough.

Matrix builds, caches and artifacts

A matrix runs the same job once per combination of variables, such as operating system and language version. A single workflow run is capped at 256 matrix jobs (GitHub Docs limits reference), and each combination is billed as its own job on private repositories.

Dependency caching restores installed packages between runs, keyed on a hash of the lockfile. Workflow artifacts are files a job produces, such as test reports or builds, which later jobs and people can download after the run.

Caches need care on untrusted triggers. GitHub Docs warn that setting cache-mode to write on a low-trust trigger bypasses the default read-only restriction and reintroduces cache-poisoning risk.

What Is the Actions Marketplace and How Do You Reuse Workflow Logic?

YouTube player

Prebuilt actions live in GitHub’s Marketplace catalog, and workflows call them with the uses keyword. Inside your own repositories, composite actions and reusable workflows cover most reuse, while workflow templates handle the starting point.

Action types

JavaScript actions run on the runner’s bundled Node runtime, which is Node 24 now that Node 20 was removed on September 23, 2026. Docker container actions ship their code and toolchain in an image, and the job must run in a Linux environment. Composite actions bundle several steps into one step, with no jobs and no direct secret access.

A container action packages everything inside a Docker container, which fixes the toolchain version but rules out Windows and macOS runners.

GitHub’s September 23, 2026 changelog retired Node 20 and told maintainers to set runs.using to node24 and publish a new release. Workflow authors need the latest action versions that support Node 24.

Floating major tags such as v6 help here. If the author follows semantic versioning, those tags carry fixes without a workflow edit, though GitHub Docs leave that at the author’s discretion.

Reusable workflows or composite actions?

YouTube player

Both avoid copy-paste, but they sit at different levels. A reusable workflow shares an entire workflow, jobs and all. A composite action shares a block of steps inside one job.

FeatureReusable workflowComposite action
Called fromA jobA step
Can contain jobsYesNo
LoggingEvery step loggedOne step in the caller’s log
SecretsCan use themCannot use them
MarketplaceCannot be publishedCan be published

If the shared logic needs its own machine type, go with a reusable workflow. A handful of steps is composite action territory.

Actions inside a called workflow run as part of the caller, so actions/checkout pulls the caller’s repository, not the one that holds the called workflow (GitHub Docs).

Workflow templates

GitHub inspects a repository’s language and suggests a matching template. A Node.js project gets one that installs packages and runs tests.

The categories are CI, deployment, security and automation. They work best as a starting point, and the actions/starter-workflows repository lists every one.

How Much Do GitHub Actions Cost?

YouTube player

Runner type and billable minutes beyond the plan allowance drive most of the bill, and stored artifacts and caches add to it. Minutes are charged to the repository owner, not to whoever triggered the run (GitHub Docs, October 2026).

Key figures

Included minutes per month come to 2,000 on Free, 3,000 on Pro and Team, and 50,000 on Enterprise Cloud. Overage runs $0.006 per minute for Linux 2-core, $0.010 for Windows 2-core and $0.062 for macOS.

Cache storage is 10 GB included per repository on every plan, separate from artifact storage. Hosted runner prices also dropped by up to 39% from January 1, 2026.

The first three figures come from GitHub’s billing documentation as of October 2026. The price cut comes from GitHub’s December 2025 changelog.

The self-hosted runner charge: announced, then postponed

GitHub’s December 16, 2025 announcement described a new $0.002 per-minute platform charge on self-hosted runner usage, starting March 1, 2026 and counted against included minutes.

An update on the same changelog entry says GitHub postponed that change to re-evaluate its approach. The hosted runner price cut stayed.

As of October 2026, GitHub’s billing page still lists self-hosted runner usage as free. Some third-party pricing roundups keep describing the charge as active, so check the billing documentation before budgeting.

What pushes the bill up

A re-run bills again on top of the failed attempt. Larger runners are always charged, even on public repositories, and without a payment method on file, usage is blocked once the quota runs out.

Copilot code review also consumes Actions minutes on private repositories (effective June 1, 2026, per GitHub’s April 2026 changelog).

Storage accrues hourly. Deleting build artifacts stops future charges but does not erase what already accrued in the billing cycle.

How Do You Secure a GitHub Actions Workflow?

YouTube player

Start with the GITHUB\_TOKEN and give it only the permissions each job needs. Pin third-party actions to commit SHAs, keep long-lived cloud credentials out of secrets, and treat pull request content as untrusted input. Real incidents have used each of those paths.

Token permissions and secrets

Set the GITHUB\_TOKEN to read-only for repository contents, then raise permissions per job.

Anyone with write access to a repository can read every secret configured in it, which surprises people. Redaction needs an exact match, so a JSON or YAML blob stored as one secret can leak through logs. Store each value as its own secret instead. A JWT or Base64 string generated from a secret has to be registered as a secret too.

Environment secrets can also require an approving reviewer before a job reads them.

If a secret reaches a log unredacted, delete the log and rotate the secret (GitHub Docs, October 2026).

Cloud credentials with OpenID Connect

Workflows that deploy to a cloud provider can authenticate through OpenID Connect and drop stored keys. It swaps them for short-lived tokens, a form of token-based authentication that expires on its own.

GitHub Docs note that custom claims for OIDC are unavailable on AWS, so that’s a gap if your setup relies on them.

Third-party actions

A compromised action sees every secret the job sees.

Repository and organization policies can require every action to be pinned to a full-length commit SHA. That turns pinning from advice into a setting.

The Verified creator badge on the Marketplace signals that GitHub confirmed the author’s identity. It does not stop a tag from being moved if the author’s repository is taken over.

Pins go stale. Dependabot version updates open pull requests that bump SHA pins, but Dependabot alerts only fire for actions that use semantic versioning, not for SHA-pinned references.

A CODEOWNERS entry for .github/workflows routes every workflow change through a designated reviewer. It puts a code review process gate on the pipeline itself.

Untrusted pull request input

On September 17, 2026, GitHub made workflow execution protections generally available. They include a default rule that disables pull\_request\_target on public repositories without an event policy.

Enforcement for affected repositories begins November 2, 2026. Until then the rule runs in evaluate mode, and Insights shows which runs would fail.

Script injection is the quieter risk. Pass values an outsider controls, such as a pull request title, through an intermediate environment variable instead of interpolating them into a script.

On May 11, 2026, an attacker chained a pull\_request\_target workflow, cache poisoning across the fork-to-base trust boundary and OIDC token extraction from runner memory. The result was 84 malicious versions across 42 @tanstack npm packages, published in six minutes (TanStack postmortem).

OIDC trusted publishing had removed stored npm tokens from the picture, and TanStack confirmed none were stolen. The attacker still extracted an OIDC token from the release runner’s memory and used it to publish. TanStack later pinned its actions to immutable SHAs and purged its caches, according to InfoQ.

Hardening checklist

  1. Add a top-level permissions block set to read-only, then widen it per job.
  2. Pin third-party actions to full commit SHAs and enable the pinning policy.
  3. Configure Dependabot for the github-actions ecosystem.
  4. Replace stored cloud keys with OpenID Connect.
  5. Move untrusted context values into environment variables, and avoid pull\_request\_target with fork checkouts.
  6. Protect .github/workflows with CODEOWNERS.

When Does GitHub Actions Stop Being the Right Choice?

YouTube player

It fits poorly when runs hit its hard limits or when macOS or Windows minutes dominate the bill. A team that wants a self-managed server with deep plugin control will feel the mismatch too. For a small project on a public repository, none of those apply.

Hard limits

LimitValueWhat happens
Workflow run time35 daysRun is cancelled
Concurrency queue100 runs per group with queue: maxExtra runs are canceled
Job concurrencyVaries by planGitHub Support can raise it
Storage limitsVariesGitHub Support cannot raise them

Without queue: max, a concurrency group holds one pending run, and a newer run replaces it. Rapid pushes can quietly cancel a pending deployment (GitHub Docs, October 2026).

Cost cliffs and runner risks

Per the rates above, macOS minutes cost roughly ten times Linux minutes.

Self-hosted runners carry their own risk. GitHub’s security guidance says they should almost never serve public repositories, because any user can open a pull request against them.

Private repositories are exposed too, to anyone who can fork and open a pull request. Node 24 is also incompatible with macOS 13.4 and earlier and doesn’t officially support ARM32, so self-hosted runners on those systems are no longer supported (GitHub changelog, September 23, 2026).

GitHub Actions compared with Jenkins and GitLab CI/CD

YouTube player
ToolPipeline definitionWhere jobs runBest fit
GitHub ActionsYAML in .github/workflowsGitHub-hosted or self-hosted runnersCode already on GitHub
GitLab CI/CD.gitlab-ci.yml at the project rootGitLab.com runners or your ownTeams standardized on GitLab
JenkinsJenkinsfile in the repository, or job configuration on the Jenkins serverNodes you manageFull server control, plugin-driven setups

The upside is that there’s no CI server to run and workflows live beside the code. Marketplace reuse helps, and automated importers cover Jenkins, GitLab CI/CD, CircleCI, Azure DevOps, Travis CI, Bamboo and Bitbucket Pipelines.

On the downside, minutes are metered on private repositories, and run time and queues have hard limits. Third-party actions add supply chain exposure.

Teams with a mature deployment pipeline on Jenkins gain little from a rewrite unless they want to retire the server. For new projects hosted on GitHub, stay on GitHub Actions until a specific limit forces a move.

GitHub Actions FAQ

Can GitHub Actions deploy to AWS, Azure or Google Cloud?

Yes. GitHub Docs carry deployment guides for Amazon Elastic Container Service, Azure App Service, Azure Kubernetes Service and Google Kubernetes Engine.

They also document OpenID Connect setup for AWS, Azure and Google Cloud, so workflows can skip stored credentials.

How do you stop a workflow from running on a commit?

Add [skip ci] to the commit message. GitHub Docs also accept [ci skip], [no ci], [skip actions], [actions skip] and a skip-checks: true trailer.

These apply only to push and pull\_request events. Required checks stay Pending, which blocks the merge until a new commit arrives without the skip string.

How do you cancel a workflow run that is still going?

Open the repository’s Actions tab, select the queued or in-progress run, and click Cancel workflow in the upper-right corner.

You need write access to the repository for this.

Can you run GitHub Actions on your own machine?

Not natively. The open source act tool reads the .github/workflows directory and runs jobs locally.

It depends on Docker and starts a container for each runner, so results approximate GitHub’s runners rather than match them.

How are GitHub Actions different from GitHub Apps?

GitHub Apps run persistently on a server or compute infrastructure you provide, which suits quick event reactions and persistent data.

Actions skip the deployed server entirely. They run on runners or in Docker containers, with a clone of your repository available for build, test and deploy work (GitHub Docs).

Starting Small With GitHub Actions

The smallest useful setup is one workflow that runs the existing tests on pull requests, with the GITHUB\_TOKEN limited to read access on repository contents.

Order matters, since controls belong in place before any deployment secret exists. Begin with the test workflow and the read-only token, then add Dependabot and a SHA pinning policy. Caching comes next, and the deployment stage after that.

Deployment goes last because it is the first stage that needs cloud credentials. Once tests run reliably, a continuous deployment stage is the logical addition.

SHA pins block silent action swaps, but they add a recurring update review to every pipeline.

Verified October 4, 2026. The advice changes if GitHub revives the postponed self-hosted runner charge.

Bogdan Sandu

Stay sharp. Ship better code.

Every week: one curated article, one tool worth knowing, one tip you can use tomorrow. No noise, no padding.