一、什么是GitHub Actions? GitHub Actions是GitHub提供的自动化工作流工具,可以自动执行代码构建、测试、部署等流程。
1.1 核心概念 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ┌─────────────────────────────────────────────────────────────────┐ │ GitHub Actions 工作流 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 提交代码 → 触发Workflow → 运行Job → 执行Step → 完成部署 │ │ │ │ ┌──────────────────────────────────────────────────────────┐ │ │ │ Workflow(工作流) │ │ │ │ └── Job(任务) │ │ │ │ └── Step (步骤) │ │ │ │ └── Action (动作) │ │ │ └──────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘
概念
说明
Workflow
整个自动化流程,可在仓库设置多个
Job
一组Step,每个Workflow可多个Job(并行执行)
Step
每个Job中的具体步骤(命令或Action)
Action
可复用的步骤单元,可自定义或使用市场组件
1.2 典型使用场景
场景
说明
自动测试
每次提交自动运行测试用例
自动构建
代码提交后自动构建项目
自动部署
测试通过后自动部署到服务器
自动发布
打标签时自动发布Release
定时任务
定时执行清理/备份等任务
二、快速入门 2.1 创建第一个Workflow 1 2 3 4 5 mkdir -p .github/workflowstouch .github/workflows/hello.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 name: Hello World on: push: branches: [main ] pull_request: branches: [main ]jobs: hello: runs-on: ubuntu-latest steps: - name: Checkout代码 uses: actions/checkout@v4 - name: 输出Hello run: echo "Hello, GitHub Actions!" - name: 查看环境信息 run: | echo "GitHub Actions真好用" echo "当前时间: $(date)"
2.2 手动触发工作流 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 name: 手动部署 on: workflow_dispatch: inputs: environment: description: '部署环境' required: true default: 'test' type: choice options: - test - prod jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: 部署到 ${{ github.event.inputs.environment }} run: echo "部署到 ${{ github.event.inputs.environment }} 环境"
三、部署静态网站到GitHub Pages 3.1 基础配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 name: Deploy to GitHub Pages on: push: branches: [main ]permissions: contents: write jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - name: Install Dependencies run: npm ci - name: Build run: npm run build - name: Deploy uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./dist
3.2 Vue项目部署 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 name: Deploy Vue App on: push: branches: [main ]permissions: contents: write jobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - name: Install Dependencies run: | npm ci npm run build - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./dist
3.3 Hexo博客部署 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 name: Deploy Hexo Blog on: push: branches: [main ]permissions: contents: write jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 with: submodules: true fetch-depth: 0 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' - name: Cache npm dependencies uses: actions/cache@v3 with: path: node_modules key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }} restore-keys: | ${{ runner.os }}-npm- - name: Install Dependencies run: npm ci - name: Generate Static Files run: npm run build - name: Deploy uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./public
四、部署到服务器 4.1 配置SSH密钥 1 2 3 4 5 6 7 8 9 10 ssh-keygen -t ed25519 -C "deploy@github-actions" -f ~/.ssh/deploy_keycat ~/.ssh/deploy_key.pub >> ~/.ssh/authorized_keys
4.2 部署到VPS 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 name: Deploy to VPS on: push: branches: [main ]jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' - name: Install Dependencies run: npm ci - name: Build run: npm run build - name: Deploy to Server uses: appleboy/ssh-action@v0.1.0 with: host: ${{ secrets.SERVER_HOST }} username: ${{ secrets.SERVER_USER }} key: ${{ secrets.DEPLOY_KEY }} port: 22 script: | cd /var/www/myapp git pull origin main npm ci npm run build pm2 restart all
4.3 多环境部署 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 name: Deploy to Multiple Environments on: push: branches: [main ] workflow_dispatch: inputs: environment: description: 'Select environment' required: true default: 'test' type: choice options: - test - staging - prod jobs: deploy-test: runs-on: ubuntu-latest if: github.event_name == 'push' || github.event.inputs.environment == 'test' steps: - uses: actions/checkout@v4 - name: Deploy to Test run: | echo "部署到测试环境" # 部署命令... deploy-staging: runs-on: ubuntu-latest if: github.event.inputs.environment == 'staging' steps: - uses: actions/checkout@v4 - name: Deploy to Staging run: | echo "部署到预发环境" # 部署命令... deploy-prod: runs-on: ubuntu-latest if: github.event.inputs.environment == 'prod' needs: [deploy-staging ] steps: - uses: actions/checkout@v4 - name: Deploy to Production run: | echo "部署到生产环境" # 部署命令...
五、自动测试 5.1 Node.js测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 name: Test on: push: branches: [main ] pull_request: branches: [main ]jobs: test: runs-on: ubuntu-latest strategy: matrix: node-version: [18 , 20 , 22 ] steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: 'npm' - name: Install Dependencies run: npm ci - name: Run Tests run: npm test - name: Upload Coverage uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }}
5.2 Python测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 name: Python Test on: push: branches: [main ] pull_request: branches: [main ]jobs: test: runs-on: ubuntu-latest strategy: matrix: python-version: ['3.10' , '3.11' , '3.12' ] steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} cache: 'pip' - name: Install Dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt pip install pytest pytest-cov - name: Run Tests run: pytest --cov=. --cov-report=xml - name: Upload Coverage uses: codecov/codecov-action@v3
六、Docker自动化 6.1 自动构建镜像 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 name: Build and Push Docker on: push: branches: [main ] tags: ['v*' ]jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Extract Metadata id: meta uses: docker/metadata-action@v5 with: images: myapp/myapp tags: | type=ref,event=branch type=sha type=match,pattern=v(.+) - name: Build and Push uses: docker/build-push-action@v5 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=registry,ref=myapp/myapp:latest cache-to: type=inline
6.2 自动部署Docker Compose 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 name: Deploy with Docker Compose on: push: branches: [main ]jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Install Docker Compose run: | sudo curl -L "https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose - name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Pull latest images run: docker-compose pull - name: Restart services run: docker-compose up -d - name: Check health run: | sleep 10 curl -f http://localhost:8080/health || exit 1
七、定时任务 7.1 定时清理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 name: Scheduled Cleanup on: schedule: - cron: '0 3 * * *' workflow_dispatch: jobs: cleanup: runs-on: ubuntu-latest steps: - name: Cleanup old data run: | echo "清理7天前的日志" find /path/to/logs -type f -mtime +7 -delete echo "清理完成"
7.2 定时备份 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 name: Daily Backup on: schedule: - cron: '0 2 * * *' jobs: backup: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Backup Database run: | mysqldump -h ${{ secrets.DB_HOST }} -u ${{ secrets.DB_USER }} -p${{ secrets.DB_PASSWORD }} myapp > backup_$(date +%Y%m%d).sql - name: Upload to S3 uses: actions/upload-artifact@v3 with: name: backup path: backup_*.sql retention-days: 30
八、常用Action推荐
九、Secrets配置 9.1 添加Secret 1 2 3 4 5 1. 进入仓库 → Settings2. 左侧Secrets and variables → Actions3. 点击 New repository secret4. 输入Name和Value5. 点击 Add secret
9.2 常用Secrets
Name
说明
示例
DEPLOY_KEY
SSH私钥
—–BEGIN OPENSSH PRIVATE KEY—–
SERVER_HOST
服务器IP
192.168.1.100
SERVER_USER
服务器用户名
root
DOCKERHUB_TOKEN
Docker Hub令牌
xxx
AWS_ACCESS_KEY_ID
AWS访问密钥
xxx
AWS_SECRET_ACCESS_KEY
AWS密钥
xxx
十、调试技巧 10.1 本地测试 1 2 3 4 5 6 7 8 9 10 11 act -l act -W .github/workflows/deploy.yml act -j deploy
10.2 查看日志 1 2 3 4 1. 进入仓库 → Actions2. 选择具体工作流运行3. 查看每个Job的日志4. 失败的Step会标红
十一、实战案例:完整CI/CD流程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 name: CI/CD Pipeline on: push: branches: [main ] pull_request: branches: [main ]env: NODE_VERSION: '20' REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' - run: npm ci - run: npm run lint test: runs-on: ubuntu-latest needs: lint steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' - run: npm ci - run: npm test --if-present - run: npm run test:coverage --if-present build: runs-on: ubuntu-latest needs: test if: github.event_name == 'push' && github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract Metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=sha,prefix= type=ref,event=branch - name: Build and Push uses: docker/build-push-action@v5 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} deploy: runs-on: ubuntu-latest needs: build if: github.event_name == 'push' && github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v4 - name: Deploy to Server uses: appleboy/ssh-action@v0.1.0 with: host: ${{ secrets.SERVER_HOST }} username: ${{ secrets.SERVER_USER }} key: ${{ secrets.DEPLOY_KEY }} script: | cd /var/www/myapp docker-compose pull docker-compose up -d docker system prune -f
参考资料
持续更新中…欢迎收藏!
#GitHub #CI/CD #自动化 #DevOps #教程