Workflows & Syntax
Workflows & Syntax Workflow Structure # .github/workflows/ci.yml name: CI on: push: branches: [main, develop] pull_request: branches: [main] schedule: - cron: '…
Workflows & Syntax
Workflow Structure
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
- cron: '0 2 * * *' # daily at 2am UTC
workflow_dispatch: # manual trigger
inputs:
environment:
description: 'Deploy to'
required: true
default: 'staging'
type: choice
options: [staging, production]
jobs:
test:
name: Test
runs-on: ubuntu-latest # ubuntu-latest | ubuntu-22.04 | windows-latest | macos-latest
timeout-minutes: 30
strategy:
matrix:
node-version: [18, 20, 22]
os: [ubuntu-latest, macos-latest]
fail-fast: false # continue other matrix jobs on failure
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # full history for git-based versioning
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- name: Install pnpm
uses: pnpm/action-setup@v3
with:
version: 9
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Type check
run: pnpm tsc --noEmit
- name: Lint
run: pnpm lint
- name: Test
run: pnpm test --coverage
env:
NODE_ENV: test
DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }}
- name: Upload coverage
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}Expressions & Contexts
# Contexts
${{ github.sha }} # commit SHA
${{ github.ref }} # refs/heads/main
${{ github.ref_name }} # main
${{ github.repository }} # owner/repo
${{ github.actor }} # triggering user
${{ github.event_name }} # push, pull_request, etc.
${{ github.workspace }} # /home/runner/work/repo
${{ runner.os }} # Linux, Windows, macOS
${{ env.MY_VAR }} # environment variable
${{ secrets.MY_SECRET }} # repository secret
${{ vars.MY_VAR }} # repository variable (not secret)
${{ inputs.environment }} # workflow_dispatch input
# Expressions
${{ github.event_name == 'push' }}
${{ contains(github.ref, 'main') }}
${{ startsWith(github.ref, 'refs/tags/') }}
${{ matrix.node-version >= 20 }}
# Conditional steps
- name: Deploy to production
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: ./deploy.sh
- name: Only on PRs
if: github.event_name == 'pull_request'
run: echo "PR event"
- name: Run if previous step failed
if: failure()
run: ./notify-slack.shCaching & Artifacts
# Cache dependencies
- name: Cache node_modules
uses: actions/cache@v4
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-
# Upload artifact (pass between jobs or download later)
- name: Upload build
uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
retention-days: 7
# Download artifact in another job
- name: Download build
uses: actions/download-artifact@v4
with:
name: build-output
path: dist/