CI/CD for TypeScript Projects: GitHub Actions from A to Z
Modern TypeScript development is impossible without fast and reliable automation. Manual testing, building, and deployment are not only time-consuming but also prone to errors. CI/CD (Continuous Integration / Continuous Deployment) comes to the rescue — a practice that allows you to automatically check and deploy your code. In this article, we will break down how to set up a complete CI/CD pipeline for TypeScript projects using GitHub Actions — from basic configuration to advanced scenarios.
What is CI/CD and why does a TypeScript developer need it?
CI/CD is a methodology that combines two practices:
- Continuous Integration (CI) — automatic building and testing of code with every push to the repository. This allows you to quickly detect bugs and conflicts.
- Continuous Deployment/Delivery (CD) — automatic deployment of the application to a server or cloud after tests pass successfully.
For TypeScript projects, CI/CD is especially important because TypeScript compiles to JavaScript, and errors in types or configuration may only appear during the build stage. GitHub Actions is a built-in GitHub tool that allows you to create workflows directly in the repository.
Step 1: Basic workflow for a TypeScript project
Let's start simple — create a file .github/workflows/ci.yml in the root of your project. This workflow will run on every push to the main branch or when a Pull Request is created.
name: CI Pipeline
on: push: branches: [ main ] pull_request: branches: [ main ]
jobs: build-and-test: runs-on: ubuntu-latest
strategy: matrix: node-version: [18.x, 20.x]
steps: - uses: actions/checkout@v4 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: 'npm' - run: npm ci - run: npm run build --if-present - run: npm test - run: npm run lint --if-presentLet's break down the key points:
actions/checkout— clones the repository into the runner.actions/setup-node— installs Node.js with dependency caching.npm ci— clean install of dependencies (faster thannpm install).npm run build— compiles TypeScript to JavaScript (make sure you have abuildscript inpackage.json).npm test— runs tests (e.g., Jest).
The strategy.matrix allows you to test the code on multiple Node.js versions simultaneously — this increases confidence in compatibility.
Step 2: Adding linting and formatting
Code quality is an important part of CI. Let's add steps for ESLint and Prettier. Make sure they are installed in the project:
npm install --save-dev eslint prettier eslint-config-prettierLet's supplement our workflow with new steps:
- run: npm run lint - run: npm run format:checkThe package.json should have the corresponding scripts:
{ "scripts": { "lint": "eslint src --ext .ts", "format:check": "prettier --check \"src/**/*.ts\"", "format": "prettier --write \"src/**/*.ts\"" }}Now, with every push, GitHub Actions will check not only types and tests but also code style. If the linter finds errors — the pipeline will fail, and the developer will receive a notification.
Step 3: Setting up CD — automatic deployment to Vercel/Netlify
For TypeScript projects, serverless platforms are often used. Let's look at deployment to Vercel — this is one