白嫖的CI/CD资源 -- GitHub Actions

805 阅读3分钟

开发公司项目时一般有专门的服务器来做CI/CD,但是作为普通开发者自己一般只有一台低配的服务器,再分配出本就不多的资源给CI/CD就有点捉襟见肘了,所幸github提供了免费的CI/CD -- GitHub Actions,大部分人的项目也是托管在GitHub上,这个白嫖的资源怎么能浪费呢。

官方文档:GitHub Actions

什么是CI/CD?

额,这个就不赘述了...

创建项目

项目必须托管在github,在github创建或将已有项目推送到github

创建Actions

action就是工作流,可以理解就是你推送代码等行为触发的自动执行的任务。

先项目中点击Actions

如果在当前项目中是首次创建Action,下面会显示一些常用模板供你选择,这里我们选择重新创建。

Action的语法其实很简单,点击创建后会在当前项目的.github/workflows/下创建main.yml文件,看一遍下面的示例和注释,基本就可以了解基本写法了。

# This is a basic workflow to help you get started with Actions
# 当前这个Action的名字,可以任意起
name: CI

# Controls when the workflow will run
# on关键字,控制这个Action的执行时机
on:
  # Triggers the workflow on push or pull request events but only for the "master" branch
	# 在master分支的push和pull_request时触发
  push:
    branches: [ "master" ]
  pull_request:
    branches: [ "master" ]

  # Allows you to run this workflow manually from the Actions tab
	# 允许你在项目的Actions tab下手动执行当前Action
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
# 当前Action具体要执行的工作(jobs)
jobs:
  # This workflow contains a single job called "build"
	# 当前Action只包含一个job,名为"build",若想添加更多job,与build并行往下写即可(与上面的on类似)
  build:
    # The type of runner that the job will run on
  	# 当前job的运行环境,注意,这个运行环境是github提供的虚拟机,是这个ci脚本要执行的环境,而不是你的代码部署之后运行的环境。用默认的配置即可
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
  	# 当前job具体要执行的任务流
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
    	# 任务1  每个任务以一个 "-" 开头
    	# uses 关键字,表示使用github的actions仓库中已有的脚本,这与使用npm包类似,在使用时也可以添加一些配置参数
    	# 使用github提供的"checkout@v3"脚本,来检出代码(检出的是上面on配置的分支,这里即master)
      - uses: actions/checkout@v3

      # Runs a single command using the runners shell
    	# 任务2 执行一个单行脚本
      - name: Run a one-line script
        run: echo Hello, world!

      # Runs a set of commands using the runners shell
    	# 执行多行脚本
      - name: Run a multi-line script
        run: |
          echo Add other actions to build,
          echo test, and deploy your project.

runs-on

注意这个环境指的是当前这个action脚本运行的环境,即是GitHub提供的虚拟环境,并不是我们代码部署最后部署环境。

目前支持的环境:

运行器

触发Action

把刚才创建的文件提交,等于在master分支上触发了push操作,github会扫描.github/workflows/下的yml文件,拿到刚才创建的main.yml文件,开始执行这个Action,在设置的ubuntu虚拟机里,先检出master代码,然后打印Hello, world!,然后打印Add other actions to build 最后打印test, and deploy your project 结束。

部署Vue/React项目

这里我们只需要关注jobs的改动即可。

部署流程

一个前端静态项目的完整部署流程如下:

graph LR
拉取最新代码 --> 安装node环境 --> B["安装依赖(npm install)"] --> C["执行打包命令(build)"] --> D["将产物(dist)拷贝到目标服务器"]

使用github的actions仓库中的预设

对于一些常用操作,比如安装node环境(再次强调,我们的脚本是跑在github提供的虚拟环境里的,所以这里安装node环境也是指在github的虚拟环境里安装)、使用scp复制静态文件到我们自己的服务器。

在action的编辑页右侧搜索需要的功能,下面可以找一个star比较多的点进去

介绍了这个action的功能、使用方法、接收参数,点击View full Marketplace listing可以查看更详细的文档。

安装node环境

# ...
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      # 检出你的分支,GitHub提供的预设脚本
      - uses: actions/checkout@v3

      # 安装node环境 这种通用的脚本在GitHub上都有现成的,可以直接去GitHub搜索
      - name: Setup Node.js environment
        uses: actions/setup-node@v3.4.1
        with: # 参数
          node-version: "14.x" # 指定安装14版本node

打包

安装完node环境,按步骤执行常规打包流程即可:安装依赖 -> build

# ...
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      # 检出你的分支,GitHub提供的预设脚本
      - uses: actions/checkout@v3

      # 安装node环境 这种通用的脚本在GitHub上都有现成的,可以直接去GitHub搜索
      - name: Setup Node.js environment
        uses: actions/setup-node@v3.4.1
        with:
          node-version: "14.x" # 指定安装14版本node

    	# 安装依赖
      - name: install deps
        run: npm install

    	# 打包
      - name: build app
        run: npm run buil

使用scp拷贝产物到目标服务器

这里我们也直接使用预设的action

根据使用文档添加step

    	# 打包
      - name: build app
        run: npm run buil

    	# 拷贝产物到目标服务器
			- name: copy file via ssh password
        uses: appleboy/scp-action@master # doc: https://github.com/marketplace/actions/scp-files
        with:
          host: 111.22.33.44 # 目标服务器的host
          username: abcd # 账号
          password: 1234 # 密码 ,也可以使用ssh key,参考文档
          port: 22
          source: "dist" # 要拷贝的文件路径
          target: /var/web/static # 要发送到的目标服务器的路径
          strip_components: 1 # 当前移动过去会变为 /var/web/static/dist/...  这里指定向上跳过1层变为 /var/web/static/...
          rm: true # 上传前先清空目标文件夹

至此就完成了一个基本的部署流程,只要目标服务器nginx配置好文件目录,就可以访问了。

使用screts

可以看到上面在使用scp时,我们将账号密码明文的写到了main.yml文件里,但是这个文件在github上是公开的,显然这样是不可行的。github提供了screts让我们来保存这些敏感的信息。

创建scret

可以看到这些screts在创建后只能在当前项目使用、更新和删除,不能查看,因此是安全的。

使用screts替换main.yml里的敏感信息

    	# 拷贝产物到目标服务器
			- name: copy file via ssh password
        uses: appleboy/scp-action@master # doc: https://github.com/marketplace/actions/scp-files
        with:
          host: ${{ secrets.REMOTE_HOST }}
          username: ${{ secrets.REMOTE_USER }}
          password: ${{ secrets.REMOTE_PASS }}
          port: 22
          source: "dist" # 要拷贝的文件路径
          target: ${{ secrets.REMOTE_TARGET }} # 要发送到的目标服务器的路径
          strip_components: 1
          rm: true # 上传前先清空目标文件夹

完整配置文件如下

# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the workflow will run
# 控制workflow的执行时机
on:
  # Triggers the workflow on push or pull request events but only for the "master" branch
  # 在master分支被push或pull_request时触发
  push:
    branches: [ "master" ]
  pull_request:
    branches: [ "master" ]

  # Allows you to run this workflow manually from the Actions tab
  # 允许你在Action tabs里手动执行这个workflow
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
# 一个workflow由一个或多个jobs组成,他们可以串行或并行执行
jobs:
  # This workflow contains a single job called "build"
  # 这个workflow包含一个名为"build"的job
  build:
    # The type of runner that the job will run on
    # 这个job的运行环境,注意,这并不是你自己的服务器的环境,而是指定的当前这个job执行的脚本的运行环境,是github提供的虚拟机
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    # Steps是一系列要执行的任务,他们属于job的一部分
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      # 检出你的分支,GitHub提供的预设脚本
      - uses: actions/checkout@v3

      # 安装node环境 这种通用的脚本在GitHub上都有现成的,可以直接去GitHub搜索
      - name: Setup Node.js environment
        uses: actions/setup-node@v3.4.1
        with:
          node-version: "14.x" # 指定安装14版本node

    	# 安装依赖
      - name: install deps
        run: npm install

    	# 打包
      - name: build app
        run: npm run buil

    	# 拷贝产物到目标服务器
			- name: copy file via ssh password
        uses: appleboy/scp-action@master # doc: https://github.com/marketplace/actions/scp-files
        with:
          host: ${{ secrets.REMOTE_HOST }} # 目标服务器的host
          username: ${{ secrets.REMOTE_USER }} # 账号
          password: ${{ secrets.REMOTE_PASS }} # 密码 ,也可以使用ssh key,参考文档
          port: 22
          source: "dist" # 要拷贝的文件路径
          target: ${{ secrets.REMOTE_TARGET }} # 要发送到的目标服务器的路径
          strip_components: 1 # 当前移动过去会变为 /var/web/static/dist/...  这里指定向上跳过1层变为 /var/web/static/...
          rm: true # 上传前先清空目标文件夹