2025-09-13
Git
00
请注意,本文编写于 172 天前,最后修改于 172 天前,其中某些信息可能已经过时。

目录

uses 的环境是 Docker 吗?
三种 Action 类型的深度解析
1. JavaScript Action (非 Docker 环境)
2. Docker Container Action (真正的 Docker 环境)
3. Composite Action (混合环境)
如何制作自己的 Action 环境?
方法一:制作 JavaScript Action (推荐用于大多数场景)
方法二:制作 Docker Container Action (需要环境一致性时)
关键注意事项和最佳实践

搞清楚 GitHub Actions 中 uses 的环境,以及如何制作自己的环境。

uses 的环境是 Docker 吗?

答案是:取决于 Action 的类型。

GitHub Actions 支持三种类型的 Action,它们的执行环境不同:

  1. JavaScript Action不是在 Docker 中运行。它直接在 GitHub 托管的运行器(Runner)虚拟机环境中执行。这是最常见、性能最好的类型。
  2. Docker Container Action是在 Docker 容器中运行。它会在运行器上启动一个全新的、隔离的 Docker 容器来执行 Action 的代码。
  3. Composite Action:是一种将多个步骤(包括 runuses)组合成一个可重用单元的方式。它本身不定义环境,其内部的每个步骤按其自己的方式执行(可能是 JavaScript、Docker 或 Shell 命令)。

三种 Action 类型的深度解析

1. JavaScript Action (非 Docker 环境)

  • 执行环境:直接共享运行器的操作系统和环境。
  • 优点
    • 速度快:无需启动容器,开销极小。
    • 访问方便:可以轻松缓存文件、访问先前步骤的工作目录。
  • 缺点
    • 环境依赖:依赖于运行器预装的环境,或者需要你自己用 run 步骤来安装依赖。
    • 污染风险:可能修改运行器的全局环境,影响后续步骤。

如何识别: 在 Action 的 action.yml 文件中,主要使用 runs.using: 'node16''node20'

yaml
# action.yml for a JavaScript Action name: 'Hello JavaScript' description: 'A simple JavaScript Action' runs: using: 'node20' # 关键标识:使用 nodejs main: 'dist/index.js' # 执行编译后的JS文件

2. Docker Container Action (真正的 Docker 环境)

  • 执行环境:在一个全新的、短暂的 Docker 容器中运行。
  • 优点
    • 环境一致性这是最大的优势。无论在哪里运行,都能获得完全一致的环境(特定的操作系统、预装的所有工具、库和版本)。实现了“构建一次,随处运行”。
    • 隔离性:不会污染主机运行器环境,非常安全。
    • 灵活性:可以基于任何 Docker 镜像(Ubuntu, Alpine, CentOS, 甚至包含特定工具链的定制镜像)。
  • 缺点
    • 速度慢:需要拉取镜像和启动容器,有额外开销。
    • 文件访问:需要将工作目录作为卷(volume)挂载到容器中才能访问代码。

如何识别: 在 Action 的 action.yml 文件中,使用 runs.using: 'docker' 并指定一个镜像。

yaml
# action.yml for a Docker Action name: 'Hello Docker' description: 'A simple Docker Action' runs: using: 'docker' # 关键标识:使用 docker image: 'Dockerfile' # 使用当前仓库的 Dockerfile 构建镜像 # 或者直接使用公共镜像 # image: 'docker://ubuntu:20.04'

3. Composite Action (混合环境)

  • 执行环境:它只是一个步骤的包装器,每个步骤按自己的类型在执行。
  • 如何识别:使用 runs.using: 'composite'
yaml
# action.yml for a Composite Action name: 'Setup Tools' description: 'Installs a bunch of tools' runs: using: 'composite' steps: - run: sudo apt-get update && sudo apt-get install -y jq shell: bash - run: npm install -g some-package shell: bash

如何制作自己的 Action 环境?

需要创建一个新的 GitHub 仓库来存放你的 Action 代码。核心是创建一个 action.yml (或 action.yaml) 文件来定义 Action 的元数据和行为。

方法一:制作 JavaScript Action (推荐用于大多数场景)

步骤

  1. 创建仓库:例如 my-cool-action
  2. 创建 action.yml
    yaml
    name: 'My Cool Action' description: 'Greets someone and logs their name' author: 'Your Name' # 定义输入参数 inputs: who-to-greet: description: 'The person to greet' required: true default: 'World' # 定义输出参数 outputs: time: description: 'The time we greeted you' # 定义运行方式 runs: using: 'node20' main: 'dist/index.js' # 指向打包后的文件
  3. 编写源码 (src/main.js):
    javascript
    const core = require('@actions/core'); const github = require('@actions/github'); function run() { try { // 获取输入参数 const nameToGreet = core.getInput('who-to-greet'); console.log(`Hello ${nameToGreet}!`); // 获取当前时间并设置为输出 const time = new Date().toTimeString(); core.setOutput('time', time); // 你也可以访问 GitHub 上下文 const actor = github.context.actor; console.log(`This workflow was triggered by ${actor}!`); } catch (error) { core.setFailed(error.message); } } run();
  4. 配置打包 (package.json):
    json
    { "name": "my-cool-action", "main": "dist/index.js", "scripts": { "build": "ncc build src/main.js -o dist --license licenses.txt" }, "dependencies": { "@actions/core": "^1.10.0", "@actions/github": "^5.1.1" }, "devDependencies": { "@vercel/ncc": "^0.36.1" } }
  5. 打包并提交:运行 npm run build,将生成的 dist/index.js 提交到仓库。

使用 Action

yaml
- name: Use my cool action uses: your-username/my-cool-action@v1 # 使用发布后的版本标签 with: who-to-greet: 'GitHub Actions'

方法二:制作 Docker Container Action (需要环境一致性时)

步骤

  1. 创建仓库:例如 my-python-linter-action
  2. 创建 action.yml
    yaml
    name: 'Python Linter' description: 'Runs a linter on Python code inside a custom container' inputs: python-version: description: 'Python version to use' required: false default: '3.9' runs: using: 'docker' image: 'Dockerfile' args: - ${{ inputs.python-version }}
  3. 创建 Dockerfile
    dockerfile
    # 使用一个官方基础镜像 FROM python:3.9-slim # 将整个仓库文件拷贝到容器内的 /action 目录 COPY . /action WORKDIR /action # 在容器构建时安装你的依赖 RUN pip install --no-cache-dir flake8 # 设置入口点,容器启动时执行这个脚本 ENTRYPOINT ["python", "/action/entrypoint.py"]
  4. 创建入口脚本 (entrypoint.py):
    python
    import os import sys import subprocess def run_linter(python_version): print(f"Running linter with Python {python_version}") # 在这里编写你的核心逻辑,例如运行 flake8 result = subprocess.run(['flake8', 'src/'], capture_output=True, text=True) if result.returncode != 0: print(result.stdout) print(result.stderr) sys.exit(result.returncode) else: print("Linting passed!") if __name__ == '__main__': # 第一个参数是脚本名,第二个开始才是传递的参数 python_version = sys.argv[1] if len(sys.argv) > 1 else '3.9' run_linter(python_version)

使用你的 Docker Action

yaml
- name: Checkout code uses: actions/checkout@v4 - name: Run Python Linter uses: your-username/my-python-linter-action@v1 with: python-version: '3.10'

关键注意事项和最佳实践

  1. 版本控制

    • 使用 Git 标签(如 @v1, @v1.0.2)来发布 Action 的稳定版本。
    • 绝对不要在生产工作流中引用 @main 分支,因为 breaking change 会破坏你的 CI/CD。
  2. 选择类型的考量

    • 选 JavaScript Action:如果你的逻辑主要是调用 API、处理数据,且依赖的工具在 GitHub 运行器上普遍存在(如 curl, git, npm)。
    • 选 Docker Action:如果你需要特定版本的操作系统、编译器、语言运行时(如古老的 Python 2.7、特定的 JDK 版本)或复杂的系统依赖库。
  3. 安全性

    • 使用来自可信源的 Action,检查其源码。
    • 对于 Docker Action,尽量使用官方或受信任的基础镜像,并定期更新以修补安全漏洞。
  4. 性能

    • Docker Action 的 image: 'Dockerfile' 会在每次运行时构建,非常慢。应该先构建好镜像并推送到 Docker Hub 或 GitHub Container Registry (ghcr.io),然后使用 image: 'docker://my-image:tag'

本文作者:sea-whales

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!