Every pull request should be validated automatically before a human reviews it. Type checking, linting, tests, and build verification should happen on every push without anyone triggering them manually. GitHub Actions makes this native to the repository. Workflows are YAML files committed alongside the code, triggered by git events, and executed on GitHub’s runners. No external CI service to configure, no webhooks to maintain, no separate dashboard to monitor.
A complete CI workflow for TypeScript
A single workflow file can run type checking, linting, and tests in parallel. Each job runs on its own runner, so failures are isolated and the total pipeline time equals the slowest job, not the sum of all jobs.
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm tsc --noEmit
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm eslint . --max-warnings 0
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm vitest run --coverage
The cache: pnpm option on setup-node caches the pnpm store between runs. This cuts install times from minutes to seconds on subsequent runs. --frozen-lockfile ensures CI uses the exact dependency versions from the lockfile, preventing “works on my machine” drift.
Reusable workflows to avoid duplication
When multiple repositories share the same CI structure, copying YAML files between them creates maintenance burden. Reusable workflows let you define a workflow once and call it from any repository.
name: Reusable CI
on:
workflow_call:
inputs:
node-version:
type: string
default: '22'
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm tsc --noEmit
- run: pnpm eslint . --max-warnings 0
- run: pnpm vitest run
name: CI
on: [push, pull_request]
jobs:
ci:
uses: your-org/shared-workflows/.github/workflows/ci-reusable.yml@main
with:
node-version: '22'
The calling workflow is three lines. All the logic lives in the shared repository. Updating the CI pipeline for every project means changing one file.
Automating deployments with environment protection
GitHub Actions handles deployment pipelines with built-in environment protection rules. Production deployments can require manual approval, restrict which branches can deploy, and store environment-specific secrets.
name: Deploy
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm build
- uses: actions/upload-artifact@v4
with:
name: build-output
path: .next/
deploy:
needs: build
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/download-artifact@v4
with:
name: build-output
path: .next/
- run: echo "Deploying to production..."
The environment: production declaration links to GitHub’s environment settings where you configure required reviewers, wait timers, and deployment branch policies. The build artifact is passed between jobs so the deploy step uses exactly what was tested.
Scheduled workflows and automation
Beyond CI/CD, GitHub Actions runs scheduled tasks directly in the repository. Dependency audits, stale issue cleanup, and periodic health checks all fit naturally.
name: Security Audit
on:
schedule:
- cron: '0 8 * * 1'
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm audit --audit-level=high
This runs every Monday at 8am. If pnpm audit finds high-severity vulnerabilities, the workflow fails and GitHub sends a notification. No external cron service, no separate monitoring tool.
Conclusion
GitHub Actions turns the repository into the single source of truth for both code and automation. CI pipelines, deployment workflows, scheduled tasks, and reusable templates all live next to the code they operate on. For TypeScript projects, the combination of parallel jobs, dependency caching, and environment protection covers the entire path from commit to production.