几年前开始,为了将自己的杂七杂八的代码托管起来,自己建了代码私服,当时综合调研了下选择了比较轻量的Gitea,一是防止github、gitee、coding等产品托管的代码审查,二是为了应对墙,不然推送代码真吃力,Gitea1.19 版本之前不支持内置的CI/CD解决方案,所以是我自己使用的Gitea+Drone实现流程自动化。

前段时间 Gitea 发布了1.22.0版本,Gitea Actions成为了内置的CI/CD解决方案已经有一段时间了,所以打算慢慢迁移到Gitea Actions,这样可以统一维护,再加上Drone被收购后产品路线也发生了一些变化,所以打算迁了。

尽管Gitea Actions旨在与GitHub Actions兼容,但它们之间存在一些差异,但是Gitea Actions目前没有什么详情的语法文档,所以本文主要通过学习Github Actions,差异可以根据Gitea 文档进行微调,一下掌握两个平台的使用,当然也可以举一反三应用到其他CI/CD平台,只是编写yml语法不同,原理都是大差不差。

概念

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

GitHub Actions 不仅仅是 DevOps,还允许您在存储库中发生其他事件时运行工作流程。 例如,您可以运行工作流程,以便在有人在您的存储库中创建新问题时自动添加相应的标签。

GitHub 提供 Linux、Windows 和 macOS 虚拟机来运行工作流程,或者您可以在自己的数据中心或云基础架构中托管自己的自托管运行器。

Gitea 也是如此,只是Gitea Runner需要自己注册,可以根据自己手里的机器直接注册。

大白话讲:就是当你的代码仓库发送某种变化时,你要触发某种工作流,然后进行编排自动执行。举个栗子:当你推送代码到仓库后,需要验证多个平台是否都能正常编译运行,都通过之后就发布到内部测试环境供测试人员进行测试,如果没有通过就不执行发布流程等等,这样就可以从传统开发本地打包再手动部署服务器上,然后启停服务,再验证服务是否正常这么复杂的流程。

准备环境

可以直接采用公有云Github创建一个公开仓库进行学习,当然你也可以按照 Gitea 官方安装手册 自己部署示例进行练习。

github 准备一个空仓库,新建 .github/workflows/ci-demo.yml 文件,gitea则新建 .gitea/workflows/ci-demo.yml

编写一个简单的配置文件,示例如下:

name: GitHub Actions Demo
run-name: ${{ github.actor }} is testing out GitHub Actions 🚀
on: [push]
jobs:
  Explore-GitHub-Actions:
    runs-on: ubuntu-latest
    steps:
      - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
      - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
      - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
      - name: Check out repository code
        uses: actions/checkout@v4
      - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
      - run: echo "🖥️ The workflow is now ready to test your code on the runner."
      - name: List files in the repository
        run: |
          ls ${{ github.workspace }}
      - run: echo "🍏 This job's status is ${{ job.status }}."

上方是一个示例demo,github actions默认是自动开启,使用gitea actions则需要按照 手动启用仓库actions ,当你推送文件到仓库时候,就会自动执行了。

github actions运行截图:仓库导航 -> Acitons -> 左侧导航All workflows -> 查看Explore-GitHub-Actions -> 点击查看详情

零基础入门 GitHub/Gitea Actions 流程自动化

gitea actions运行截图:仓库导航 -> Acitons -> 左侧导航所有工作流 -> 点击查看详情

零基础入门 GitHub/Gitea Actions 流程自动化

以上步骤运行成功,说明你的环境没有任何问题,可以继续往下学习了。

常用组件名词解释

Workflows(工作流程)

工作流程是一个可配置的自动化过程,它将运行一个或多个作业。 工作流程由签入到存储库的 YAML 文件定义,并在存储库中的事件触发时运行,也可以手动触发,或按定义的时间表触发。

工作流程在存储库的 【github】.github/workflows 或者 【gitea】 .gitea/workflows 目录中定义,存储库可以有多个工作流程,每个工作流程都可以执行不同的任务集。 例如,您可以有一个工作流程来构建和测试拉取请求,另一个工作流程用于在每次创建发布时部署应用程序,还有一个工作流程在每次有人打开新议题时添加标签。

Events(事件)

事件是存储库中触发工作流程运行的特定活动。 例如,当有人创建拉取请求、打开议题或将提交推送到存储库时,活动可能源自 GitHub。此外,还可以通过回调api或者手动方式触发工作流按计划运行。

Jobs(任务)

作业是工作流中在同一运行器上执行的一组步骤。 每个步骤要么是一个将要执行的 shell 脚本,要么是一个将要运行的动作。 步骤按顺序执行,并且相互依赖。 由于每个步骤都在同一运行器上执行,因此您可以将数据从一个步骤共享到另一个步骤。 例如,可以有一个生成应用程序的步骤,后跟一个测试已生成应用程序的步骤。

您可以配置作业与其他作业的依赖关系;默认情况下,作业没有依赖关系,并且彼此并行运行。 当一个作业依赖于另一个作业时,它将等待从属作业完成,然后才能运行。 例如,对于没有依赖关系的不同体系结构,您可能有多个生成作业,以及一个依赖于这些作业的打包作业。 生成作业将并行运行,当它们全部成功完成后,打包作业将运行。

Steps(步骤)

步骤,某个任务下的多个步骤。步骤可以是操作,也可以是 shell 命令。作业中的每个步骤都在同一个运行程序上执行,从而允许该作业中的操作彼此共享数据。

Actions(操作)

操作是用于 GitHub Actions 平台的自定义应用程序,它执行复杂但经常重复的任务。 使用操作可帮助减少在工作流程文件中编写的重复代码量。 操作可以从 GitHub 拉取 git 存储库,为您的构建环境设置正确的工具链,或设置对云提供商的身份验证。

您可以编写自己的操作,也可以在 GitHub Marketplace 中找到要在工作流程中所有可以使用的操作。

Runners(运行器)

运行程序是触发工作流时运行工作流的服务器。 每个运行器一次可以运行一个作业。 GitHub 提供 Ubuntu Linux、Microsoft Windows 和 macOS 运行器来运行您的工作流程;每个工作流程运行都在新预配的全新虚拟机中执行。 GitHub 还提供 大型运行器(适用于大型配置)。如果需要其他操作系统或特定硬件配置,可托管自己的运行器。

了解工作流配置文件

我们拿前面的ci-demo.yml工作流程来说明一下:

name: GitHub Actions Demo # 可选 - 工作流程的名称,它将显示在 GitHub 存储库的“操作”选项卡中。如果省略此字段,则将使用工作流程文件的名称
run-name: ${{ github.actor }} is testing out GitHub Actions 🚀 # 工作流生成的工作流运行的名称,Gitea本文编写时暂时不支持
on: [push] # 指定此工作流的触发器。此示例使用 push 事件,因此每次有人将更改推送到存储库或合并拉取请求时都会触发工作流运行。这是由对每个分支的推送触发的;有关仅在推送到特定分支、路径或标签时运行的语法示例,请参阅“GitHub Actions 的工作流语法”。
jobs: # 工作流程中运行的所有作业job聚合在一起。
  Explore-GitHub-Actions: # 定义一个名为 Explore-GitHub-Actions 的作业job。下面则将定义作业的属性。
    runs-on: ubuntu-latest # 将作业配置为在最新版本的 ubuntu-latest 运行程序上运行。这意味着该作业将在 GitHub 托管的新虚拟机上执行。
    steps: # 作业中运行的所有操作聚合在一起。
      - run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event." # run 关键字告诉作业在运行器上执行命令。 下面也同样的。
      - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
      - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
      - name: Check out repository code # name关键字设置操作步骤的名称,界面上流程会展示出来
        uses: actions/checkout@v4  # uses 关键字指定此步骤将运行 actions/checkout 操作的 v4 。这是一个将存储库检出到运行器上的操作,允许您针对代码运行脚本或其他操作(例如构建和测试工具)。只要您的工作流程将使用存储库的代码,您就应该使用签出操作。
      - run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
      - run: echo "🖥️ The workflow is now ready to test your code on the runner."
      - name: List files in the repository
        run: | # 执行多行命令可以直接使用| 然后写多行命令
          ls ${{ github.workspace }}
      - run: echo "🍏 This job's status is ${{ job.status }}."
GitHub Actions 的工作流语法:https://docs.github.com/zh/actions/using-workflows/workflow-syntax-for-github-actions#run-name

知道每个步骤的写法,我们可以参考官方语法自己定义手写一个:有两个job,job2依赖job1,job1使用ubuntu,job2使用windows

name: test ci
run-name: test run name
on:
  push:
    branches:
      - master
jobs:
  job1:
    runs-on: ubuntu-latest
    steps:
      - name: 步骤1
        run: ls -lh
      - name: 步骤2
        run: |
          pwd
          date
      - name: 步骤3:检出代码
        uses: actions/checkout@v4
      - name: 步骤4
        run: |
          ls -lh
          date
  job2:
    needs: [job1]
    runs-on: windows-latest
    steps:
      - name: job2步骤1
        run: git version

表达式

更多介绍见官方链接:https://docs.github.com/zh/actions/learn-github-actions/expressions

使用表达式对工作流和操作中的表达式求值,当满足条件的时候才执行流程或者操作。您可以使用表达式程序化设置工作流程文件中的环境变量和访问上下文(环境变量和上下文后面会讲)。

使用语法:作为表达式的一部分,可使用 booleannullnumberstring 数据类型。

env:
  MY_ENV_VAR: ${{ <expression> }}
数据类型文本值
booleantruefalse
nullnull
numberJSON 支持的任何数字格式。
string无需将字符串括在 ${{}} 中。 但是,如果这样做,则必须在字符串两边使用单引号 (')。 若要使用文本单引号,请使用额外的单引号 ('') 转义文本单引号。 用双引号 (") 括起来会引发错误。

请注意,在条件中,假值(false0-0""''null)被强制转换为 false,且真值(true 和其他非假值)被强制转换为 true

示例:

env:
  myNull: ${{ null }}
  myBoolean: ${{ false }}
  myIntegerNumber: ${{ 711 }}
  myFloatNumber: ${{ -9.2 }}
  myHexNumber: ${{ 0xff }}
  myExponentialNumber: ${{ -2.99e-2 }}
  myString: Mona the Octocat
  myStringInBraces: ${{ 'It''s open source!' }}

运算符如下:

运算符说明
( )逻辑分组
[ ]索引
.属性取消引用
!Not
<小于
<=小于或等于
>大于
>=大于或等于
==等于
!=不等于
&&
丨丨

用于判断前面步骤都成功或者失败或者始终都要执行的写法:

steps:
  ...
  - name: 成功执行
    if: ${{ success() }}
  - name: 始终执行
    if: ${{ always() }}
  - name: 退出的时候执行
    if: ${{ cancelled() }}
  - name: 失败执行
    if: ${{ failure() }}

上下文

更多介绍见官方链接:https://docs.github.com/zh/actions/learn-github-actions/contexts

上下文是一种访问工作流运行、变量、运行器环境、作业及步骤相关信息的方式。 每个上下文都是一个包含属性的对象,属性可以是字符串或其他对象。

基本语法,可以使用表达式语法访问上下文:

${{ <context> }}
上下文名称类型说明
githubobject工作流程运行的相关信息。 有关更多信息,请参阅 github 上下文
envobject包含工作流、作业或步骤中设置的变量。 有关更多信息,请参阅 env 上下文
varsobject包含在存储库、组织或环境级别上设置的变量集。 有关更多信息,请参阅 vars 上下文
jobobject有关当前运行的作业的信息。 有关更多信息,请参阅 job 上下文
jobsobject仅适用于可重用工作流,包含可重用工作流中的作业输出。 有关更多信息,请参阅 jobs 上下文
stepsobject有关当前作业中已运行的步骤的信息。 有关更多信息,请参阅 steps 上下文
runnerobject有关运行当前作业的运行器的信息。 有关更多信息,请参阅 runner 上下文
secretsobject包含可用于工作流运行的机密的名称和值。 有关更多信息,请参阅 secrets 上下文
strategyobject有关当前作业的矩阵执行策略的信息。 有关更多信息,请参阅 strategy 上下文
matrixobject包含在工作流中定义的应用于当前作业的矩阵属性。 有关更多信息,请参阅 matrix 上下文
needsobject包含定义为当前作业依赖项的所有作业的输出。 有关更多信息,请参阅 needs 上下文
inputsobject包含可重用或手动触发的工作流的输入。 有关更多信息,请参阅 inputs 上下文

比如我们前面ci-demo.yml文件里面写的 ${{ runner.os }} 就是runner上下文,${{ github.ref }} 就是github上下文,在gitea中可以额外使用 ${{ gitea.ref }} 上下文

    ....
      - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
      - run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."

这里特别要强调一下secrets密钥上下文,为了一些隐私的账号信息不被泄漏,所以可以在actions设置界面添加密钥,然后直接在流程中引用,如下图:

零基础入门 GitHub/Gitea Actions 流程自动化

gitea创建密钥也是差不多的,如下图:

零基础入门 GitHub/Gitea Actions 流程自动化

通过上下文,可以获取运行中的任何信息拿来构建程序所用,比如判断操作系统版本,根据commitId打包镜像标签等等。

变量

更多请参考官方链接:https://docs.github.com/zh/actions/learn-github-actions/variables

GitHub 为每个 GitHub Actions 工作流运行设置默认变量。 你还可以设置自定义变量,以便在单个工作流或多个工作流中使用。

变量提供了一种存储和重用非敏感配置信息的方法。 可以将任何配置数据(如编译器标志、用户名或服务器名称)存储为变量。 变量在运行工作流的运行器计算机上插值。 在操作或工作流步骤中运行的命令可以创建、读取和修改变量。

变量和上面说的密钥最大的区别就是密钥在日志中会以*号脱敏,但是变量会直接呈现出来。

为单个工作流定义环境变量

若要设置单个工作流的自定义环境变量,可以在工作流文件中使用 env 键进行定义。 此方法设置的自定义变量的作用域仅限于在其中定义它的元素。 可以定义作用域如下的变量:

整个工作流,方法是在工作流文件的顶层使用 env。
工作流中的作业内容,方法是使用 jobs.<job_id>.env。
作业中的特定步骤,方法是使用 jobs.<job_id>.steps[*].env。

示例:

name: Greeting on variable day

on:
  workflow_dispatch

env:
  DAY_OF_WEEK: Monday

jobs:
  greeting_job:
    runs-on: ubuntu-latest
    env:
      Greeting: Hello
    steps:
      - name: "Say Hello Mona it's Monday"
        run: echo "$Greeting $First_Name. Today is $DAY_OF_WEEK!"
        env:
          First_Name: Mona

可以使用运行器环境变量或上下文访问 env 变量值。 上面的示例显示了要在 echo 命令中用作运行器环境变量的 3 个自定义变量:$DAY_OF_WEEK$Greeting$First_Name。 这些变量的值分别在工作流、作业和步骤级别设置和定义作用域。 这些变量的内插发生在运行器上。

工作流或引用操作 run 步骤中的命令由在运行器上使用的 shell 处理。 工作流其他部件中的指令由 GitHub Actions 处理,不会发送到运行器。 可以在 run 步骤中使用运行器环境变量或上下文,但在未发送到运行器的工作流部件中,必须使用上下文来访问变量值。

由于运行器环境变量插值是在将工作流作业发送到运行器计算机后完成的,因此必须对运行器上使用的 shell 使用适当的语法。 在此示例中,工作流指定 ubuntu-latest。 默认情况下,Linux 运行器使用 bash shell,因此你需要使用语法 $NAME。 Windows 运行器默认使用 PowerShell,因此您将使用语法 $env:NAME

为多个工作流定义配置变量

beta版本,以创建用于多个工作流的配置变量,并且可以在组织、存储库或环境级别定义它们。github免费版本只允许设置设置仓库级别的,组织需要付费,gitea是支持组织级别的。

例如,可以使用配置变量为传递给组织级别的生成工具的参数设置默认值,但随后允许存储库所有者根据具体情况重写这些参数。

定义配置变量时,它们在 vars 上下文中自动可用。

使用上下文访问变量值

可以使用 env 上下文来访问环境变量值,还可以使用 vars 上下文来访问配置变量值。

默认环境变量

GitHub 设置的默认环境变量可用于工作流程中的每个步骤。

由于默认环境变量由 GitHub 设置,并且未在工作流中进行定义,因此无法通过 env 上下文访问它们。 但是,大多数默认变量都有一个对应且名称类似的上下文属性。 例如,在工作流处理期间,可以使用 ${{ github.ref }} 上下文属性读取 GITHUB_REF 变量的值。

所有可用的值见链接,在gitea中,GITHUB_前缀改为GIEA_ 同样适用:https://docs.github.com/zh/actions/learn-github-actions/variables#default-environment-variables

适用工作流模版快速创建

入门工作流是可助你为存储库创建自己的 GitHub Actions 工作流的模板。 使用入门工作流时,你无需从空白工作流文件全新开始,由于部分工作已经为你完成,因此非常实用。

GitHub 为各种语言和工具提供入门工作流程。 在存储库中设置工作流程时,GitHub 会分析存储库中的代码,并根据存储库中的语言和框架推荐工作流程。

可以在创建actions直接选择模版如下图,快速进行学习借鉴别人是如果做的:

零基础入门 GitHub/Gitea Actions 流程自动化

点击这里可以看到常见的工作流:https://docs.github.com/zh/actions/guides#all-guides

Gitea/GitHub Actions的对比

虽然gitea官方会持续兼容github actions的所有功能,但是还需要时间,所以部分功能在gitea不可用或者有差异,请一定要注意。

见gitea官方链接:https://docs.gitea.com/zh-cn/usage/actions/comparison

总结

本人虽然接触github比较久,但是对于github actions没有深入了解过,画了个周末跟到官方文档实操了一下,也主要是想切到gitea actions上面来减少自己的私服维护成本,工作中是很少用公有云项目,企业级基本上都是首选gitlab+Jenkins的方案完成的,针对于开源项目或者是个人项目为了节省成本肯定还是选择“白嫖”了,现在devops平台基本上都提供,博主也用过阿里云的云效、coding的持续集成部署,gitee的Jenkins for gitee,最后选择自建私服还是因为基本上免费的都有构建时长或者对仓库公开的要求,用下来其实原理都差不多,主要是一个语法的熟悉,有些平台使用可视化编排,最终还是要了解熟悉底层原理,才能快速上手。

在大环境不好情况下,devops多多少少都要熟悉一点,这样可以减少运维沟通成本,通过本文你可以对github actions有个初步的认识,在对于不同语言构建项目的实际使用过程中过程肯定不大相同的,还需要在使用中不断持续学习,在ai以来的时代,你可以选择直接描述需求给AI直接给你写出配置文件

希望本文对你初识github actions/gitea actions的你有所帮助。

参考链接

github actions官方文档

github actions 工作流语法

知乎-如何优雅地使用 Github Actions?

gitea actions官方文档

巧用GitHub Action实现自动化部署Java项目

阮一峰博客-GitHub Actions 入门教程

10 个你该了解的 GitHub Actions 进阶技巧

Gitea Actions/Github Actions 构建 SpringBoot 多平台 Docker 镜像