Next.js logomarkGitHub Actions 的 CI/CD

2023年5月1日

Openai logomark
Hamster1963

Github Actions与CI/CD

GitHub Actions是GitHub提供的一种自动化工具,可以帮助您在代码仓库中自动执行任务,如构建、测试和部署。CI/CD(持续集成/持续部署)是一种自动化软件开发实践,可以帮助您更快地交付高质量的软件。在本文中,我们将介绍如何使用GitHub Actions为Go项目实现简易CI/CD。

实现目标

Untitled

将Actions主要分为三个部分

  1. 在代码提交后进行编译检查,检查是否存在代码错误。
  2. 在进行git tag操作后,针对tag进行docker镜像的构建与推送。
  3. 达到版本号发布时,自动构建多平台可执行二进制文件。

前置准备

为Actions开放仓库权限

在仓库主页,选中Settings→Actions→General→Workflow permissions,将权限设置为Read and write permisssions。

Untitled

获取Docker相关信息

将信息储存在Actions secrets and variables中,分别设置Docker用户名,token与仓库名称。

获取 Docker token 的步骤如下:

  1. 登录到 Docker Hub 帐户。
  2. 点击右上角的头像,选择“Account Settings”。
  3. 在左侧菜单中选择“Security”。
  4. 滚动到“Access Tokens”部分,然后单击“New Access Token”按钮。
  5. 输入访问令牌的描述,选择令牌的有效期,并选择要授予令牌的权限。
  6. 单击“Create”按钮以生成令牌。
  7. 复制生成的令牌并保存在安全的地方。

仓库名称则为 用户名/仓库名

进行secrets的设置

Settings→Secrets and variables中点击New repository secret进行新增。

  1. DOCKER_USERNAME
  2. DOCKER_ACCESS_TOKEN
  3. DOCKER_IMAGE_NAME

Untitled

设置Actions

点击仓库内Actions模块,点击New workflow进行工作流的新增。

代码编译检查工作流

将会在检测到push或pull_request后进行代码编译检查。

# This workflow will build a golang project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go

name: 代码编译测试

on:
  push:
    branches: ['main']
  pull_request:
    branches: ['main']

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Set up Go
        uses: actions/setup-go@v3
        with:
          go-version: 1.19

      - name: Build
        run: |
          go build -v ./...
          pwd

编译构建并推送Docker镜像

此工作流只会在仓库新增tag时进行。

git tag v0.0.1
git push --tags

工作流分为以下几个步骤

  1. 获取tag作为版本号
  2. 根据Dockerfile进行Docker镜像的构建
  3. 针对构建完成镜像进行tag打版本号
  4. 将镜像推送至Dockerhub
name: Build and push Docker image

on:
  push:
    tags:
      - 'v*'

env:
  IMAGE_NAME: ${{ secrets.DOCKER_IMAGE_NAME }}

jobs:
  build-and-push:
    runs-on: ubuntu-latest

    steps:
      - name: Get version
        id: get_version
        run: echo "VERSION=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT

      - name: Checkout code
        uses: actions/checkout@v3

      - name: Login to Dockerhub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_ACCESS_TOKEN }}

      - name: Build Docker image
        run: docker build -t $IMAGE_NAME:${{ github.sha }} .

      - name: Tag Docker image
        run: docker tag $IMAGE_NAME:${{ github.sha }} $IMAGE_NAME:${{ steps.get_version.outputs.VERSION }}

      - name: Tag Docker image as latest
        run: docker tag $IMAGE_NAME:${{ github.sha }} $IMAGE_NAME:latest

      - name: Push Docker image
        run: |
          docker push $IMAGE_NAME:${{ steps.get_version.outputs.VERSION }}
          docker push $IMAGE_NAME:latest

这时我们需要针对项目进行Dockerfile的编写,一下是一个针对Goframe项目的示例。

  1. 设置golang构建环境,有许多版本可以选择,可以参考https://hub.docker.com/_/golang,这里选择golang:1.20-buster。
  2. 拷贝代码至构建环境,进行构建,在这里将编译完成后将二进制文件命名为service,构建命令也可以指定系统与架构,在命令中加上GOOS=linux GOARCH=amd64
  3. 设置镜像环境,设置工作路径,为二进制文件添加权限并增加端口绑定。
  4. 设置入口命令。

至此一份Dockerfile就编写完成了。

FROM golang:1.20-buster AS builder

ARG VERSION=dev

WORKDIR /go/src/app
COPY . .
RUN CGO_ENABLED=0 go build -o service -ldflags=-X=main.version=${VERSION} main.go

FROM loads/alpine:3.8

LABEL maintainer="Hamster <liaolaixin@gmail.com>"

###############################################################################
#                                INSTALLATION
###############################################################################

# 设置固定的项目路径
ENV WORKDIR /app/main
COPY --from=builder /go/src/app/service $WORKDIR/service
# 添加应用可执行文件,并设置执行权限
RUN chmod +x $WORKDIR/service

# 增加端口绑定
EXPOSE 10399

###############################################################################
#                                   START
###############################################################################
WORKDIR $WORKDIR
CMD ["./service"]

新增后通过git tag测试工作流,检查Dockerhub是否有最新构建镜像。

Untitled

Untitled

编译多平台二进制文件

设置为只在新增release时进行构建,可以设置需要的系统架构或排除的,十分简单易用。

name: build-go-binary

on:
  release:
    types: [created] # 表示在创建新的 Release 时触发

jobs:
  build-go-binary:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        goos: [linux, windows, darwin] # 需要打包的系统
        goarch: [amd64, arm64] # 需要打包的架构
        exclude: # 排除某些平台和架构
          - goarch: arm64
            goos: windows
    steps:
      - uses: actions/checkout@v3
      - uses: wangyoucao577/go-release-action@v1
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }} # 一个默认的变量,用来实现往 Release 中添加文件
          goos: ${{ matrix.goos }}
          goarch: ${{ matrix.goarch }}
          goversion: 1.18 # 可以指定编译使用的 Golang 版本
          binary_name: 'push_go' # 可以指定二进制文件的名称
          pre_command: export CGO_ENABLED=0 && export GODEBUG=http2client=0
          overwrite: true

在仓库中新增release并测试,等待编译完成后即可在release中查看不同系统架构的二进制文件。

Untitled

Untitled

消息通知

可针对Actions的进度进行消息通知,在Settings→Webhooks设置推送目标URL,搭配自建的消息推送即可实现在手机上获取Actions进度流程。

IMG_EBE9B7CDBE3C-1.jpeg