GitHub Actions上手全指南

真的很抱歉咕咕咕了这么久才发文章!因为一直在忙自己项目相关的事儿,就没咋管博客了(汗),不过咱人没失踪!所以!既然拖了辣么久,就决定了要来了个大的!(`ヮ´ )

什么是GitHub Actions?

如果项目需要编译、打包后才能变成能够被执行的可发行的软件,通常项目会需要一个CI(Continuous Integration,即持续集成)环境,以在特定事件(如一次提交或者PR)之后,实时对项目进行编译、打包。

比如有些软件的Nightly或Canary版,甚至每提交一次push就自动构建一个版本,这样的版本实际上就是CI版啦。

以往多数人会选择使用Jenkins等框架在本地或者私有服务器上部署,或者通过Travis CI、CircleCI等平台实现云端CI。作为全球最大的代码托管库,GitHub相应地也自己也推出了CI/CD服务,即传说中的GitHub Actions。

对咕咕这样不愿意到处跑去创建项目、复制粘贴ID和KEY的懒人来说,Actions开箱即用的特点,的确太太太太方便了!当然啦,毕竟咱技术能力有限,所以用个CI其实完完全全很够了。

快速上手

如果你的项目的CI要跑的命令很大众,无需过多自定义规则或配置,那就可以直接到官方的插件市场,找别人造好的轮子,导入进你的项目,大功告成!

慢速上手

创建工作流

通常一个大型项目会同时拥有好几个工作流(即workflow),像编译应用、评论审批、编译特定组件之类的工作,多是每一个工作由单独的工作流完成。而我们的小型项目最多也就编译打包下App,一个工作流足矣。

由于Actions的工作流使用YAML文件进行配置,所以你需要了解一些基本的YAML前置常识。当然看不全懂没关系啦,只要有一点了解就行。

给工作流起好一个名字,在项目根目录下创建目录.github/workflows,然后在该目录创建相应的yml配置文件。

如图配置,当我们在向项目push一个commit的时候,就会启动这个工作流。按照预期,GitHub会请求自己托管的专用于Actions环境的服务器(即runner),来执行该工作流的内容。

打开导航栏的“Actions”一项,打开刚刚请求的工作流,在“test”流程的“test01”步骤里,控制台中果然输出了“Hello, world!”这段字符串。

设置名称和触发条件

name字段是这个工作流的实际名称,用处似乎就是区分不同的工作流而已ᕕ( ᐛ )ᕗ

on字段用于设置该工作流执行的触发条件,常见的有:pushpull_requestissue_commentrelease等。

# 当 push commit 时触发工作流
on: push

# 当 push 到 dev 和 main 分支时触发工作流
on: 
   push:
      branches: [dev, main]

# 当 push commit 或新增 PR 时都触发工作流
on: [push, pull_request]

# 手动触发工作流
on: workflow_dispatch

配置工作流程

jobs字段中,每一个流程都是独立的,只有数据可以进行迁移(稍后会谈),所以我们需要单独为每个流程设定相关配置。

runs-on字段用于规定该流程运行的操作系统。一般情况下咱顶多使用以下三个值之一——windows-latestubuntu-latestmacos-latest——用于编译不同操作系统下的二进制文件。

接下来就是各个步骤(即steps字段)的内容!按照之前咱放的示例图,咕咕自己习惯将每个步骤开头冒号前的内容,叫做这个步骤的“步骤ID”,它是独一无二的,相当一个代表这个步骤的变量。

进入到具体的步骤中,首先是name字段,它能让每个步骤都有一个用于在Actions页面直观展示的名称。

其次就是id字段,一般推荐用小写字母+短横线连字符的方法命名,用于后面的数据交互!

最后就是run字段,就和咱在控制台上敲命令一样了,打根竖线再提行,一行写一个命令。

好嘞,完工!

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - name: 'Test Output'
      id: test-output
      run: |
        echo 'Hello, world!'

在某个步骤使用他人创建的Actions仓库

打个比方,咱跑前端项目需要设置好Node.js环境,但从下载Node二进制包到完成部署,即使在实际操作中也不可能不繁琐,更何况Actions这种需要盲打命令的情况。既然所有工作不可能全部手撸,能重复利用轮子的地方还是多多利用轮子的好!

所以Actions为我们提供了使用他人Actions仓库的功能。在步骤中,通过uses字段代替原有的run,咱就能使用他人仓库的Actions脚本,写得就更快,写出来的配置文件就更加简洁易懂。

# 将项目源码 clone 到本地
- name: 🧐 Checkout
  id: checkout
  uses: actions/checkout@main
  with: 
    fetch-depth: '0'

# 部署 Node.js 环境
- name: 🛠️ Setup Node.js Environment
  id: setup-node
  uses: actions/setup-node@v4
  with: 
    node-version: latest

如上述示例,uses字段中填写的应该是GitHub的项目,格式为“项目拥有者/项目名称”,同时需要用“@”符号指定要执行哪一个分支或标签上的脚本,查看相关Actions脚本仓库的分支/标签填入即可。

同时,如上述setup-node脚本需要传入node-version参数才能正常执行,所以咱需要通过with字段来传递参数。

checkout就相当于git clone的封装,故fetch-depth参数可根据需要改动或去除。咕咕此处添加,是因为当深度为0时才能正常获取项目当前分支的commit数,这是项目所需要的。

既然都用上Node.js了,不妨测试下它是否正常运行。

// test.js   注:此文件在根目录
const v = process.versions
console.log('当前 Node.js 版本:' + v.node)
console.log('当前 v8 引擎版本:' + v.v8)
console.warn('Not hello, world!')

// .github/workflows/test.yml 节选
- name: 👀 Test about Node.js
  id: test
  run: |
    node test.js

完美执行!

接下来我们就可以直接写构建生产版本的命令了!

上传构建好的文件

每次运行工作流的编译/构建好的东西叫作产物(即artifact),GitHub官方提供了一个Actions仓库——upload-artifact,用于给我们上传本次工作流的产物。

此Action脚本一般有两个参数——namepathname参数规定了这个上传的artifact会展示为什么名字,而path参数规定了要上传的artifact位于工作目录下哪一个路径,并将它打包。(注:即使这个路径指向一个文件而非文件夹,最终也是以.zip压缩包的形式上传)

由于咱项目打包好的文件位于dist文件夹内,所以最终如下配置:

 - name: 🌐 Upload the build
   id: upload
   uses: actions/upload-artifact@v4
   with: 
     name: dist
     path: dist
     # 此参数为可选参数,规定产物的有效天数,过期后不可下载
     retention-days: 30

不过注意了,此处产物的大小是以原始大小计算,而非压缩后大小计算,真是莫名其妙

多job信息传递

导出变量

为了在job中使用前一个job获取到的信息,这时我们就需要在step中先将变量导出,再在job的output字段里将该变量输出。

现在Actions的变量导出方式和Linux中一致,通过echo实现。比如,我们要获取当前时间并导出,则可以:

steps:
 - name: Get current time
   id: get-time
   run: |
      TIME_VAR=$(date "+%Y%m%d %H:%M:%S")
      echo "TIME_EXPORT=${TIME_VAR}" >> $GITHUB_OUTPUT

然后再在上级的job中通过outputs字段将其输出,以给其它job使用:

jobs: 
   # 创建 id 为 setup 的 job,以将导出的数据输出,get-time 步骤就在其中
   setup:
      name: Setup Information
      runs-on: ubuntu-latest
      outputs: 
         # get-time 是导出数据的步骤的 id,TIME_EXPORT 是导出的数据的变量名称
         TIME_OUTPUT: ${{ steps.get-time.outputs.TIME_EXPORT }}
      steps: ......

其它job中使用变量

Actions允许我们在jobs的env字段中,预置该job中可用的变量。同样地,咱可以先从needs字段中接收之前的job输出的内容,再在env字段中将其设为可用的变量。

jobs:
   setup:
      ......

   print:
      name: Print Information
      runs-on: ubuntu-latest
      needs: setup
      env:
         # 为该 job 的运行环境添加一个名为 TIME_ENV 的变量,变量的值来自于 id 为 setup 的 job 所输出的名为 TIME_OUTPUT 的变量
         TIME_ENV: ${{ needs.setup.outputs.TIME_OUTPUT }}
      steps:  ......

接下来,我们就能在在该job下任一步骤中使用变量了!

steps:
 - name: Print Time
   id: print-time
   run: |
      echo ${{ env.TIME_ENV }}

那么我们就能顺利地在控制台看到时间被打印出来了👀

此时可以看到,工作流的两个job已经形成前后合作的关系

注:上述变量名称可以自定,不一定非要加后缀,此处加上只是为了方便辨析,如果要变量全叫同一个名字也没问题。

实例

我们一般做这样的简单项目,多job信息传递的最大用处就是更改产物上传所显示的名字,以达到辨别版本的目的。

首先在之前“创建生产页面”的Action的基础上,在build之前创建一个id为setup的job,以获取基本信息。

setup:
    name: Setup Project Info
    runs-on: ubuntu-latest
    outputs:
       DIST_SUFFIX: ${{ steps.get-suffix.outputs.DIST_SUFFIX }}
    steps: 
     - name: 🧐 Checkout
       id: checkout
       uses: actions/checkout@v4
       with: 
          fetch-depth: '0'

     - name: 📙 Get Package Suffix
       id: get-suffix
       run: |
         # 获取当前版本,此处直接从 package.json 读取
         sudo apt-get install jq
         VERSION=$(jq -r '.version' ./package.json)
         # 获取 commit 数
         COMMIT_COUNT=$(git rev-list --count HEAD)
         # 获取构建日期
         BUILD_DATE=$(date "+%y%m%d")
         # 获取构建 commit head 哈希
         HEAD_SHA=$(git rev-parse --short HEAD)
         echo "DIST_SUFFIX=${TAG_NAME}-${COMMIT_COUNT}-${BUILD_DATE}-${HEAD_SHA}" >> $GITHUB_OUTPUT

build:
   name: Build Production Page
   needs: setup
   env:
      DIST_NAME: dist-${{ needs.setup.outputs.DIST_SUFFIX }}
   runs-on: ubuntu-latest
   steps:
      ......

    - name: 🌐 Upload the build
      id: upload
      uses: actions/upload-artifact@v4
      with:
         name: ${{ env.DIST_NAME }}
         path: dist
         retention-days: 60

可以看到产物名称已经规范ᕕ( ᐛ )ᕗ

好耶!完结撒花!

除特殊声明转载之外,本文由博主 云萧只会咕咕咕 原创,依据 CC BY-NC-SA 4.0 许可协议授权,转载请注明出处。(*◦˙▽˙◦)
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇