惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Proofpoint News Feed
Martin Fowler
Martin Fowler
The GitHub Blog
The GitHub Blog
B
Blog RSS Feed
U
Unit 42
阮一峰的网络日志
阮一峰的网络日志
量子位
GbyAI
GbyAI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
云风的 BLOG
云风的 BLOG
小众软件
小众软件
博客园 - 三生石上(FineUI控件)
L
LangChain Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园_首页
IT之家
IT之家
V
Visual Studio Blog
Y
Y Combinator Blog
Blog — PlanetScale
Blog — PlanetScale
宝玉的分享
宝玉的分享
Apple Machine Learning Research
Apple Machine Learning Research
I
InfoQ
D
Docker
V
V2EX

The Practical Developer

The Libuv Thread Pool Trap: Why Node.js Async APIs Stall Under Load Postgres Covering Indexes with INCLUDE: Eliminate Heap Fetches on Read-Heavy Workloads Postgres DISTINCT ON: The Fastest Way to Get the Latest Row Per Group Postgres Transaction Isolation: The Anomalies Your App Actually Faces in Production Linux TCP Tuning for Node.js Microservices: The Kernel Settings That Stop Silent Connection Drops Under Load Postgres HOT Updates and Fillfactor: Why Not All Writes Are Created Equal Database Connection Pool Leaks: Finding the Promise That Never Returns Its Seat Linux OOM Killer in Production: Why Your Node.js Containers Die Without a Stack Trace Postgres Materialized Views: Refresh Strategies That Do Not Lock Your Dashboards API Dependency Health Checks: Why /health Is Not Enough Authorization with Zanzibar Tuples: How Google Manages Permissions and How To Build the Same Check in Node.js Postgres Advisory Locks: The 20-Character Primitive That Replaces Redis for Coordination Dead Letter Queues: The Message Queue Pattern That Saves You at 2 a.m. File Descriptor Exhaustion: The Kernel Limit That Silently Drops Node.js Connections Graceful Degradation: The Pattern That Turns Total Outages into Partial Success PostgreSQL Full-Text Search: Dropping Elasticsearch for 90% of Use Cases S3 Presigned Multipart Uploads: Stop Your API Server from Being a File Upload Bottleneck MessagePack vs JSON: The Binary Serialization Switch That Cut Our Internal RPC Overhead by 40% DNS Caching in Node.js: The Silent Cause of Production Latency Spikes Reliable Cron Jobs: The Pattern That Stops Double Runs, Missed Executions, And The 2 AM Page GraphQL Query Complexity: Stop the OOM Query Before It Reaches Your Resolver Node.js Event Loop Lag: The Hidden Metric Behind Random Latency Spikes API Request Validation with Zod: The Schema That Catches Bad Input Before It Corrupts Your Database Load Shedding in Node.js: How to Reject Traffic Before You Drown Request Hedging: Cut Tail Latency In Half Without Overprovisioning Git Bisect: The Automated Binary Search That Finds Breaking Commits in Minutes Node.js Garbage Collection Tuning: Stop Letting V8 Pause Your Event Loop Node.js Server Timeouts: The Settings That Stop Slow Clients from Holding Sockets Hostage Postgres BRIN Indexes: The Time-Series Secret That Shrinks Indexes by 99% Event Sourcing with PostgreSQL: The Pragmatic 80% Solution
CI/CD From Zero to Production in 30 Minutes With GitHub A...
The Practica · 2025-02-14 · via The Practical Developer

A CI/CD pipeline doesn’t need to be complex. Here’s a real workflow that runs on every push, catches bugs before merge, and deploys automatically.

The goal

On every pull request: lint, test, build. On merge to main: deploy. Under 30 minutes to set up. Copy and adapt.

Step 1: Create the workflow file

.github/workflows/ci.yml

Step 2: The CI pipeline

name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  ci:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '22'
          cache: 'npm'

      - run: npm ci

      - name: Lint
        run: npm run lint

      - name: Type check
        run: npm run typecheck

      - name: Test
        run: npm test -- --coverage

      - name: Build
        run: npm run build

That’s it for CI. Every PR now runs all four steps in parallel jobs if you split them, or sequentially here for simplicity.

Step 3: Deploy on merge to main

Add a deploy job that depends on ci:

  deploy:
    needs: ci
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '22'
          cache: 'npm'

      - run: npm ci
      - run: npm run build

      - name: Deploy to production
        run: npx your-deploy-cli deploy ./dist
        env:
          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}

Add DEPLOY_TOKEN to GitHub → Settings → Secrets.

Caching dependencies

The cache: 'npm' in setup-node caches ~/.npm between runs. On a warm cache, npm ci goes from 90s to 8s on a typical project.

Useful additions

Matrix testing across Node versions:

strategy:
  matrix:
    node-version: ['20', '22']

Fail fast if coverage drops:

- name: Test with coverage threshold
  run: npm test -- --coverage --coverageThreshold='{"global":{"lines":80}}'

Notify on failure (Slack):

- name: Notify Slack
  if: failure()
  uses: slackapi/slack-github-action@v1
  with:
    payload: '{"text":"❌ Build failed on ${{ github.ref }}"}'
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

Common mistakes

  1. Not pinning action versions. Use @v4 not @main. Unpinned actions can silently break.
  2. Storing secrets in the workflow file. Always use ${{ secrets.NAME }}.
  3. Running everything in one job. Split lint/test/build into parallel jobs to cut wall-clock time.
  4. Not caching. The cache step pays for itself on the first warm run.

The result

Every PR gets a green check or a red X before anyone reviews it. Merging to main ships to production automatically. The whole thing costs $0 on GitHub’s free tier for public repos, and ~$0.008 per minute for private repos.

That’s the baseline every project should have.