如何编写项目自动构建脚本

wen 实用脚本 2

本文目录导读:

如何编写项目自动构建脚本

  1. Shell脚本(Linux/Mac)
  2. JavaScript/Node.js (npm scripts)
  3. Python项目
  4. CI/CD集成脚本
  5. 最佳实践建议
  6. 一键构建脚本模板

Shell脚本(Linux/Mac)

基础构建脚本示例

#!/bin/bash
# build.sh - 项目自动构建脚本
set -e  # 出错立即停止
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo -e "${YELLOW}开始构建项目...${NC}"
# 1. 清理旧文件
echo "清理旧构建文件..."
rm -rf dist/
rm -rf build/
# 2. 安装依赖
echo "安装依赖..."
npm install
# 3. 运行测试
echo "运行测试..."
npm test
# 4. 构建项目
echo "构建项目..."
npm run build
# 5. 生成文档
if [ -f "README.md" ]; then
    echo "生成文档..."
    npx jsdoc src/
fi
echo -e "${GREEN}构建成功!${NC}"

JavaScript/Node.js (npm scripts)

package.json配置

{
  "name": "my-project",
  "version": "1.0.0",
  "scripts": {
    "clean": "rimraf dist",
    "lint": "eslint src/**/*.js",
    "test": "jest",
    "build": "npm run lint && npm run clean && babel src -d lib",
    "docs": "jsdoc -c jsdoc.json",
    "deploy": "npm run build && npm run docs && scp -r dist/ user@server:/var/www/",
    "prepublishOnly": "npm test && npm run build"
  },
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "eslint": "^8.0.0",
    "jest": "^29.0.0",
    "rimraf": "^5.0.0"
  }
}

Python项目

Makefile方式

# Makefile - Python项目构建
.PHONY: help install clean test build deploy
help:
    @echo "可用命令:"
    @echo "  make install - 安装依赖"
    @echo "  make test    - 运行测试"
    @echo "  make build   - 构建项目"
    @echo "  make clean   - 清理文件"
    @echo "  make deploy  - 部署项目"
install:
    pip install -r requirements.txt
    pip install -r requirements-dev.txt
test:
    pytest tests/ -v --cov=src
clean:
    rm -rf build/ dist/ *.egg-info
    find . -type d -name __pycache__ -exec rm -rf {} +
    find . -type f -name "*.pyc" -delete
build: clean
    python setup.py sdist bdist_wheel
    python -m pip install --upgrade pip
deploy: build
    twine upload dist/*

Python构建脚本

#!/usr/bin/env python3
# build.py - Python构建脚本
import os
import shutil
import subprocess
import sys
from datetime import datetime
class ProjectBuilder:
    def __init__(self):
        self.project_root = os.path.dirname(os.path.abspath(__file__))
        self.build_dir = os.path.join(self.project_root, 'dist')
        self.log_file = os.path.join(self.project_root, 'build.log')
    def log(self, message):
        timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        log_message = f"[{timestamp}] {message}"
        print(log_message)
        with open(self.log_file, 'a') as f:
            f.write(log_message + '\n')
    def clean(self):
        self.log("清理构建目录...")
        if os.path.exists(self.build_dir):
            shutil.rmtree(self.build_dir)
        os.makedirs(self.build_dir)
    def install_dependencies(self):
        self.log("安装依赖...")
        subprocess.run([sys.executable, "-m", "pip", "install", "-r", 
                       "requirements.txt"], check=True)
    def run_tests(self):
        self.log("运行测试...")
        subprocess.run([sys.executable, "-m", "pytest", "tests/", "-v"],
                       check=True)
    def build(self):
        self.log("构建项目...")
        subprocess.run([sys.executable, "setup.py", "sdist", "bdist_wheel"],
                       check=True)
    def deploy(self, environment='staging'):
        self.log(f"部署到{environment}环境...")
        # 实际部署逻辑
        if environment == 'production':
            subprocess.run(["rsync", "-av", "dist/", "user@server:/var/www/"], 
                         check=True)
        else:
            subprocess.run(["rsync", "-av", "dist/", "user@staging-server:/var/www/"],
                         check=True)
    def run(self, command='all'):
        commands = {
            'clean': self.clean,
            'install': self.install_dependencies,
            'test': self.run_tests,
            'build': self.build,
            'deploy': self.deploy,
        }
        if command == 'all':
            for cmd in ['clean', 'install', 'test', 'build']:
                commands[cmd]()
        else:
            if command in commands:
                commands[command]()
            else:
                self.log(f"未知命令: {command}")
                sys.exit(1)
if __name__ == "__main__":
    builder = ProjectBuilder()
    if len(sys.argv) > 1:
        command = sys.argv[1]
    else:
        command = 'all'
    try:
        builder.run(command)
        builder.log("构建成功!")
    except Exception as e:
        builder.log(f"构建失败: {str(e)}")
        sys.exit(1)

CI/CD集成脚本

GitHub Actions

# .github/workflows/build.yml
name: Build and Deploy
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Setup Node.js
      uses: actions/setup-node@v2
      with:
        node-version: '18'
    - name: Cache dependencies
      uses: actions/cache@v2
      with:
        path: ~/.npm
        key: ${{ runner.OS }}-npm-cache-${{ hashFiles('**/package-lock.json') }}
    - name: Install dependencies
      run: npm ci
    - name: Run lint
      run: npm run lint
    - name: Run tests
      run: npm test
      env:
        CI: true
    - name: Build project
      run: npm run build
    - name: Upload build artifacts
      uses: actions/upload-artifact@v2
      with:
        name: dist
        path: dist/
    - name: Deploy to server
      if: github.ref == 'refs/heads/main'
      run: |
        echo "部署到生产服务器..."
        # 添加部署命令

Jenkins pipeline

// Jenkinsfile
pipeline {
    agent any
    environment {
        NODE_ENV = 'production'
    }
    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }
        stage('Install Dependencies') {
            steps {
                sh 'npm install'
            }
        }
        stage('Run Tests') {
            steps {
                sh 'npm test'
            }
            post {
                always {
                    junit 'test-results/**/*.xml'
                }
            }
        }
        stage('Build') {
            steps {
                sh 'npm run build'
            }
        }
        stage('Deploy') {
            when {
                branch 'main'
            }
            steps {
                sh 'npm run deploy'
            }
        }
    }
    post {
        success {
            echo '构建成功!'
        }
        failure {
            echo '构建失败!'
        }
        always {
            archiveArtifacts artifacts: 'dist/**', fingerprint: true
        }
    }
}

最佳实践建议

版本控制

# 添加版本号
echo "构建版本: $(git describe --tags --always)"
echo "构建时间: $(date '+%Y-%m-%d %H:%M:%S')" > version.txt

环境配置

#!/bin/bash
# 根据环境选择配置
ENV=${1:-staging}
case $ENV in
  staging)
    export API_URL="https://staging-api.example.com"
    ;;
  production)
    export API_URL="https://api.example.com"
    ;;
esac
echo "使用环境: $ENV"

错误处理

#!/bin/bash
# 带错误处理的构建脚本
PROGRESS_FILE=".build_progress"
echo "build_started" > $PROGRESS_FILE
handle_error() {
    echo "构建失败: $1"
    echo "build_failed" > $PROGRESS_FILE
    exit 1
}
# 使用trap捕获错误
trap 'handle_error $?' ERR
# 构建步骤
echo "step1" 
[ -f package.json ] || handle_error "package.json不存在"
npm install || handle_error "依赖安装失败"
echo "build_completed" > $PROGRESS_FILE
echo "构建成功"

一键构建脚本模板

#!/bin/bash
# 全功能一键构建脚本
set -e
# 配置
PROJECT_NAME="my-project"
BUILD_DIR="build"
DIST_DIR="dist"
# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}
log_error() {
    echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') $1" >&2
}
# 检查依赖
check_requirements() {
    log "检查构建环境..."
    if ! command -v node &> /dev/null; then
        log_error "Node.js未安装"
        exit 1
    fi
    if ! command -v npm &> /dev/null; then
        log_error "npm未安装"
        exit 1
    fi
}
# 主构建函数
main() {
    check_requirements
    log "开始构建 ${PROJECT_NAME}"
    # 清理
    rm -rf ${BUILD_DIR} ${DIST_DIR}
    mkdir -p ${BUILD_DIR}
    # 依赖安装
    log "安装依赖..."
    npm install
    # 测试
    if [ -f "package.json" ]; then
        if grep -q '"test"' "package.json"; then
            log "运行测试..."
            npm test
        fi
    fi
    # 构建
    log "编译代码..."
    npm run build
    # 输出结果
    if [ -d "${DIST_DIR}" ]; then
        log "构建成功!输出目录: ${DIST_DIR}"
        du -sh ${DIST_DIR}
    else
        log_error "构建失败:输出目录不存在"
        exit 1
    fi
}
main "$@"

这个脚本模板包含:

  • 完整的错误处理
  • 日志记录
  • 环境检查
  • 模块化设计
  • 可配置选项

建议根据项目实际需求选择适合的构建工具和脚本方式,并逐步优化完善。

抱歉,评论功能暂时关闭!