devops2025-03-28·7·136/348

npm version 자동 업데이트 설정

Automating npm package version updates with scripts, git hooks, and CI/CD integration for consistent version management.

npm version 자동 업데이트 설정

Introduction

Managing package versions manually is error-prone and tedious. npm provides built-in versioning commands, but automating the process with scripts and git hooks ensures consistency across your team.

Environment

node --version
# v20.11.0

npm --version
# 10.2.4

git --version
# git version 2.42.0

Problem

Manual version updates lead to inconsistencies:

# Developer A
npm version patch  # 1.0.0 → 1.0.1

# Developer B (forgot to pull)
npm version patch  # 1.0.0 → 1.0.1 (duplicate version!)

# No git tag created
# Changelog not updated
# Package-lock not synced

Analysis

npm version commands follow semantic versioning:

MAJOR.MINOR.PATCH
  1  .  0  .  0

MAJOR: Breaking changes
MINOR: New features (backward compatible)
PATCH: Bug fixes (backward compatible)

The npm version workflow:

npm version patch → Updates package.json → Creates git commit → Creates git tag

Solution

Solution 1: Basic npm version commands

# Increment patch version
npm version patch      # 1.0.0 → 1.0.1

# Increment minor version
npm version minor      # 1.0.1 → 1.1.0

# Increment major version
npm version major      # 1.1.0 → 2.0.0

# Set specific version
npm version 1.2.3      # → 1.2.3

# Prerelease versions
npm version prerelease --preid=alpha  # 1.0.0 → 1.0.1-alpha.0

Solution 2: Git hooks for automatic versioning

// package.json
{
  "scripts": {
    "version": "echo 'Version updated to' $npm_package_version",
    "postversion": "git push && git push --tags"
  },
  "devDependencies": {
    "husky": "^9.0.0"
  }
}
# Install husky
npx husky init

# Create pre-commit hook
echo "npm run lint" > .husky/pre-commit
chmod +x .husky/pre-commit

Solution 3: Custom version script

// scripts/version-update.js
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');

function updateVersion(type) {
  const packagePath = path.join(__dirname, '../package.json');
  const package = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
  
  const [major, minor, patch] = package.version.split('.').map(Number);
  
  let newVersion;
  switch (type) {
    case 'major':
      newVersion = `${major + 1}.0.0`;
      break;
    case 'minor':
      newVersion = `${major}.${minor + 1}.0`;
      break;
    case 'patch':
      newVersion = `${major}.${minor}.${patch + 1}`;
      break;
    default:
      throw new Error(`Invalid version type: ${type}`);
  }
  
  // Update package.json
  package.version = newVersion;
  fs.writeFileSync(packagePath, JSON.stringify(package, null, 2) + '\n');
  
  // Update package-lock.json
  execSync('npm install --package-lock-only', { stdio: 'inherit' });
  
  // Create git commit and tag
  execSync('git add package.json package-lock.json');
  execSync(`git commit -m "chore: release v${newVersion}"`);
  execSync(`git tag v${newVersion}`);
  
  console.log(`Version updated to ${newVersion}`);
}

const versionType = process.argv[2] || 'patch';
updateVersion(versionType);
# Usage
node scripts/version-update.js patch
node scripts/version-update.js minor
node scripts/version-update.js major

Solution 4: Changelog generation

// package.json
{
  "scripts": {
    "release:patch": "npm version patch && npm run changelog",
    "release:minor": "npm version minor && npm run changelog",
    "release:major": "npm version major && npm run changelog",
    "changelog": "npx conventional-changelog -p angular -i CHANGELOG.md -s"
  },
  "devDependencies": {
    "conventional-changelog-cli": "^4.0.0"
  }
}

Solution 5: CI/CD version automation

# .github/workflows/release.yml
name: Release
on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          registry-url: 'https://registry.npmjs.org'
      
      - run: npm ci
      - run: npm test
      - run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
      
      - name: Create GitHub Release
        uses: softprops/action-gh-release@v1
        with:
          generate_release_notes: true

Lessons Learned

  1. Use conventional commits - feat:, fix:, chore: for automated changelogs
  2. Always tag releases - npm version creates tags automatically
  3. Run tests before version bump - Ensure the version is stable
  4. Automate in CI/CD - Do not rely on manual version bumps
  5. Use prerelease versions for beta testing

This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.