CI/CD流水线:使用GitHub Actions自动化部署
大家好,我是欧阳瑞(Rich Own)。今天想和大家聊聊CI/CD这个话题。作为一个全栈开发者,我深知自动化部署的重要性。一个好的CI/CD流水线可以大大提高开发效率,减少人为错误。今天就来分享一下如何使用GitHub Actions构建CI/CD流水线。
什么是CI/CD?
CI/CD代表持续集成(Continuous Integration)和持续部署(Continuous Deployment)。
| 阶段 | 描述 |
|---|---|
| 持续集成 | 代码提交后自动构建和测试 |
| 持续交付 | 自动部署到测试环境 |
| 持续部署 | 自动部署到生产环境 |
为什么需要CI/CD?
- 提高效率:自动化重复任务
- 减少错误:避免人为失误
- 快速反馈:立即发现问题
- 持续改进:频繁发布新功能
GitHub Actions基础
什么是GitHub Actions?
GitHub Actions是GitHub提供的CI/CD服务,可以自动化软件开发工作流程。
核心概念
| 概念 | 描述 |
|---|---|
| Workflow | 自动化流程的定义 |
| Job | 一组步骤的集合 |
| Step | 单个命令或动作 |
| Action | 可重用的步骤 |
| Runner | 执行工作流的服务器 |
创建第一个Workflow
# .github/workflows/hello-world.yml name: Hello World on: [push] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Run a one-line script run: echo "Hello, World!" - name: Run a multi-line script run: | echo "This is a multi-line script" echo "It can have multiple commands"Node.js项目CI/CD
项目结构
my-node-app/ ├── src/ │ └── index.js ├── package.json └── .github/ └── workflows/ └── ci-cd.ymlWorkflow配置
# .github/workflows/ci-cd.yml name: Node.js CI/CD on: push: branches: [ main ] pull_request: branches: [ main ] jobs: build: runs-on: ubuntu-latest strategy: matrix: node-version: [16.x, 18.x] steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} cache: 'npm' - name: Install dependencies run: npm ci - name: Run tests run: npm test - name: Build run: npm run build deploy: needs: build runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v3 - name: Deploy to production uses: some-deployment-action@v1 with: target: production api-key: ${{ secrets.DEPLOY_API_KEY }}React项目CI/CD
构建和部署到Vercel
name: React CI/CD on: push: branches: [ main ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18.x' cache: 'npm' - name: Install dependencies run: npm ci - name: Run tests run: npm test - name: Build run: npm run build env: CI: false deploy: needs: build runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Deploy to Vercel uses: amondnet/vercel-action@v20 with: vercel-token: ${{ secrets.VERCEL_TOKEN }} vercel-org-id: ${{ secrets.VERCEL_ORG_ID }} vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }} vercel-args: '--prod'Docker项目CI/CD
构建Docker镜像
name: Docker CI/CD on: push: branches: [ main ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Login to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Build and push uses: docker/build-push-action@v4 with: context: . push: true tags: ${{ secrets.DOCKER_USERNAME }}/my-app:latestKubernetes部署
部署到K8s集群
name: Kubernetes Deployment on: push: branches: [ main ] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up Kubectl uses: azure/setup-kubectl@v3 with: version: 'latest' - name: Authenticate to cluster uses: google-github-actions/get-gke-credentials@v2 with: cluster_name: ${{ secrets.GKE_CLUSTER_NAME }} project_id: ${{ secrets.GCP_PROJECT_ID }} location: ${{ secrets.GKE_REGION }} - name: Deploy to Kubernetes run: | kubectl set image deployment/my-app my-app=${{ secrets.DOCKER_USERNAME }}/my-app:${{ github.sha }} kubectl rollout status deployment/my-app智能合约CI/CD
编译和测试Solidity合约
name: Solidity CI/CD on: push: branches: [ main ] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: version: nightly - name: Run tests run: forge test -vvv - name: Run coverage run: forge coverage deploy: needs: test runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v3 - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: version: nightly - name: Deploy to Goerli run: forge create --rpc-url ${{ secrets.GOERLI_RPC_URL }} --private-key ${{ secrets.PRIVATE_KEY }} src/MyContract.sol:MyContract多环境部署
name: Multi-environment Deployment on: push: branches: - main - staging jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Build run: npm run build deploy-staging: needs: build runs-on: ubuntu-latest if: github.ref == 'refs/heads/staging' steps: - name: Deploy to staging run: echo "Deploying to staging..." deploy-production: needs: build runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - name: Deploy to production uses: chrnorm/deployment-action@releases/v1 with: token: ${{ github.token }} target_url: https://example.com environment: production自动化测试和质量检查
name: Quality Check on: [push, pull_request] jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Run ESLint run: npx eslint . typecheck: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Run TypeScript check run: npx tsc --noEmit audit: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Run npm audit run: npm audit --audit-level=critical自定义Action
创建JavaScript Action
// action/index.js const core = require('@actions/core'); const github = require('@actions/github'); async function run() { try { const name = core.getInput('name'); console.log(`Hello, ${name}!`); const octokit = github.getOctokit(core.getInput('github-token')); const { data } = await octokit.rest.repos.get({ owner: github.context.repo.owner, repo: github.context.repo.repo }); console.log(`Repository: ${data.full_name}`); } catch (error) { core.setFailed(error.message); } } run();# action/action.yml name: 'Hello World' description: 'Greet someone' inputs: name: description: 'Name to greet' required: true default: 'World' github-token: description: 'GitHub token' required: true runs: using: 'node16' main: 'index.js'最佳实践
1. 使用缓存
- name: Cache dependencies uses: actions/cache@v3 with: path: node_modules key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} restore-keys: | ${{ runner.os }}-node-2. 并行作业
jobs: test-linux: runs-on: ubuntu-latest steps: [...] test-windows: runs-on: windows-latest steps: [...] test-macos: runs-on: macos-latest steps: [...]3. 条件执行
steps: - name: Deploy if: github.event_name == 'push' && github.ref == 'refs/heads/main' run: npm run deploy4. 环境变量和密钥
steps: - name: Run script env: API_KEY: ${{ secrets.API_KEY }} NODE_ENV: production run: node script.js总结
GitHub Actions是一个功能强大的CI/CD工具,可以帮助你自动化软件开发流程。从简单的测试到复杂的多环境部署,GitHub Actions都能胜任。
我的鬃狮蜥Hash对CI/CD也有自己的理解——它总是按照固定的流程:晒太阳→吃蟋蟀→睡觉,形成了一个完美的"持续生活"循环。这和我们做CI/CD的道理是一样的。
如果你有CI/CD方面的问题,欢迎留言交流!我是欧阳瑞,极客之路,永无止境!
技术栈:GitHub Actions · CI/CD · Docker · Kubernetes · Vercel