使用 GitHub Action 自动化构建 Golang 程序并发布

Qiang 发布在技术 1

我们首先创建一个文件.github/workflows/go.yml,内容如下所示:

name: Release
on:
  create:
    tags:
    - v*

jobs:
  release:
    name: Release on GitHub
    runs-on: ubuntu-latest
    steps:
    - name: Check out code
      uses: actions/checkout@v1

    - name: Get service dependencies
      working-directory: ./
      run:  |
        go get -v -u -d ./...
        if [ -f Gopkg.toml ]; then
            curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
            dep ensure
        fi

    - name: Validates GO releaser config
      uses: docker://goreleaser/goreleaser:latest
      with:
        args: check

    - name: Create release on GitHub
      uses: docker://goreleaser/goreleaser:latest
      with:
        args: release
      env:
        GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

注意:此版本为 最终版本。Get service dependencies 步骤是后续添加了,初始版本 没有这个步骤,具体原因可见下面的问题描述。

这个 workflow 中我们定义了只有在创建新的 tag 时(tag 首字母为 v)才触发任务,然后只定义了一个 release 的 Job。

上面我们定义的 Job 任务中先获取项目代码,然后使用 go get 命令获取 Go 工程的依赖包,然后使用 GoReleaser 官方 Docker 镜像来构建任务。当使用 docker 容器的时候,可以定义容器的args和entrypoint,我们这里分别使用args定义了check和release两个参数。

另外还指定了 GoReleaser 所需的 GITHUB_TOKEN 这个环境变量,这样可以在 GitHub 上来发布我们的应用版本,不过需要注意的是,secrets.GITHUB_TOKEN 这个变量的值是由 Actions 平台自动注入的,不需要我们单独手动去设置里添加了,很方便。

然后我们创建一个新的 tag 并推送到远程仓库中去:

$ git tag v0.0.1
$ git push origin --tags
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 536 bytes | 536.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0        
To https://github.com/ThreeTenth/GitHub-Discussions-to-Blog.git
 * [new tag]         v0.0.1 -> v0.0.1

如果一切正常就会立刻触发任务构建,Job 任务构建完成后会在 GitHub 上面创建一个新的版本,其中包含由 GoReleaser 工具自动生成的应用包和 Changelog

Release v0 0 1 · ThreeTenth_GitHub-Discussions-to-Blog - github com

以上,就是打包并发布 Goalng 程序的全过程,可以在 这里 查看工作过程,以下讲一下在这个过程中遇到的麻烦。

问题

GitHub Action 有一个很好的功能,就是他会保存历史执行记录,你可以在 Actions 这页看到这个项目过去提交失败的记录。

这是 第一次 提交失败的记录,当时错误的创建了(意外)一个 branch 分支 v0.0.1,导致这个 workflow 被触发了,我们可以看到他的错误提示:

  ⨯ release failed after 0s                  error=git doesn't contain any tags. Either add a tag or use --snapshot

可以在 这里 查看当时的 workflow 代码。

这是因为当前仓库没有任何 tag 可用,所以构建失败了。这是第一次错误,于是删除 branch,创建 tag,就有了 第二次 错误。

  ⨯ release failed after 0s                  error=failed to build for linux_arm64: exit status 1: go: github.com/excing/goflag@v1.0.1: missing go.sum entry; to add it:
	go mod download github.com/excing/goflag
go: github.com/excing/goflag@v1.0.1: missing go.sum entry; to add it:
	go mod download github.com/excing/goflag

提示编译失败,丢失 go.sum,需要添加一个依赖包 goflag

在项目中,go.sum 作为自动生成的文件,我经常把他写入 .gitignore 文件里,所以远程仓库没有这个文件,而我又不想上传这个文件,于是在 wordflow 里添加了以下步骤代码:

解决方法:

    - name: Get service dependencies
      working-directory: ./
      run:  |
        go get -v -u -d ./...
        if [ -f Gopkg.toml ]; then
            curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
            dep ensure
        fi

这里要提示一下,workflow 的初始版本里,是没有这个步骤的,初始版本代码:go.yml

Get service dependencies 步骤的作用前面已经讲过了,是获取 Golang 工程的依赖包,所以我添加了这段代码。为了测试这个代码是否有效,于是有了 第三次 错误。

为了节省时间,我修改了 workflow 的触发条件,使之在 main 分支发生变化时也能被触发,这样我就不用创建分节去测试代码了,可以在 这里 看到原始文件:

  ⨯ release failed after 0s                  error=git tag v0.0.1 was not made against commit 7acedebd53edea27e8dcb958309f595f2ad5cd0e

提示 commit 7acede 没有指向 v0.0.1 仓库,这是因为 GoReleaser 仅会在 tags 发生改变时执行打包操作,所以当我们的提交发生了 main 分支上时,就会出现以上错误。

解决办法:

删除推送到 main 分支的触发条件,重新创建分支即可,便是最开始的那个 workflow 和操作过程。

以上就是这次自动化构建过程中踩到的几个坑,如果你也遇到过类似或其他的问题,欢迎在下面评论,谢谢。

TOP
前往 GitHub Discussion 评论