DEV Community

Wen Ping
Wen Ping

Posted on Originally published at anguskit.com

导入 GitHub Actions 之后:事件、密钥和 Runner 还要对一遍

这篇讲把 GitHub Actions 的 workflow 贴进 导入 GitHub Actions、点 转换 之后,对话框里还没保存的 YAML 和贴进去的 workflow 差在哪里。看完你可以对照 未映射(需人工改) 和 注意 两份清单,改完触发事件、密钥和运行器(Runner,真正执行任务的机器)再创建流水线;REPO_TOKEN 这类密钥要另外建成凭证,导入不会替你创建。下文把转换出来、还没保存的那份 YAML 称为初稿,贴进去的 workflow 称为原文件。

先登录 AngusGit。流水线在团队版和企业版中提供,社区版没有 CI/CD 菜单。侧栏进入 CI/CD → 流水线,点 新建流水线,选 导入 GitHub Actions。密钥要自己建:打开 CI/CD → 配置,切到 凭证,点 新建凭证。名称 填 workflow 里的名字,例如 REPO_TOKEN,创建后不能改。类型 选 凭证文本。可见性 选 指定仓库,在 绑定仓库 里选上这个仓库。值 粘贴令牌,保存后不能再看明文。本文示例转换后是 runner.mode: NATIVE、标签 ubuntu-latest。还没有这种运行器时,侧栏进入 CI/CD → 运行器,点 新增 Runner,生成令牌(1 小时内有效,只显示一次),页签选 Zip 安装,标签填 ubuntu-latest,不要带 docker,否则会变成容器模式,接不到这份任务。把命令复制到构建机执行,列表里变成 空闲 后再创建流水线。

.github/workflows/ 下的文件不会在 AngusGit 上运行,所以必须走导入。对话框说明是:「子集映射为 AngusCICD YAML。Marketplace Action、托管 runs-on 镜像不会自动可用,请看未映射清单。」流水线在团队版和企业版中提供;社区版没有 CI/CD 菜单。

导入 GitHub Actions 之后要核对的四件事

1. 先导入,拿到初稿

  1. 打开导入对话框 进入 CI/CD → 流水线,点 新建流水线,选 导入 GitHub Actions。菜单项下面有一行小字:「部分语法自动转换,导入后请校验」。
  2. 粘贴 workflow 并转换 默认页签是 粘贴 YAML(旁边是 扫描仓库),输入框的标签是 GitHub Actions workflow,提示是「粘贴 .github/workflows/.yml 内容」。把下面这份贴进去,点 *转换**。
  3. 读清单,再决定是否创建 转换结果出现在输入框下面,从上到下依次是两份清单、流水线名称,最后是 YAML。从流水线列表打开时,右下角按钮是 创建流水线;从空白创建页打开时,同一位置则是 填入编辑器。如果清单还没核对完,点 取消 即可,仓库里不会留下流水线。

示例 workflow 如下:

name: CI
on:
  push:
    branches: [main]
  pull_request:
    types: [opened, synchronize]
jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 20
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: "21"
      - name: Build
        run: mvn -B verify
      - name: Publish
        if: github.ref == 'refs/heads/main'
        run: ./publish.sh
        env:
          REPO_TOKEN: ${{ secrets.REPO_TOKEN }}
Enter fullscreen mode Exit fullscreen mode

转换完成后的清单:未映射三条、注意四条,流水线名称是 CI

转换完成后,对话框中间会滚到两份清单;标题和右下角的 取消、创建流水线 仍在。未映射清单列出:

  • on.pull_request.types
  • jobs.build.steps[2].uses=actions/setup-java@v4(Marketplace / 远程 Action 不会拉取)
  • jobs.build.timeout-minutes(Job 级超时未建模,未写入 Step)

注意清单列出:

  • jobs.build.runs-on 映射为 NATIVE;不会拉取 GitHub-hosted 镜像(ubuntu-latest 等)
  • 已跳过 actions/checkout@v4:AngusGit 会检出工作区
  • github.ref → ref(值为分支名,不是 refs/heads/...)
  • secrets.X → env.X,并写入 Job secrets 名单;须在仓库凭证中同名存在

编辑器里转换后的初稿是:

version: '1'
name: CI
triggers:
- 'on': push
  branches:
  - main
- 'on': pull_request
pipeline:
  build:
    runner:
      mode: NATIVE
      labels:
      - ubuntu-latest
    steps:
    - name: Build
      run: mvn -B verify
    - name: Publish
      if: ref == 'refs/heads/main'
      env:
        REPO_TOKEN: ${{ env.REPO_TOKEN }}
      run: ./publish.sh
    secrets:
    - REPO_TOKEN
Enter fullscreen mode Exit fullscreen mode

名称自动填了 CI;'on' 带引号,是为了避开 YAML 里 on 会被当成布尔值。这是转换结果,保存前按下面四节改完再创建。

2. 触发事件有没有变

GitHub Actions 转换后的初稿 需要你做什么
push 加 branches: [main] on: push,并且保留了 branches: [main] 这一条不用改
pull_request 的 types 触发器只有 on: pull_request,没有 branches types 进了未映射。这份示例的 pull_request 下面没有写 branches,所以转换后的初稿也不会限制目标分支
pull_request_target 会变成 on: pull_request 未映射写「on.pull_request_target → pull_request(权限模型不同)」。这份示例没有
push 下的 tags 额外一条 on: tag 过滤条件未映射,未映射写「on.push.tags 过滤条件未映射(仅保留 tag 触发)」
release 变成 on: tag 有 types 时未映射写「on.release.types 未映射」。这份示例没有
workflow_dispatch on: workflow_dispatch,输入参数会保留 这份示例没有
schedule 加 cron 写成 on: schedule,并带上原来的 cron cron 会被登记,大约每 60 秒刷新一次。这份示例没有定时,转换后的初稿里也就没有

on: push 只响应 git push,在拉取请求页点合并不会因此再触发一次 push。因此,main 只能通过拉取请求合并时,合并前的检查要靠 pull_request。

3. secrets 有没有建成凭证

${{ secrets.REPO_TOKEN }} 被改成了 ${{ env.REPO_TOKEN }},名字写在 Job 的 secrets 下面,不是 credentials。运行时会按这个名字找凭证;找不到、对这个仓库不可见或者已过期,Job 就会失败,并提示 Credential not visible or expired。

导入不会创建凭证。要让发布步骤能读到令牌,按开头在 CI/CD → 配置 → 凭证 新建一条,名称必须是 REPO_TOKEN,类型选 凭证文本,可见性选 指定仓库。不要把令牌写进仓库文件。

GITHUB_TOKEN 是 GitHub 自动提供的,AngusGit 没有同名内置凭证,用到它的步骤要改成你自己的凭证,或者删掉。

4. runs-on 和 Marketplace Action 去哪了

ubuntu-latest 没有变成一台托管机器。 转换后的初稿是 runner.mode: NATIVE(直接在运行器机器上跑),标签是 ubuntu-latest,意思是在带这个标签的运行器上直接执行。没有这种运行器,Job 会一直排队;按开头用 Zip 安装 接一台,标签填 ubuntu-latest。注意里写了不会拉取 GitHub-hosted 镜像。写了 container 的 Job 才会变成 DOCKER(在镜像容器里跑),镜像用 container 里的名字。这份示例没有 container。

actions/setup-java@v4 被删掉了。 未映射原文是 jobs.build.steps[2].uses=actions/setup-java@v4(Marketplace / 远程 Action 不会拉取),所以 JDK 和 Maven 不会被装上。

actions/checkout@v4 被跳过。 注意原文是「已跳过 actions/checkout@v4:AngusGit 会检出工作区」,不用补这个步骤。检出是浅克隆,深度 1,只有触发这次运行的那一个提交,不带历史和标签,也不能在 workflow 里关掉。

Job 上的 timeout-minutes: 20 没有变成 1200 秒。 未映射写「Job 级超时未建模,未写入 Step」。超时要写在步骤上:步骤里的 timeout-minutes 会乘以 60,或者直接写 timeout,单位是秒。

按这些差别,保存前可以改成下面这样。镜像换成平台上的 repo.anguskit.com/docker-public/angus-ci-maven:21,里面有 JDK 21 和 Maven。这是改完后的写法,不是导入器直接给出的初稿:

version: "1"
name: CI
triggers:
  - "on": push
    branches: [main]
  - "on": pull_request
    branches: [main]
pipeline:
  build:
    runner:
      mode: DOCKER
      image: repo.anguskit.com/docker-public/angus-ci-maven:21
      labels: ["linux", "docker"]
    steps:
      - name: Build
        run: mvn -B verify
        timeout: 1200
  publish:
    needs: [build]
    if: event == 'push' && branch == 'main'
    secrets: ["REPO_TOKEN"]
    runner:
      mode: DOCKER
      image: repo.anguskit.com/docker-public/angus-ci-maven:21
      labels: ["linux", "docker"]
    steps:
      - name: Publish
        run: ./publish.sh
Enter fullscreen mode Exit fullscreen mode

和转换后的初稿比,改了这几处:

  • pull_request 补上 branches: [main]。 原文件只写了 types,转换后的初稿因此不限制目标分支。
  • 运行方式改成容器,标签改成 linux 和 docker。 不再要求一台贴着 ubuntu-latest 的宿主机。内网拉不到这个镜像时,换成你们自己的内网镜像名。
  • 20 分钟写到了 Build 步骤的 timeout: 1200。 这是手改的,导入不会替 Job 级超时做这个换算。
  • 发布拆成单独的 Job,条件写在 Job 上。 Job 的 if 能读到 branch、ref、commitSha、event。ref 和 branch 都是分支名,例如 main,不是 refs/heads/main。转换后的初稿把条件留在步骤上,写成 ref == 'refs/heads/main'。步骤上的 if 只有环境变量和成功/失败状态,读不到 ref。
  • secrets 仍是 REPO_TOKEN。 两个 Job 不共享工作目录。publish.sh 不能假设 build 留下了 target/。

5. 脚本里还要改的细节

检出只有一个提交。 日志里会有 clone=shallow depth=1,所以 git describe --tags、按历史生成变更日志都会缺数据。版本号改成从项目文件读,或者用 workflow_dispatch 的输入传进来。

github.ref 被改成了 ref,值是分支名。 注意原文:「github.ref → ref(值为分支名,不是 refs/heads/...)」。github.sha 会变成 commitSha,github.event_name 会变成 event,github.ref_name 会变成 branch。还残留别的 github. 时,注意会写「仍含 github.* 上下文,运行时不会注入 GitHub 对象」。脚本里可以直接用的环境变量是 GIT_REPO_URL、GIT_BRANCH、GIT_COMMIT_SHA。

你看到的 原因 怎么处理
Job 一直排队 没有运行器带 ubuntu-latest,而且模式是 NATIVE 改成容器运行,标签改成运行器真正有的,例如 linux、docker
java: command not found setup-java 在未映射里,没有被安装 换用自带 JDK 的镜像
Credential not visible or expired secrets 里有 REPO_TOKEN,凭证库里没有 按第 3 节建同名凭证
发布步骤被跳过,或者不该发布时也跑了 步骤 if 读不到 ref,右边还是 refs/heads/main 拆成单独 Job,条件写成 branch == 'main'
git describe 报找不到标签 浅克隆深度是 1 改成不依赖历史的写法
非 main 的拉取请求也触发了 转换后的初稿的 pull_request 没有 branches 补上 branches: [main]

常见问题

一个仓库有好几个 workflow 文件,怎么办?

每个文件单独导入一次,各自成为一条流水线。确认能跑之后,再把 YAML 放到 .anguscicd/,例如 .anguscicd/ci.yaml。只转换、不点创建,仓库里不会出现这条流水线。

.github/workflows/ 要不要删?

AngusGit 不会执行这个目录,留着不影响,等新流水线稳定后再清理。

自己写的复合 Action 能转吗?

uses: ./自己的目录 会保留为本地复合 Action;actions/setup-java 这种远程地址不会拉取,未映射里能看到,要把里面的命令展开成普通 run。

定时任务会不会运行?

会,schedule 里的 cron 会写进 on: schedule。这份示例没有定时,所以转换后的初稿里没有,不要把它理解成「转了也不会跑」。

小结

第 1 节贴进 导入 GitHub Actions 之后,转换后的初稿名叫 CI:push 保留了 branches: [main],pull_request 丢掉了 types,也没有分支限制;ubuntu-latest 变成 NATIVE 加同名标签;setup-java 和 Job 级 20 分钟超时在未映射里,checkout 被跳过;secrets.REPO_TOKEN 写进 Job 的 secrets,凭证要另外建;步骤上的 if: ref == 'refs/heads/main' 不能当成「只在 main 发布」。核对完再创建,不要把未改的初稿直接保存。

结论: 导入 GitHub Actions 得到的是一份还要手改的初稿。保存前要补上 pull_request 的分支、把 NATIVE / ubuntu-latest 换成自带 JDK 的容器运行器、把 Job 超时改到步骤上,并把发布条件改成 Job 级的 branch == 'main'。REPO_TOKEN 要在凭证里建同名项,导入不会替你创建。

参考文章

Top comments (0)