Introduction: Why CI/CD is Critical for TypeScript Projects
\nDeveloping with TypeScript is a powerful tool, but without automating the build, testing, and deployment processes, you risk encountering human errors, wasted time, and production instability. CI/CD (Continuous Integration / Continuous Deployment) is a philosophy and set of practices that allow you to automate these processes. GitHub Actions is a built-in GitHub tool that is perfect for TypeScript projects, providing flexible, scalable, and free (for public repositories) pipelines.
\nIn this article, we will go from zero to a full-fledged pipeline: we will set up linting, testing, building, and automatic deployment of a TypeScript application. You will learn how to write efficient YAML configs, optimize execution time, and avoid common mistakes.
\n\nMain Part: Step-by-Step Creation of a CI/CD Pipeline
\n\n1. GitHub Actions Basics: Workflow Structure
\nA workflow in GitHub Actions is a set of steps combined into jobs. It is described in a YAML file stored in the .github/workflows/ directory of your repository. The basic structure looks like this:
name: CI/CD Pipeline for TypeScript\n\non:\n push:\n branches: [ main, develop ]\n pull_request:\n branches: [ main ]\n\njobs:\n build-and-test:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: '20'\n cache: 'npm'\n - run: npm ci\n - run: npm run build\n - run: npm test\nKey elements:
\n- \n
on:— triggers (push, pull_request). \njobs:— a list of tasks (jobs) that run in parallel or sequentially. \nruns-on:— the operating system for execution (usuallyubuntu-latest). \nsteps:— a sequence of commands.usescalls ready-made actions, andrunexecutes shell commands. \nnpm ci— a fast clean installation of dependencies based onpackage-lock.json. \n
This minimal pipeline already provides basic CI: on every push or PR, the code will be checked for build and tests.
\n\n2. Advanced Configuration: Linting, Formatting, and Version Matrix
\nFor TypeScript projects, it is critical to maintain a consistent code style. Let's add checks with a linter (eslint) and a formatter (prettier). We will also use a strategy matrix to test on multiple Node.js versions.
jobs:\n lint-and-format:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - uses: actions/setup-node@v4\n with:\n node-version: '20'\n cache: 'npm'\n - run: npm ci\n - run: npm run lint\n - run: npm run format:check\n\n test:\n needs: lint-and-format\n runs-on: ubuntu-latest\n strategy:\n matrix:\n node-version: [18, 20, 22]\n steps:\n - uses: actions/checkout@v4\n - uses: actions/setup-node@v4\n with:\n node-version: ${{ matrix.node-version }}\n cache: 'npm'\n - run: npm ci\n - run: npm test\nImportant points:
\n- \n
needs:— sets the order of job execution (linting first, then tests). \nstrategy.matrix— allows running the same job with different parameters (Node.js versions).- Caching (
cache: 'npm') speeds up dependency installation. - Add scripts to
package.json:"lint": "eslint src/"and"format:check": "prettier --check src/".
Now your pipeline not only prov