搞清楚 GitHub Actions 中 uses 的环境,以及如何制作自己的环境。
uses 的环境是 Docker 吗?答案是:取决于 Action 的类型。
GitHub Actions 支持三种类型的 Action,它们的执行环境不同:
run 和 uses)组合成一个可重用单元的方式。它本身不定义环境,其内部的每个步骤按其自己的方式执行(可能是 JavaScript、Docker 或 Shell 命令)。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文件
如何识别:
在 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'
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
需要创建一个新的 GitHub 仓库来存放你的 Action 代码。核心是创建一个 action.yml (或 action.yaml) 文件来定义 Action 的元数据和行为。
步骤:
my-cool-action。action.yml:
yamlname: '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' # 指向打包后的文件
src/main.js):
javascriptconst 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();
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"
}
}
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'
步骤:
my-python-linter-action。action.yml:
yamlname: '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 }}
Dockerfile:
dockerfile# 使用一个官方基础镜像 FROM python:3.9-slim # 将整个仓库文件拷贝到容器内的 /action 目录 COPY . /action WORKDIR /action # 在容器构建时安装你的依赖 RUN pip install --no-cache-dir flake8 # 设置入口点,容器启动时执行这个脚本 ENTRYPOINT ["python", "/action/entrypoint.py"]
entrypoint.py):
pythonimport 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'
版本控制:
@v1, @v1.0.2)来发布 Action 的稳定版本。@main 分支,因为 breaking change 会破坏你的 CI/CD。选择类型的考量:
curl, git, npm)。安全性:
性能:
image: 'Dockerfile' 会在每次运行时构建,非常慢。应该先构建好镜像并推送到 Docker Hub 或 GitHub Container Registry (ghcr.io),然后使用 image: 'docker://my-image:tag'本文作者:sea-whales
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!