GitHub Actions Basics: YAML Workflow Structure and Trigger Configuration
Honestly, the first time I saw a YAML file in .github/workflows, I was confused. A bunch of indentation, colons, and keywords I couldn’t figure out—on, jobs, runs-on. What is this? Can I eat it?
Later, as projects piled up, manually running tests and deploying after each code push got tedious. That’s when I realized: GitHub Actions can save you a lot of trouble.
This article covers the basics of GitHub Actions—how to write YAML workflows and configure triggers. No fancy advanced features, just the practical stuff you’ll actually use. Getting started is what matters.
What GitHub Actions Can Do for You
Simple answer: automation.
Before, pushing code meant manually doing a bunch of things: run tests, check code formatting, build the project, deploy to server. Now you write these steps in a YAML file, and GitHub executes them automatically.
For example: every time you push code to main, GitHub Actions automatically runs your tests. Tests must pass before a PR can merge. This way, code quality is guaranteed, and you don’t have to worry.
Another benefit: it’s free. Public repositories are completely free. Private repos get 2000 free minutes per month (more than enough for personal projects).
What a YAML Workflow Looks Like
Let’s start with the simplest example:
name: Test Workflow
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Print greeting
run: echo "Hello, GitHub Actions!"
Line by line breakdown:
name: The workflow’s name. Choose whatever you want, helps identify it on the GitHub Actions page.
on: Trigger condition. Writing push here means the workflow triggers every time you push code.
jobs: Task block. A workflow can contain multiple jobs that run in parallel or sequentially.
build: This job’s ID. Name it however you like, but make it meaningful (like build, test, deploy).
runs-on: Execution environment. ubuntu-latest means running on the latest Ubuntu server. You can also choose windows-latest, macos-latest.
steps: Step list. A job consists of multiple steps executed in order.
run: The command to execute. Here it just prints a message.
This is the basic skeleton. Complex workflows just pile on more jobs, more steps, more logic on top of this. Don’t panic though—master the basics first, the complex stuff will come naturally.
Triggers: When Does Your Workflow Run
The trigger is the “switch” for your entire workflow. Configured correctly, it runs at the right time.
There are four common triggers: push, pull_request, schedule, workflow_dispatch. Let’s go through each.
1. push: Trigger on Code Push
The most commonly used trigger.
on: push
This way, every code push to any branch triggers it.
But usually we only want triggers on specific branches:
on:
push:
branches:
- main
- dev
This configuration means: only trigger when pushing to main or dev branches. Other branches? Ignored.
You can be even more specific—only monitor changes to certain paths:
on:
push:
branches:
- main
paths:
- 'src/**'
- 'package.json'
Only triggers when files in src/ directory or package.json change. This way, changing docs or config files won’t waste a CI run.
2. pull_request: Trigger on PR Operations
PRs (Pull Requests) are the core of team collaboration.
on: pull_request
This triggers on all PR operations: opening a PR, updating a PR, reopening a PR.
But you can also limit to specific branches:
on:
pull_request:
branches:
- main
Only triggers when the PR’s target branch is main.
You can also specify PR operation types:
on:
pull_request:
types:
- opened
- synchronize
- reopened
opened: When a PR is just openedsynchronize: When a PR gets new commits (like when you push new changes)reopened: When a closed PR is reopened
This configuration is common—run tests when a PR opens to ensure changes are solid.
3. schedule: Scheduled Triggering
Like a cron job, runs the workflow on schedule.
on:
schedule:
- cron: '0 0 * * *'
This is a cron expression, format: minute hour day month weekday.
The line above means: run once daily at UTC 0:00 (8:00 AM Beijing time).
Common use cases: daily automated tests, periodic cache cleanup, scheduled report generation.
Honestly, cron expressions are easy to mess up. There are online tools to help verify, like crontab.guru.
4. workflow_dispatch: Manual Triggering
Sometimes we need manual triggers—like one-click deploy, or manually running a specific task.
on: workflow_dispatch
After configuration, a “Run workflow” button appears on the GitHub Actions page. Click it to trigger manually.
You can also configure input parameters:
on:
workflow_dispatch:
inputs:
environment:
description: 'Deploy environment'
required: true
default: 'production'
type: choice
options:
- production
- staging
When manually triggering, you can choose which environment to deploy to. Deploy to test or production with one click. Convenient, right?
Combining Triggers
Real projects often need multiple triggers:
on:
push:
branches:
- main
pull_request:
branches:
- main
schedule:
- cron: '0 6 * * 1' # Every Monday 6:00 UTC
workflow_dispatch:
This configuration means:
- Trigger when pushing to
mainbranch - Trigger when PR targets
mainbranch - Run once every Monday morning
- Support manual triggering
One workflow, multiple trigger methods. A common configuration pattern.
Practical Example: Automated Testing for Node.js
Let’s write a practical example—automated testing for a Node.js project.
Assume your project structure looks like this:
my-project/
├── src/
├── tests/
├── package.json
└── .github/
└── workflows/
└── test.yml
Create .github/workflows/test.yml file:
name: Automated Testing
on:
push:
branches:
- main
- dev
pull_request:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
steps:
# 1. Checkout code
- name: Checkout code
uses: actions/checkout@v4
# 2. Setup Node.js
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
# 3. Install dependencies
- name: Install dependencies
run: npm ci
# 4. Run tests
- name: Run tests
run: npm test
# 5. Code format check (optional)
- name: Check code format
run: npm run lint
Step by step explanation:
Checkout code: actions/checkout@v4 is an official Action that downloads your repository to the runtime environment.
Setup Node.js: actions/setup-node@v4 is also an official Action, installs the specified Node.js version. node-version: '20' means using Node.js 20.
Install dependencies: npm ci is better suited for CI environments than npm install—it strictly follows package-lock.json, faster and more reliable.
Run tests: Directly runs your test command. Requires test script configured in package.json.
Code format check: If you configured ESLint or Prettier, this step automatically checks code format.
This workflow triggers when pushing to main or dev branches, and when PRs target main. Every change gets tested.
Common Pitfalls
Honestly, I hit quite a few pitfalls when I started writing YAML. Here are some common ones:
1. Indentation Errors
YAML is extremely sensitive to indentation. Must use spaces, not tabs. Indentation levels must be consistent.
# ❌ Wrong: inconsistent indentation
jobs:
build:
runs-on: ubuntu-latest
# ✅ Correct: consistent indentation
jobs:
build:
runs-on: ubuntu-latest
Recommend using a YAML plugin in your editor—it automatically highlights indentation errors.
2. Triggers Not Working
Sometimes configured triggers don’t fire the workflow. Common reasons:
- Wrong branch configuration: Like pushing to
developbranch, but configuration only monitorsmain - Forked repository: Pushing from a fork repository won’t trigger
pushevent workflows - PR from fork: PRs from forks won’t trigger certain triggers by default
3. Forgot to Checkout Code
The most common mistake beginners make: forgot to use actions/checkout@v4.
Without this step, the workflow environment is empty—your code isn’t even there.
steps:
# ❌ Wrong: running commands before checking out code
- run: npm test
# ✅ Correct: checkout code first
- uses: actions/checkout@v4
- run: npm test
4. Outdated Action Versions
Some tutorials use actions/checkout@v2 or v3. But I recommend using the latest version v4—more complete features, better performance.
Regularly check if the Actions you use have new versions. GitHub will remind you about outdated versions.
Some Practical Tips
Trigger Selection Principles
Ask yourself a few questions:
- Want automatic or manual runs? → Automatic: use
push/pull_request, Manual: useworkflow_dispatch - High frequency? → High frequency means limit branches or paths, avoid wasting resources
- Team collaboration? → PR scenarios must configure
pull_request
Performance Optimization Tips
- Limit trigger scope: Only monitor key branches and paths
- Parallel execution: Multiple independent jobs can run in parallel
- Use caching:
actions/setup-nodeautomatically caches Node.js and dependencies, no reinstall needed every time
Clear Naming
# ❌ Vague naming
jobs:
job1:
steps:
- name: step1
# ✅ Clear naming
jobs:
test:
steps:
- name: Install dependencies
Clear names make troubleshooting easier—GitHub Actions page displays each step’s name.
Recommended Learning Path
This article only covered basics. If you want to dive deeper, continue learning:
- Matrix builds: Run tests in multiple environments (Node.js 16, 18, 20) simultaneously
- Cache optimization: Manually configure caching to speed up builds
- Secret management: Securely store API keys, passwords, and sensitive information
- Custom Actions: Encapsulate your own Actions for reusable logic
- Deployment automation: Automatically deploy to servers or cloud platforms
The official documentation is the best resource: GitHub Actions Docs. Comprehensive content, just a bit lengthy.
Another suggestion: look at others’ configurations. Many open source projects on GitHub have complete configurations in .github/workflows folders—copying homework is fine too.
Final Thoughts
After all this talk, the core is really just three things:
- YAML structure:
name,on,jobs,steps—four keywords build the skeleton - Trigger configuration:
push,pull_request,schedule,workflow_dispatch—four most commonly used - Practical example: Node.js automated testing is the classic beginner scenario
I still remember the feeling after getting my first workflow working—pushing code, GitHub automatically running tests, then sending me an email saying “tests passed.” That sense of “everything under control” was really satisfying.
Later if you want to learn advanced features (matrix builds, cache optimization, deployment automation), with the foundation laid, it won’t be hard. GitHub Actions has a low entry barrier, but mastering it can really save a lot of time. At least you won’t have to manually run tests every time you push code, right?
Configure GitHub Actions Automated Testing Workflow
Create an automated testing workflow for Node.js projects that runs tests automatically when code is pushed
⏱️ Estimated time: 15 min
- 1
Step1: Create Workflow File
Create .github/workflows/test.yml in project root:
• Path must be exact: .github/workflows/
• Filename should be meaningful: test.yml, ci.yml
• File extension must be .yml or .yaml - 2
Step2: Configure Triggers
Set workflow trigger conditions:
• push trigger: monitor main, dev branches
• pull_request trigger: monitor PRs targeting main
• Can limit paths: paths: ['src/**'] - 3
Step3: Configure Runtime Environment
Specify runtime environment and Node.js version:
• runs-on: ubuntu-latest (latest Ubuntu)
• uses: actions/setup-node@v4
• node-version: '20' (Node.js 20) - 4
Step4: Write Test Steps
Execute testing process in order:
• Checkout code: uses: actions/checkout@v4
• Install dependencies: run: npm ci (prefer ci over install)
• Run tests: run: npm test
• Format check: run: npm run lint (optional) - 5
Step5: Verify Workflow
Check run results after pushing code:
• View run status on GitHub Actions page
• Check log output for each step
• Confirm tests pass before merging PR
FAQ
What's the difference between GitHub Actions and other CI/CD tools like Jenkins?
Must YAML files be placed in .github/workflows directory?
Why didn't my workflow trigger after pushing to a branch?
What's the difference between npm ci and npm install?
Are GitHub Actions for private repositories free?
How to avoid triggering workflow on every push?
References
- GitHub Actions Official Documentation
- Workflow Syntax for GitHub Actions
- Events that trigger workflows
9 min read · Published on: Apr 5, 2026 · Modified on: Apr 5, 2026
Related Posts
n8n Workflow Building: From Node Connections to Automation Scenario Design
n8n Workflow Building: From Node Connections to Automation Scenario Design
Supabase Database Design: Tables, Relationships & Row Level Security Guide
Supabase Database Design: Tables, Relationships & Row Level Security Guide
Firewall Configuration: UFW, iptables, and Security Policy Design

Comments
Sign in with GitHub to leave a comment