Linuzb' 的博客

记录学习点滴

06 May 2024

Github Action 简明教程

前言

本文的目的是介绍一种自动化的构建、测试、部署流程。

我们在开发软件时,常常需要构建环境、编译、测试以及部署,这些工作都是简单重复的工作,一旦我们的软件及环境复杂,这些工作就会变成一个重复且枯燥的过程。例如,当我们使用了 Docker 之后,我们构建环境就变成了一个 docker build 的过程。每当我们对环境有所修改,我们都需要重新 docker build 一次。每当我们修改一次代码,都需要忍受长时间的编译和测试。 这些工作都有标准的命令,我们是否可以写一个脚本,每当我们对代码进行修改,就可以自动执行以上工作呢? 当然可以,不过 Github Action 就是这么一个平台,通过 Github Action 我们可以自定义修改代码之后的工作流程(构建镜像、编译、测试和部署等)。

感兴趣的可以搜索下 DevOps 和 CI/CD(持续集成和持续部署)。这是一种软件开发理念,这里我们不做过多介绍,接下来的内容是 CI/CD 的一种实现。

这里看一下 Github Action官方定义

GitHub Actions 是一种持续集成和持续交付 (CI/CD) 平台,可用于自动执行生成、测试和部署管道。 您可以创建工作流程来构建和测试存储库的每个拉取请求,或将合并的拉取请求部署到生产环境。

Github Action 的组件

我们可以配置 Github Action workflow(工作流),当仓库中发生特定的事件时可以触发该工作流。如下图所示,下图即为一个工作流,一个工作流包含多个作业,这些作业可以并行可以串行。每个作业中运行了我们定义的脚本(例如docker build、编译、测试等)。

workflow

GitHub Actions 主要有以下几个概念

  • Workflows:工作流,可以添加到存储库中的自动化过程。工作流由一个或多个作业组成,可以由事件调度或触发。
  • Event:事件,触发工作流的特定动作。例如,向存储库提交 pr 或 pull 请求。
  • Jobs:作业,在同一跑步器上执行的一组步骤。默认情况下,具有多个作业的工作流将并行运行这些作业。
  • Steps:步骤,可以在作业中运行命令的单个任务。步骤可以是操作,也可以是 shell 命令。作业中的每个步骤都在同一个运行程序上执行,从而允许该作业中的操作彼此共享数据。
  • Actions:操作是独立的命令,它们被组合成创建作业的步骤。操作是工作流中最小的可移植构建块。你可以创建自己的动作,或者使用 GitHub 社区创建的动作。
  • Runners:运行器,安装了 GitHub Actions 运行器应用程序的服务器。。Github 托管的运行器基于 Ubuntu Linux、Microsoft Windows 和 macOS,工作流中的每个作业都在一个新的虚拟环境中运行。

快速入门

本文是一个入门教程,仅起到抛砖引玉的作用,详细概念介绍和使用方法以可见参考文档或者自行搜索。

这里介绍一些例子快速上手。

自动构建 docker 镜像并推送到 dockerhub

准备

  • 注册 Dockerhub(或者其他镜像中心)
  • Dockerhub 的用户名密码添加到 github action secret中。这一步的操作是将用户名密码放到一个 github action 可以读取的配置中,这个配置以 secret 形式保存,仅 github action可见。
  • 在 github 仓库中编写 Dockerfile
  • 添加 Actions 配置文件,这个文件定义了如何使用以上的 Dockerfile 构建镜像

Dockerfile

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
ARG REGISTRY=quay.io
ARG OWNER=jupyter
ARG BASE_CONTAINER=$REGISTRY/$OWNER/scipy-notebook
FROM $BASE_CONTAINER

LABEL maintainer="Jupyter Project <jupyter@googlegroups.com>"

# Fix: https://github.com/hadolint/hadolint/wiki/DL4006
# Fix: https://github.com/koalaman/shellcheck/wiki/SC3014
SHELL ["/bin/bash", "-o", "pipefail", "-c"]

USER root

RUN apt-get update --yes \
    && apt-get install --yes --no-install-recommends \
    wget \
    curl \
    vim \
    git \
    && apt-get clean && rm -rf /var/lib/apt/lists/*

# Installation de Code Server et server-proxy/vscode-proxy pour intégrer Code dans JupyterLab
# Install VSCode extensions
ENV CODE_VERSION=4.22.1
RUN curl -fOL https://github.com/coder/code-server/releases/download/v$CODE_VERSION/code-server_${CODE_VERSION}_amd64.deb && \
    dpkg -i code-server_${CODE_VERSION}_amd64.deb && \
    rm -f code-server_${CODE_VERSION}_amd64.deb && \
    EXT_LIST="ms-python.python ms-python.debugpy zhuangtongfa.material-theme" && \
    for EXT in $EXT_LIST; do code-server --install-extension $EXT; done

USER ${NB_UID}

# https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/docker-specialized.html#dockerfiles
ENV NVIDIA_VISIBLE_DEVICES all
ENV NVIDIA_DRIVER_CAPABILITIES compute,utility

如何编写 Dockerfile 可以参考 docker 教程

github action 配置

github action 的配置都统一放在 .github/workflows/ 目录下,该目录下可以放多个 workflow 配置。

例如以下 build docker 的配置 .github/workflows/build-docker.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
name: build_docker

on:
  # 提交代码时触发
  push:
    # 触发条件,以下为与的关系
    # 1. 向 main 分支或者 feat/ 开头的分支提交代码
    # 2. 仅当 src/docker/ 目录下的文件有变化
    branches:
    - main
    - feat/**
    paths:
    - 'src/docker/**'
  # 手动触发
  workflow_dispatch:

env:
  # 定义环境变量,在下面可以这样用 ${{ env.TARGET_NAMESPACE }}
  TARGET_NAMESPACE: linuzb

jobs:
  build_docker:
    name: Build docker
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v2
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
      # 登录到 dockerhub
      # 需要提前将 DOCKERHUB_USERNAME 和 DOCKERHUB_TOKEN 放到 github action secret 中
      - name: Login to DockerHub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      # 获取 git commit hash 值或者 tag 值,并存储到环境变量 APP_VERSION 中
      - name: Generate App Version
        run: echo APP_VERSION=`git describe --tags --always` >> $GITHUB_ENV

      - name: Build and push
        id: docker_build
        uses: docker/build-push-action@v4
        with:
          # 切换上下文到 Dockerfile 所在目录
          context: src/docker
          # 指定 Dockerfile 目录,前面 context 已经制定了dockerfile所在目录,这里可以忽略
          # file: src/docker/Dockerfile
          push: true
          platforms: linux/amd64,linux/arm64
          tags: |
            ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.TARGET_NAMESPACE }}:${{ github.ref_name }}
            ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.TARGET_NAMESPACE }}:latest            

推荐

参考

Next time, we'll talk about "What Tiger King can teach us about x86 Assembly"