Introduction: Why CI/CD is Critical for TypeScript Projects
Modern TypeScript development requires not only high-quality code but also a reliable process for delivering it to users. Manually running tests, building, and deploying is not only tedious but also a source of errors. CI/CD (Continuous Integration / Continuous Deployment) solves this problem by automating each stage.
In this article, we will walk through how to set up a full CI/CD pipeline for a TypeScript project using GitHub Actions. You will learn how to automate linting, testing, building, and deploying your application, saving hours of work time.
This article is written for the PythonLib platform, but all examples and concepts are applicable to any TypeScript project. We will be using TypeScript 5.x and Node.js 20.
Main Part: Step-by-Step CI/CD Setup
1. Project Structure and Preparation
Before writing a workflow, make sure your TypeScript project is properly configured. Here is the minimal structure:
my-typescript-app/├── src/│ └── index.ts├── tests/│ └── index.test.ts├── package.json├── tsconfig.json├── .eslintrc.json└── .github/ └── workflows/ └── ci.ymlImportant: the package.json must have scripts defined for testing and building.
{ "name": "my-typescript-app", "version": "1.0.0", "scripts": { "build": "tsc", "test": "jest", "lint": "eslint src/**/*.ts", "start": "node dist/index.js" }, "devDependencies": { "typescript": "^5.3.0", "jest": "^29.7.0", "@types/jest": "^29.5.0", "ts-jest": "^29.1.0", "eslint": "^8.50.0" }}Make sure that tsconfig.json includes a correct outDir (e.g., "./dist") and strict mode.
2. Creating a GitHub Actions Workflow
GitHub Actions works based on YAML files in the .github/workflows/ directory. Create a file ci.yml with the following content:
name: CI/CD Pipeline
on: push: branches: [ main, develop ] 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'
- name: Install dependencies run: npm ci
- name: Lint code run: npm run lint
- name: Build project run: npm run build
- name: Run tests run: npm test
- name: Upload build artifacts uses: actions/upload-artifact@v4 with: name: build-${{ matrix.node-version }} path: dist/Key points breakdown:
- on: The workflow runs on push and pull request to the main and develop branches.
- matrix: We test on two Node.js versions (18 and 20) for compatibility.
- npm ci: Clean installation of dependencies (faster and more reliable than npm install).
- upload-artifact: We save the built files for subsequent deployment.
3. Adding a Deployment Stage
After successful building and testing, you can automatically deploy the application. Let's look at deployment to GitHub Pages (for static sites) and to a VPS via SSH.
Option A: Deploy to GitHub Pages
deploy: needs: build-and-test runs-on: ubuntu-latest if: github.ref == 'refs/heads/main'
steps: - uses: actions/download-artifact@v4 with: name: build-20.x path: dist/
- name: Deploy to GitHub Pages uses