Introduction: Why CI/CD is Essential for JavaScript Projects
Developing a modern JavaScript application on Node.js is a complex process that includes writing code, testing, building, and deploying. Without automation, these stages are performed manually, which leads to errors, delays, and reduced product quality. CI/CD (Continuous Integration / Continuous Delivery) is a DevOps practice that automates building, testing, and deploying code.
GitHub Actions is a built-in GitHub tool that allows you to create workflows for task automation. It is ideal for JavaScript projects as it supports Node.js, npm, Yarn, and many popular services. In this article, we will break down how to set up a full CI/CD pipeline for your JavaScript project using GitHub Actions.
You will learn: how to run tests, how to build the application, how to deploy to a server or cloud platform, and how to avoid common mistakes.
GitHub Actions Basics for JavaScript
What is GitHub Actions?
GitHub Actions is a platform for automating workflows. You describe a sequence of steps in a YAML file, which is placed in the repository (usually .github/workflows/main.yml). Each time an event occurs (e.g., push, pull request), the workflow is triggered.
A workflow consists of jobs that are executed on a runner (a virtual machine). For JavaScript projects, an Ubuntu runner pre-installed with Node.js is typically used.
Basic workflow for Node.js
Let's start with a simple workflow that runs tests on every push or pull request. Create a file .github/workflows/ci.yml:
name: CI для JavaScript
on: push: branches: [ main, develop ] pull_request: branches: [ main ]
jobs: test: runs-on: ubuntu-latest
strategy: matrix: node-version: [16.x, 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 test - run: npm run build --if-presentThis workflow does the following:
- Triggers: runs on push to main/develop or on pull request to main.
- Version matrix: tests on Node.js 16, 18, 20 — this ensures compatibility.
- Caching:
cache: 'npm'speeds up dependency installation. - Commands:
npm ci(clean install),npm test(tests),npm run build(build, if present).
Setting up a Full CI/CD Pipeline
Now let's make it more complex: add linting, security checks, and automatic deployment after successful testing.
Step 1: Linting and Formatting
Add a job for ESLint and Prettier. This ensures a consistent code style:
jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '18.x' cache: 'npm' - run: npm ci - run: npm run lint - run: npx prettier --check .In package.json, there should be scripts "lint" and "format". Example:
{ "scripts": { "lint": "eslint src/", "format": "prettier --write ." }}Step 2: Dependency Security
Use npm audit to check for vulnerabilities:
security: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm audit --audit-level=highIf