actions/github-script
这个 Action 可以让你在工作流程中轻松快速地编写脚本,使用 GitHub API 和工作流运行上下文。
要使用这个 Action,请提供一个名为 script
的输入,其中包含异步函数调用的主体。将提供以下参数:
github
一个预先认证的 octokit/rest.js 客户端,带有分页插件context
一个包含工作流运行上下文的对象core
@actions/core 包的引用glob
@actions/glob 包的引用io
@actions/io 包的引用exec
@actions/exec 包的引用require
一个围绕普通 Node.jsrequire
的代理包装器,用于启用相对路径(相对于当前工作目录)的 require 和在当前工作目录中安装的 npm 包的 require。如果由于某种原因你需要未包装的require
,有一个逃生舱可用:__original_require__
是require
的原始值,没有应用我们的包装。
由于 script
只是一个函数体,这些值将已经被定义,所以你不需要导入它们(参见下面的例子)。
有关 API 客户端文档,请参阅 octokit/rest.js。
重大变更
V7
此 Action 的版本 7 将运行时更新到 Node 20 - https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#runs-for-javascript-actions
所有脚本现在都使用 Node 20 而不是 Node 16 运行,并受到 Node 16 和 20 之间的任何重大变更的影响。
previews
输入现在只适用于 GraphQL API 调用,因为 REST API 预览不再必要 - https://github.blog/changelog/2021-10-14-rest-api-preview-promotions/。
V6
此 Action 的版本 6 将运行时更新到 Node 16 - https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#runs-for-javascript-actions
所有脚本现在都使用 Node 16 而不是 Node 12 运行,并受到 Node 12 和 16 之间的任何重大变更的影响。
V5
此 Action 的版本 5 包括 @actions/github
和 @octokit/plugin-rest-endpoint-methods
的版本 5。作为此更新的一部分,通过 github
可用的 Octokit 上下文不再直接具有 REST 方法。这些方法通过 github.rest.*
提供 - https://github.com/octokit/plugin-rest-endpoint-methods.js/releases/tag/v5.0.0
例如,V4 中的 github.issues.createComment
在 V5 中变为 github.rest.issues.createComment
github.request
、github.paginate
和 github.graphql
保持不变。
开发
请参阅 development.md。
读取步骤结果
脚本的返回值将在步骤的输出中的 "result" 键下。
- uses: actions/github-script@v7
id: set-result
with:
script: return "Hello!"
result-encoding: string
- name: Get result
run: echo "${{steps.set-result.outputs.result}}"
有关如何更改这些输出的编码方式的详细信息,请参阅"结果编码"。
结果编码
默认情况下,函数的 JSON 编码返回值被设置为 github-script 步骤输出中的 "result"。对于某些工作流程,首选字符串编码。可以使用 result-encoding
输入设置此选项:
- uses: actions/github-script@v7
id: my-script
with:
result-encoding: string
script: return "I will be string (not JSON) encoded!"
重试
默认情况下,使用 github
实例发出的请求不会重试。你可以使用 retries
选项配置此行为:
- uses: actions/github-script@v7
id: my-script
with:
result-encoding: string
retries: 3
script: |
github.rest.issues.get({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
})
在这个例子中,github.rest.issues.get()
的请求失败将重试最多 3 次。
你还可以通过 retry-exempt-status-codes
选项配置哪些状态码应该免于重试:
- uses: actions/github-script@v7
id: my-script
with:
result-encoding: string
retries: 3
retry-exempt-status-codes: 400,401
script: |
github.rest.issues.get({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
})
默认情况下,以下状态码不会重试:400, 401, 403, 404, 422
(来源)。
这些重试使用 octokit/plugin-retry.js 插件实现。重试使用指数退避来间隔重试。(来源)
示例
请注意,在这个 Action 中 github-token
是可选的,输入存在是为了在需要使用非默认令牌的情况下使用。
默认情况下,github-script 将使用提供给你的工作流程的令牌。
打印 context 的可用属性
- name: View context attributes
uses: actions/github-script@v7
with:
script: console.log(context)
在 issue 上评论
on:
issues:
types: [opened]
jobs:
comment:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '👋 感谢你的报告!'
})
给 issue 添加标签
on:
issues:
types: [opened]
jobs:
apply-label:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
with:
script: |
github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['分类']
})
欢迎首次贡献者
你可以使用与 GitHub 网页界面相同的 Markdown 语法 来格式化评论中的文本:
on: pull_request_target
jobs:
welcome:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
with:
script: |
// 获取PR创建者创建的所有issue列表
// 参见:https://octokit.github.io/rest.js/#pagination
const creator = context.payload.sender.login
const opts = github.rest.issues.listForRepo.endpoint.merge({
...context.issue,
creator,
state: 'all'
})
const issues = await github.paginate(opts)
for (const issue of issues) {
if (issue.number === context.issue.number) {
continue
}
if (issue.pull_request) {
return // 创建者已经是贡献者了。
}
}
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `**欢迎**,新贡献者!
请确保你已经阅读了我们的[贡献指南](CONTRIBUTING.md),我们期待很快审核你的 Pull request ✨`
})
从 URL 下载数据
你可以使用 github
对象访问 Octokit API。例如,github.request
on: pull_request
jobs:
diff:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
with:
script: |
const diff_url = context.payload.pull_request.diff_url
const result = await github.request(diff_url)
console.log(result)
(请注意,这个特定的例子只适用于公共 URL,其中 diff URL 是公开可访问的。获取私有 URL 的 diff 需要使用 API。)
这将在屏幕上打印完整的 diff 对象;result.data
将包含实际的 diff 文本。
运行自定义 GraphQL 查询
你可以使用 github.graphql
对象对 GitHub API 运行自定义 GraphQL 查询。
jobs:
list-issues:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
with:
script: |
const query = `query($owner:String!, $name:String!, $label:String!) {
repository(owner:$owner, name:$name){
issues(first:100, labels: [$label]) {
nodes {
id
}
}
}
}`;
const variables = {
owner: context.repo.owner,
name: context.repo.repo,
label: 'wontfix'
}
const result = await github.graphql(query, variables)
console.log(result)
运行单独的文件
如果你不想内联你想运行的整个脚本,你可以使用存储库中的单独 JavaScript 模块,如下所示:
on: push
jobs:
echo-input:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/github-script@v7
with:
script: |
const script = require('./path/to/script.js')
console.log(script({github, context}))
然后从你的模块导出一个函数:
module.exports = ({github, context}) => {
return context.payload.client_payload.value
}
请注意,因为你不能 require
像 GitHub 上下文或 Actions Toolkit 库这样的东西,你会想把它们作为参数传递给你的外部函数。
此外,你会想使用 checkout action 来确保你的脚本文件可用。
运行带有异步函数的单独文件
你也可以以这种方式使用异步函数,只要你在内联脚本中 await
它。
在你的工作流程中:
on: push
jobs:
echo-input:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/github-script@v7
env:
SHA: '${{env.parentSHA}}'
with:
script: |
const script = require('./path/to/script.js')
await script({github, context, core})
然后从你的模块导出一个异步函数:
module.exports = async ({github, context, core}) => {
const {SHA} = process.env
const commit = await github.rest.repos.getCommit({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `${SHA}`
})
core.exportVariable('author', commit.data.commit.author.email)
}
使用 npm 包
像上面导入你自己的文件一样,你也可以使用已安装的模块。请注意,这是通过 require
的包装器实现的,所以如