自动化部署编译部署【.net core】

github 自动化编译部署 .NET 程序,程序有两个服务,一个是api,一个是admin.
需要部署到两台机器上(测试和正式),所以采用两个Action来处理

项目目录结构

root
├── Config
│   ├── deploy
│   │   ├── nginx
│   │   │   ├── admin.conf
│   │   │   └── api.conf
│   │   ├── cert
│   │   │   ├── api.example.com.pem
│   │   │   ├── api.example.com.key
│   │   │   ├── admin.example.com.pem
│   │   │   └── admin.example.com.key
│   │   ├── supervisor
│   │   │   ├── admin.conf
│   │   │   └── api.conf
│   │   └── setting
│   │       ├── api.json
│   │       └── admin.json
│   └── deploy_test
│       ├── nginx
│       │   ├── testadmin.conf
│       │   └── testapi.conf
│       ├── cert
│       │   ├── testapi.example.com.pem
│       │   ├── testapi.example.com.key
│       │   ├── testadmin.example.com.pem
│       │   └── testadmin.example.com.key
│       ├── supervisor
│       │   ├── testadmin.conf
│       │   └── testapi.conf
│       └── setting
│           ├── testapi.json
│           └── testadmin.json
├── Admin
│   ├── appsettings.json
│   └── Admin.csproj
├── Api
│   ├── appsettings.json
│   └── Api.json
└── Website
    ├── static
    └── index.html

不太好看的流程图

图片alt

部署 Admin 服务的action

这里使用分支来做不同环境的部署, deploymaster 签出部署至正式机器,deploy_testdev 签出部署至测试机器,下面的action也只能从这两个分支中自动触发,其他的分支都可以手动触发流程,当然手动触发只支持部署至测试机器。


name: Deploy Admin
on:
  push:
    branches:
      - deploy
      - deploy_test
  #    paths:
  #      - "**.cs"
  workflow_dispatch:
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup .NET
        uses: actions/setup-dotnet@v3
        with:
          dotnet-version: 7.0
      - name: Restore dependencies
        run: dotnet restore
      - name: Publish
        run: |
          dotnet publish Admin/Web.Admin.csproj -c Release -o release/AdminServer
          mkdir -p release/Config

      - name: Copy Deploy Test File
        if: github.ref != 'refs/heads/deploy'
        run: |
          cp -rf Config/deploy_test/* release/Config/
          cp -f Config/deploy_test/setting/admin.json release/AdminServer/appsettings.json

      - name: Copy Deploy File
        if: github.ref == 'refs/heads/deploy' || github.ref == 'refs/heads/master'
        run: |
          cp -rf Config/deploy/* release/Config/
          cp -f Config/deploy/setting/admin.json release/AdminServer/appsettings.json

      - name: Tar AdminServer
        run: tar -czvf AdminServer.tar.gz -C release .

      - name: Deploy To TEST
        uses: cross-the-world/ssh-scp-ssh-pipelines@v1.1.4
        if: github.ref != 'refs/heads/deploy' && github.ref != 'refs/heads/master'
        with:
          host: ${{ secrets.DEPLOY_TEST_SSH_HOST}}
          port: ${{ secrets.SSH_PORT }}
          user: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_KEY }}
          first_ssh: |
            rm -f /home/shop/AdminServer.tar.gz
            mkdir -p /home/shop/logs/
          scp: |
            AdminServer.tar.gz => /home/shop/
          last_ssh: |
            cd /home/shop/
            tar -xzvf AdminServer.tar.gz --overwrite
            ln -sf /home/shop/Config/supervisor/admin_service.conf /etc/supervisor/conf.d/shop_admin.conf
            ln -sf /home/shop/Config/nginx/shop.conf /etc/nginx/sites-enabled/admin_nginx.conf
            supervisorctl reread
            supervisorctl update
            supervisorctl restart adminserver
            nginx -s reload

      - name: Deploy To PROD
        uses: cross-the-world/ssh-scp-ssh-pipelines@v1.1.4
        if: github.ref == 'refs/heads/deploy' || github.ref == 'refs/heads/master'
        with:
          host: ${{ secrets.DEPLOY_SSH_HOST}}
          port: ${{ secrets.SSH_PORT }}
          user: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_KEY }}
          first_ssh: |
            rm -f /home/shop/AdminServer.tar.gz
            mkdir -p /home/shop/logs/
          scp: |
            AdminServer.tar.gz => /home/shop/
          last_ssh: |
            cd /home/shop/
            tar -xzvf AdminServer.tar.gz --overwrite
            ln -sf /home/shop/Config/supervisor/admin_service.conf /etc/supervisor/conf.d/shop_admin.conf
            ln -sf /home/shop/Config/nginx/shop.conf /etc/nginx/sites-enabled/admin_nginx.conf
            supervisorctl reread
            supervisorctl update
            supervisorctl restart adminserver
            nginx -s reload

部署 Api 服务的action

内容其实更 Admin 大同小异啦

name: Deploy Api
on:
  push:
    branches:
      - deploy
      - deploy_test
#    paths:
#      - "**.cs"
  workflow_dispatch:
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup .NET
        uses: actions/setup-dotnet@v3
        with:
          dotnet-version: 7.0
      - name: Restore dependencies
        run: dotnet restore

      - name: Publish
        run: |
          dotnet publish WebApi/WebApi.csproj -c Release -o release/ApiServer
          mkdir -p release/Config

      - name: Copy Deploy Test File
        if: github.ref != 'refs/heads/deploy' && github.ref != 'refs/heads/master'
        run: |
          cp -rf Config/deploy_test/* release/Config/
          cp -f Config/deploy_test/setting/api.json release/ApiServer/appsettings.json

      - name: Copy Deploy File
        if: github.ref == 'refs/heads/deploy' || github.ref == 'refs/heads/master'
        run: |
          cp -rf Config/deploy/* release/Config/
          cp -f Config/deploy/setting/api.json release/ApiServer/appsettings.json

      - name: Tar ApiServer
        run: tar -czvf ApiServer.tar.gz -C release .

      - name: Deploy To TEST
        uses: cross-the-world/ssh-scp-ssh-pipelines@v1.1.4
        if: github.ref != 'refs/heads/deploy' && github.ref != 'refs/heads/master'
        with:
          host: ${{ secrets.DEPLOY_TEST_SSH_HOST}}
          port: ${{ secrets.SSH_PORT }}
          user: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_KEY }}
          first_ssh: |
            rm -f /home/shop/ApiServer.tar.gz
            mkdir -p /home/shop/logs/
          scp: |
            ApiServer.tar.gz => /home/shop/
          last_ssh: |
            cd /home/shop/
            tar -xzvf ApiServer.tar.gz --overwrite
            ln -sf /home/shop/Config/supervisor/api_service.conf /etc/supervisor/conf.d/shop_api.conf
            ln -sf /home/shop/Config/nginx/api.conf /etc/nginx/sites-enabled/api_nginx.conf
            supervisorctl reread
            supervisorctl update
            supervisorctl restart apiserver
            nginx -s reload

      - name: Deploy To PROD
        uses: cross-the-world/ssh-scp-ssh-pipelines@v1.1.4
        if: github.ref == 'refs/heads/deploy' || github.ref == 'refs/heads/master'
        with:
          host: ${{ secrets.DEPLOY_SSH_HOST}}
          port: ${{ secrets.SSH_PORT }}
          user: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_KEY }}
          first_ssh: |
            rm -f /home/shop/ApiServer.tar.gz
            mkdir -p /home/shop/logs/
          scp: |
            ApiServer.tar.gz => /home/shop/
          last_ssh: |
            cd /home/shop/
            tar -xzvf ApiServer.tar.gz --overwrite
            ln -sf /home/shop/Config/supervisor/api_service.conf /etc/supervisor/conf.d/shop_api.conf
            ln -sf /home/shop/Config/nginx/api.conf /etc/nginx/sites-enabled/api_nginx.conf
            supervisorctl reread
            supervisorctl update
            supervisorctl restart apiserver
			nginx -s reload

后期优化的地方

  1. 每次部署的时候 都需要重新编译代码,就算只改了配置文件,部署一次需要两分半, 考虑使用 paths-filter 优化。
  2. 后期一台机器撑不住的时候如何多台机器同时部署。

暂时考虑在正式机器部署完成之后,ssh 通过内网把文件传输到其他机器上面重启服务,但是又要考虑到部署不成功, 如何通知?并快速的回退上次部署?

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐