GitHub Actions Core Concepts
Before writing any workflow, you need to understand the five building blocks that every GitHub Actions setup uses. These concepts connect to each other in a specific order, and knowing how they fit together makes everything else in this course easier to follow.
The Five Core Concepts at a Glance
Event (Trigger)
↓
Workflow (.yml file)
↓
Job (group of steps)
↓
Step (single command)
↓
Runner (the machine that runs it all)
Each layer depends on the one above it. An event starts a workflow, the workflow defines jobs, jobs contain steps, and a runner executes everything.
Events — What Starts Everything
An event is something that happens in your GitHub repository. GitHub Actions watches for these events and reacts to them.
Common events include:
- Someone pushes code to the main branch
- Someone opens a pull request
- A new release tag is created
- A scheduled time is reached (like 9:00 AM every Monday)
- Someone manually clicks a button to start the workflow
Events act like the alarm on a clock. The clock does nothing until the alarm fires. Once it fires, everything else kicks into motion.
Workflows — The Master Plan
A workflow is a YAML file stored inside .github/workflows/ in your repository. It describes exactly what should happen when a specific event occurs.
One repository can contain multiple workflow files. For example:
test.yml— runs tests on every pull requestdeploy.yml— deploys the app when code reaches the main branchcleanup.yml— removes old data every Sunday night
Think of a workflow file as a recipe card. It lists the ingredients (inputs), the steps to follow, and what the final product should look like.
Jobs — Chapters Inside the Workflow
A job is a collection of steps that run on the same machine. One workflow can contain multiple jobs.
Workflow: "Build and Test"
├── Job 1: build
│ ├── Step: Check out code
│ ├── Step: Install dependencies
│ └── Step: Compile the app
└── Job 2: test
├── Step: Check out code
└── Step: Run test suite
By default, jobs run at the same time (in parallel). You can also make them run one after another (in sequence) by setting dependencies between them.
Steps — The Actual Work
A step is the smallest unit of work inside a job. Each step either runs a shell command or uses a pre-built action from the GitHub Marketplace.
Two types of steps exist:
- Run steps — execute a command directly in the terminal, like
npm installorpython test.py - Uses steps — call a pre-built action, like
actions/checkout@v4which downloads your code onto the runner
Steps inside a job always run one after another, from top to bottom. If one step fails, the remaining steps in that job stop by default.
Runners — The Machines That Do the Work
A runner is a virtual machine (a computer in the cloud) that actually executes your workflow. GitHub provides runners for three operating systems:
- Ubuntu Linux (most commonly used)
- Windows
- macOS
Runners are clean machines. Each time a workflow runs, the runner starts fresh with no files, no installed software, and no memory of previous runs. Your workflow must install everything it needs from scratch every time.
Runner Lifecycle:
GitHub starts a fresh virtual machine
↓
Workflow steps run one by one
↓
Machine shuts down and disappears
↓
Next run starts with a brand new machine
Actions — Reusable Units of Work
An action (lowercase, singular) is a reusable piece of code that performs one specific task. The GitHub Marketplace hosts thousands of actions created by GitHub and the community.
Think of actions like apps on your phone. Instead of building every feature yourself, you download an app that already does it. For example, instead of writing 50 lines of code to set up Node.js, you use the actions/setup-node action, which handles it in one line.
How They All Work Together — A Visual Summary
Developer pushes code → (Event)
↓
GitHub reads test.yml → (Workflow)
↓
Starts "build" job → (Job)
↓
Runner machine spins up → (Runner)
↓
Step 1: checkout code → (Step using Action)
Step 2: install packages → (Step using run command)
Step 3: run tests → (Step using run command)
↓
Job finishes → Result appears on GitHub
