开发公司项目时一般有专门的服务器来做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 # 上传前先清空目标文件夹