GitHub Actions react to events such as code push, PR creation, and certain times. It is a CI/CD platform that automatically executes build, test, and deployment. You can define a complex pipeline with a single YAML file. Reuse open source actions for quick composition.
Learning Objectives
- Can understand and write the basic structure of GitHub Actions workflow YAML.
- You can set
push·pull_requesttrigger and manual trigger (workflow_dispatch). - Parallel tests can be run on multiple OS/Version combinations as a matrix.
- Workflow execution time can be shortened with dependency cache.
- You can store build output with artifacts and use sensitive information safely with secrets.
Key concepts
1) Workflow structure
name: Workflow name
on: #trigger
push:
branches: [main]
pull_request:
branches: [main]
jobs:
job-name:
runs-on: ubuntu-latest #execution environment
steps:
- uses: actions/checkout@v4 #Use action
- name: step name
run: echo "Hello" #shell command
2) Trigger type
on:
push: #push event
branches: [main, develop]
paths: ['src/**'] #Only when changing a specific path
pull_request:
types: [opened, synchronize, reopened]
schedule:
- cron: '0 9 * * 1' #Every Monday 09:00 UTC
workflow_dispatch: #Manual execution (UI button)
inputs:
environment:
type: choice
options: [staging, production]
3) Matrix Strategy
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node: [18, 20, 22]
fail-fast: false #Even if one fails, the rest continues to run
runs-on: ${{ matrix.os }}
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
4) Cache
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
5) Artifacts
- uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
retention-days: 7
#download
- uses: actions/download-artifact@v4
with:
name: build-output
6) Secrets
env:
API_KEY: ${{ secrets.API_KEY }}
DB_URL: ${{ secrets.DATABASE_URL }}
#GitHub → Repository Settings → Secrets and variables → Actions → New repository secret
See as example
Example 1 — ex01_hello.yml: “Hello” output when pushing
name: Hello World
on:
push:
branches: [main]
workflow_dispatch:
jobs:
greet:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Say Hello
run: |
echo "Hello, GitHub Actions!"
echo "Repo: ${{ github.repository }}"
echo "Branch: ${{ github.ref_name }}"
echo "Actor: ${{ github.actor }}"
Execution results (check in Actions tab)
Hello, GitHub Actions!
Repo: username/my-repo
Branch: main
Actor: username
Key point: You can retrieve repository, branch, and user information with the github context.
Example 2 — ex02_test.yml: Node.js project CI
name: Node.js CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Run tests
run: npm test
- name: Build
run: npm run build
Key point: npm ci is installed accurately based on package-lock.json to ensure reproducibility.
Example 3 — ex03_matrix.yml: OS·Node version matrix
name: Matrix Build
on:
push:
branches: [main]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node-version: [18, 20, 22]
exclude:
- os: windows-latest
node-version: 18 #Excluding certain combinations
steps:
- uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Install and test
run: |
npm ci
npm test
Key point: 3 × 3 = 9 (8 including 1) combinations are executed in parallel.
Example 4 — ex04_cache.yml: Reduce installation time with cache + save artifacts
name: Build with Cache
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm' #Built-in cache (automatically configure actions/cache)
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist-${{ github.sha }}
path: dist/
retention-days: 7
deploy:
needs: build #Run after build completion
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: dist-${{ github.sha }}
path: dist/
- name: Deploy
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
run: echo "Deploying with secret key (masked)"
Key point: needs specifies the order between jobs, and secrets safely transmit sensitive information.
Seeing from a different perspective
| Actions concept | Metaphor |
|---|---|
| workflow | Factory production line blueprint |
| job | Each workshop in the production line |
| step | Detail work in workshop |
action (uses) |
Ready-made tools |
| matrix | Simultaneous production in multiple factories |
| artifact | Finished product packaging box |
| secrets | Key locked in safe |
Common Mistakes
- Access code without
actions/checkout— Workflow does not automatically import code. - Output secrets as
echo— GitHub masks this, but it may remain in the log. - Fix the cache key — The cache is not updated when dependencies change; Use dynamic keys with
hashFiles. - Ignore
fail-fast: truedefault — If one fails, all matrix jobs are canceled. - Setting only
workflow_dispatchwithouton: push— It does not run automatically.
Cleanup
- The workflow is saved in
.github/workflows/*.ymland has the structure of event → job → step. - Increase test coverage by executing multiple environment combinations in parallel using a matrix.
- Reduce dependency installation time with
cacheand save build results withartifact. secretsis set in the GitHub UI and referenced as${{ secrets.NAME }}in the workflow.- Control the order by setting dependency relationships between jobs with
needs.
Try it yourself
#The Actions yml file runs from a GitHub repository.
#Copy the file to the workflow directory with the command below.
mkdir -p .github/workflows
cp 08_GitHub_Actions/src/ex01_hello.yml .github/workflows/
git add .github/workflows/ex01_hello.yml
git commit -m "ci: add hello workflow"
git push
#→ Check the results in the GitHub repository Actions tab.
Application:
- Add the
inputparameter toworkflow_dispatchto select the environment when running manually. - Create a workflow that runs every midnight at midnight with the
scheduletrigger.