关于上下文
上下文是一种访问有关工作流运行、变量、运行器环境、作业和步骤的信息的方法。每个上下文都是一个包含属性的对象,这些属性可以是字符串或其他对象。
在不同的工作流运行条件下,上下文、对象和属性会有很大的不同。例如,matrix 上下文仅在 矩阵中的作业中填充。
您可以使用表达式语法访问上下文。有关更多信息,请参阅“在工作流和操作中评估表达式”。
${{ <context> }}
警告
创建工作流和操作时,应始终考虑您的代码是否可能执行来自潜在攻击者的不受信任的输入。某些上下文应被视为不受信任的输入,因为攻击者可能会插入他们自己的恶意内容。更多信息,请参阅“GitHub Actions 的安全加固”。
| 上下文名称 | 类型 | 描述 |
|---|---|---|
github | 对象 | 有关工作流运行的信息。更多信息,请参阅 github 上下文。 |
env | 对象 | 包含在工作流、作业或步骤中设置的变量。更多信息,请参阅 env 上下文。 |
vars | 对象 | 包含在仓库、组织或环境级别设置的变量。更多信息,请参阅 vars 上下文。 |
job | 对象 | 有关当前正在运行的作业的信息。更多信息,请参阅 job 上下文。 |
jobs | 对象 | 仅适用于可重用的工作流,包含可重用工作流中作业的输出。更多信息,请参阅 jobs 上下文。 |
steps | 对象 | 有关当前作业中已运行的步骤的信息。更多信息,请参阅 steps 上下文。 |
runner | 对象 | 有关正在运行当前作业的运行器的信息。更多信息,请参阅 runner 上下文。 |
secrets | 对象 | 包含可用于工作流运行的密钥的名称和值。更多信息,请参阅 secrets 上下文。 |
strategy | 对象 | 有关当前作业的矩阵执行策略的信息。更多信息,请参阅 strategy 上下文。 |
matrix | 对象 | 包含应用于当前作业的工作流中定义的矩阵属性。更多信息,请参阅 matrix 上下文。 |
needs | 对象 | 包含定义为当前作业依赖项的所有作业的输出。更多信息,请参阅 needs 上下文。 |
inputs | 对象 | 包含可重用或手动触发的工作流的输入。更多信息,请参阅 inputs 上下文。 |
作为表达式的一部分,您可以使用两种语法之一访问上下文信息。
- 索引语法:
github['sha'] - 属性解引用语法:
github.sha
为了使用属性解引用语法,属性名称必须以字母或_开头,并且只能包含字母数字字符、-或_。
如果您尝试解引用不存在的属性,它将评估为空字符串。
确定何时使用上下文
GitHub Actions 包含一组称为上下文的变量和一组类似的称为默认变量的变量。这些变量旨在用于工作流的不同点
- 默认环境变量:这些环境变量仅存在于执行作业的运行器上。更多信息,请参阅“在变量中存储信息”。
- 上下文:您可以在工作流的任何点使用大多数上下文,包括在默认变量不可用时。例如,您可以将上下文与表达式一起使用,以便在将作业路由到运行器以执行之前执行初始处理;这允许您将上下文与条件
if关键字一起使用,以确定是否应运行步骤。作业运行后,您还可以从执行作业的运行器中检索上下文变量,例如runner.os。有关您可以在工作流中使用各种上下文的位置的详细信息,请参阅“上下文可用性”。
以下示例演示了如何在作业中一起使用这些不同类型的变量
name: CI
on: push
jobs:
prod-check:
if: ${{ github.ref == 'refs/heads/main' }}
runs-on: ubuntu-latest
steps:
- run: echo "Deploying to production server on branch $GITHUB_REF"
name: CI
on: push
jobs:
prod-check:
if: ${{ github.ref == 'refs/heads/main' }}
runs-on: ubuntu-latest
steps:
- run: echo "Deploying to production server on branch $GITHUB_REF"
在此示例中,if语句检查github.ref上下文以确定当前分支名称;如果名称为refs/heads/main,则执行后续步骤。if检查由GitHub Actions处理,只有当结果为true时,作业才会发送到运行器。一旦作业发送到运行器,步骤就会执行并引用运行器的$GITHUB_REF变量。
上下文可用性
在整个工作流运行过程中,不同的上下文是可用的。例如,secrets上下文可能只能在作业中的某些位置使用。
此外,某些函数可能只能在某些位置使用。例如,hashFiles函数并非在所有地方都可用。
下表列出了工作流中每个上下文和特殊函数的使用限制。列出的上下文仅适用于给定的工作流密钥,并且可能无法在其他任何地方使用。除非列在下面,否则函数可以在任何地方使用。
| 工作流密钥 | 上下文 | 特殊函数 |
|---|---|---|
run-name | github, inputs, vars | 无 |
concurrency | github, inputs, vars | 无 |
env | github, secrets, inputs, vars | 无 |
jobs.<job_id>.concurrency | github, needs, strategy, matrix, inputs, vars | 无 |
jobs.<job_id>.container | github, needs, strategy, matrix, vars, inputs | 无 |
jobs.<job_id>.container.credentials | github, needs, strategy, matrix, env, vars, secrets, inputs | 无 |
jobs.<job_id>.container.env.<env_id> | github, needs, strategy, matrix, job, runner, env, vars, secrets, inputs | 无 |
jobs.<job_id>.container.image | github, needs, strategy, matrix, vars, inputs | 无 |
jobs.<job_id>.continue-on-error | github, needs, strategy, vars, matrix, inputs | 无 |
jobs.<job_id>.defaults.run | github, needs, strategy, matrix, env, vars, inputs | 无 |
jobs.<job_id>.env | github, needs, strategy, matrix, vars, secrets, inputs | 无 |
jobs.<job_id>.environment | github, needs, strategy, matrix, vars, inputs | 无 |
jobs.<job_id>.environment.url | github, needs, strategy, matrix, job, runner, env, vars, steps, inputs | 无 |
jobs.<job_id>.if | github, needs, vars, inputs | always, cancelled, success, failure |
jobs.<job_id>.name | github, needs, strategy, matrix, vars, inputs | 无 |
jobs.<job_id>.outputs.<output_id> | github, needs, strategy, matrix, job, runner, env, vars, secrets, steps, inputs | 无 |
jobs.<job_id>.runs-on | github, needs, strategy, matrix, vars, inputs | 无 |
jobs.<job_id>.secrets.<secrets_id> | github, needs, strategy, matrix, secrets, inputs, vars | 无 |
jobs.<job_id>.services | github, needs, strategy, matrix, vars, inputs | 无 |
jobs.<job_id>.services.<service_id>.credentials | github, needs, strategy, matrix, env, vars, secrets, inputs | 无 |
jobs.<job_id>.services.<service_id>.env.<env_id> | github, needs, strategy, matrix, job, runner, env, vars, secrets, inputs | 无 |
jobs.<job_id>.steps.continue-on-error | github, needs, strategy, matrix, job, runner, env, vars, secrets, steps, inputs | hashFiles |
jobs.<job_id>.steps.env | github, needs, strategy, matrix, job, runner, env, vars, secrets, steps, inputs | hashFiles |
jobs.<job_id>.steps.if | github, needs, strategy, matrix, job, runner, env, vars, steps, inputs | always, cancelled, success, failure, hashFiles |
jobs.<job_id>.steps.name | github, needs, strategy, matrix, job, runner, env, vars, secrets, steps, inputs | hashFiles |
jobs.<job_id>.steps.run | github, needs, strategy, matrix, job, runner, env, vars, secrets, steps, inputs | hashFiles |
jobs.<job_id>.steps.timeout-minutes | github, needs, strategy, matrix, job, runner, env, vars, secrets, steps, inputs | hashFiles |
jobs.<job_id>.steps.with | github, needs, strategy, matrix, job, runner, env, vars, secrets, steps, inputs | hashFiles |
jobs.<job_id>.steps.working-directory | github, needs, strategy, matrix, job, runner, env, vars, secrets, steps, inputs | hashFiles |
jobs.<job_id>.strategy | github, needs, vars, inputs | 无 |
jobs.<job_id>.timeout-minutes | github, needs, strategy, matrix, vars, inputs | 无 |
jobs.<job_id>.with.<with_id> | github, needs, strategy, matrix, inputs, vars | 无 |
on.workflow_call.inputs.<inputs_id>.default | github, inputs, vars | 无 |
on.workflow_call.outputs.<output_id>.value | github, jobs, vars, inputs | 无 |
示例:将上下文信息打印到日志
您可以将上下文的內容打印到日志进行调试。toJSON 函数 要求将 JSON 对象漂亮打印到日志。
警告
使用整个github上下文时,请注意它包含敏感信息,例如github.token。GitHub会在将密钥打印到控制台时对其进行屏蔽,但您在导出或打印上下文时应谨慎。创建工作流和操作时,应始终考虑您的代码是否可能执行来自潜在攻击者的不受信任的输入。某些上下文应被视为不受信任的输入,因为攻击者可能会插入他们自己的恶意内容。更多信息,请参阅“GitHub Actions 的安全加固”。
name: Context testing
on: push
jobs:
dump_contexts_to_log:
runs-on: ubuntu-latest
steps:
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Dump job context
env:
JOB_CONTEXT: ${{ toJson(job) }}
run: echo "$JOB_CONTEXT"
- name: Dump steps context
env:
STEPS_CONTEXT: ${{ toJson(steps) }}
run: echo "$STEPS_CONTEXT"
- name: Dump runner context
env:
RUNNER_CONTEXT: ${{ toJson(runner) }}
run: echo "$RUNNER_CONTEXT"
- name: Dump strategy context
env:
STRATEGY_CONTEXT: ${{ toJson(strategy) }}
run: echo "$STRATEGY_CONTEXT"
- name: Dump matrix context
env:
MATRIX_CONTEXT: ${{ toJson(matrix) }}
run: echo "$MATRIX_CONTEXT"
name: Context testing
on: push
jobs:
dump_contexts_to_log:
runs-on: ubuntu-latest
steps:
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Dump job context
env:
JOB_CONTEXT: ${{ toJson(job) }}
run: echo "$JOB_CONTEXT"
- name: Dump steps context
env:
STEPS_CONTEXT: ${{ toJson(steps) }}
run: echo "$STEPS_CONTEXT"
- name: Dump runner context
env:
RUNNER_CONTEXT: ${{ toJson(runner) }}
run: echo "$RUNNER_CONTEXT"
- name: Dump strategy context
env:
STRATEGY_CONTEXT: ${{ toJson(strategy) }}
run: echo "$STRATEGY_CONTEXT"
- name: Dump matrix context
env:
MATRIX_CONTEXT: ${{ toJson(matrix) }}
run: echo "$MATRIX_CONTEXT"
github 上下文
github上下文包含有关工作流运行和触发运行的事件的信息。您也可以在环境变量中读取大部分github上下文数据。有关环境变量的更多信息,请参阅“在变量中存储信息”。
警告
使用整个github上下文时,请注意它包含敏感信息,例如github.token。GitHub会在将密钥打印到控制台时对其进行屏蔽,但您在导出或打印上下文时应谨慎。创建工作流和操作时,应始终考虑您的代码是否可能执行来自潜在攻击者的不受信任的输入。某些上下文应被视为不受信任的输入,因为攻击者可能会插入他们自己的恶意内容。更多信息,请参阅“GitHub Actions 的安全加固”。
| 属性名称 | 类型 | 描述 |
|---|---|---|
github | 对象 | 在工作流中的任何作业或步骤期间都可用的顶级上下文。此对象包含下面列出的所有属性。 |
github.action | 字符串 | 当前正在运行的操作的名称,或id步骤。GitHub会删除特殊字符,并在当前步骤运行没有id的脚本时使用名称__run。如果您在同一作业中多次使用相同的操作,则名称将包括带有下划线的序列号后缀。例如,您运行的第一个脚本的名称将为__run,第二个脚本的名称将为__run_2。类似地,actions/checkout的第二次调用将是actionscheckout2。 |
github.action_path | 字符串 | 操作所在的路径。此属性仅在复合操作中受支持。您可以使用此路径访问与操作位于同一存储库中的文件,例如通过将目录更改为路径:cd ${{ github.action_path }}。 |
github.action_ref | 字符串 | 对于执行操作的步骤,这是正在执行的操作的引用。例如,v2。不要在 run关键字中使用。为了使此上下文与复合操作一起使用,请在复合操作的env上下文中引用它。 |
github.action_repository | 字符串 | 对于执行操作的步骤,这是操作的所有者和存储库名称。例如,actions/checkout。不要在 run关键字中使用。为了使此上下文与复合操作一起使用,请在复合操作的env上下文中引用它。 |
github.action_status | 字符串 | 对于复合操作,这是复合操作的当前结果。 |
github.actor | 字符串 | 触发初始工作流运行的用户的用户名。如果工作流运行是重新运行,则此值可能与github.triggering_actor不同。任何工作流重新运行都将使用github.actor的权限,即使启动重新运行的参与者(github.triggering_actor)具有不同的权限。 |
github.actor_id | 字符串 | 触发初始工作流运行的人员或应用程序的帐户 ID。例如,1234567。请注意,这与参与者用户名不同。 |
github.api_url | 字符串 | GitHub REST API 的 URL。 |
github.base_ref | 字符串 | 工作流运行中拉取请求的base_ref或目标分支。此属性仅在触发工作流运行的事件为pull_request或pull_request_target时可用。 |
github.env | 字符串 | 运行器上设置来自工作流命令的环境变量的文件的路径。此文件对于当前步骤是唯一的,并且对于作业中的每个步骤都是不同的文件。更多信息,请参阅“GitHub Actions 的工作流命令”。 |
github.event | 对象 | 完整的事件 Webhook 负载。您可以使用此上下文访问事件的各个属性。此对象与触发工作流运行的事件的 Webhook 负载相同,并且对于每个事件都不同。“触发工作流的事件”中链接了每个 GitHub Actions 事件的 Webhook。例如,对于由push事件触发的工
|
github.event_name | 字符串 | 触发工作流运行的事件名称。 |
github.event_path | 字符串 | 包含完整事件Webhook有效负载的运行器上文件的路径。 |
github.graphql_url | 字符串 | GitHub GraphQL API 的 URL。 |
github.head_ref | 字符串 | 工作流运行中拉取请求的head_ref或源分支。此属性仅在触发工作流运行的事件为pull_request或pull_request_target时可用。 |
github.job | 字符串 | 当前作业的job_id。注意:此上下文属性由 Actions 运行器设置,仅在作业的执行 steps中可用。否则,此属性的值将为null。 |
github.path | 字符串 | 运行器上设置来自工作流命令的系统PATH变量的文件的路径。此文件对于当前步骤是唯一的,并且在作业中的每个步骤中都是不同的文件。有关更多信息,请参阅“GitHub Actions 的工作流命令”。 |
github.ref | 字符串 | 触发工作流运行的分支或标签的完整 ref。对于由push触发的workflow,这是推送的分支或标签 ref。对于由pull_request触发的workflow,这是拉取请求合并分支。对于由release触发的workflow,这是创建的发布标签。对于其他触发器,这是触发工作流运行的分支或标签 ref。仅当事件类型可用分支或标签时才设置此值。给定的 ref 是完整的,这意味着对于分支,格式为refs/heads/<branch_name>,对于拉取请求,它是refs/pull/<pr_number>/merge,对于标签,它是refs/tags/<tag_name>。例如,refs/heads/feature-branch-1。 |
github.ref_name | 字符串 | 触发工作流运行的分支或标签的简短 ref 名称。此值与 GitHub 上显示的分支或标签名称匹配。例如,feature-branch-1。对于拉取请求,格式为 <pr_number>/merge。 |
github.ref_protected | 布尔值 | 如果为触发工作流运行的 ref 配置了分支保护或规则集,则为true。 |
github.ref_type | 字符串 | 触发工作流运行的 ref 类型。有效值为branch或tag。 |
github.repository | 字符串 | 所有者和仓库名称。例如,octocat/Hello-World。 |
github.repository_id | 字符串 | 仓库的 ID。例如,123456789。请注意,这与仓库名称不同。 |
github.repository_owner | 字符串 | 仓库所有者的用户名。例如,octocat。 |
github.repository_owner_id | 字符串 | 仓库所有者的帐户 ID。例如,1234567。请注意,这与所有者的名称不同。 |
github.repositoryUrl | 字符串 | 仓库的 Git URL。例如,git://github.com/octocat/hello-world.git。 |
github.retention_days | 字符串 | 保留工作流运行日志和工件的天数。 |
github.run_id | 字符串 | 仓库中每次工作流运行的唯一编号。如果您重新运行工作流运行,此编号不会更改。 |
github.run_number | 字符串 | 仓库中特定工作流的每次运行的唯一编号。此编号从工作流的第一次运行开始为 1,每次新运行都会递增。如果您重新运行工作流运行,此编号不会更改。 |
github.run_attempt | 字符串 | 仓库中特定工作流运行的每次尝试的唯一编号。此编号从工作流运行的第一次尝试开始为 1,每次重新运行都会递增。 |
github.secret_source | 字符串 | 工作流中使用的密钥的来源。可能的值为None、Actions、Codespaces或Dependabot。 |
github.server_url | 字符串 | GitHub服务器的URL。例如:https://github.com。 |
github.sha | 字符串 | 触发工作流的提交 SHA。此提交 SHA 的值取决于触发工作流的事件。有关更多信息,请参阅“触发工作流的事件”。例如,ffac537e6cbbf934b08745a378932722df287a53。 |
github.token | 字符串 | 代表安装在您的仓库上的 GitHub 应用进行身份验证的令牌。这在功能上等效于GITHUB_TOKEN密钥。有关更多信息,请参阅“自动令牌身份验证”。注意:此上下文属性由 Actions 运行器设置,仅在作业的执行 steps中可用。否则,此属性的值将为null。 |
github.triggering_actor | 字符串 | 启动工作流运行的用户的用户名。如果工作流运行是重新运行,此值可能与github.actor不同。任何工作流重新运行都将使用github.actor的权限,即使启动重新运行的 actor (github.triggering_actor) 具有不同的权限。 |
github.workflow | 字符串 | 工作流的名称。如果工作流文件未指定name,则此属性的值为仓库中工作流文件的完整路径。 |
github.workflow_ref | 字符串 | 工作流的 ref 路径。例如,octocat/hello-world/.github/workflows/my-workflow.yml@refs/heads/my_branch。 |
github.workflow_sha | 字符串 | 工作流文件的提交 SHA。 |
github.workspace | 字符串 | 运行器上步骤的默认工作目录,以及使用checkout操作时仓库的默认位置。 |
github上下文的示例内容
以下示例上下文来自由push事件触发的workflow运行。此示例中的event对象已被截断,因为它与pushWebhook有效负载的内容相同。
注意
此上下文仅为示例。上下文的內容取决于您正在运行的工作流。在不同的工作流运行条件下,上下文、对象和属性会有很大的差异。
{
"token": "***",
"job": "dump_contexts_to_log",
"ref": "refs/heads/my_branch",
"sha": "c27d339ee6075c1f744c5d4b200f7901aad2c369",
"repository": "octocat/hello-world",
"repository_owner": "octocat",
"repositoryUrl": "git://github.com/octocat/hello-world.git",
"run_id": "1536140711",
"run_number": "314",
"retention_days": "90",
"run_attempt": "1",
"actor": "octocat",
"workflow": "Context testing",
"head_ref": "",
"base_ref": "",
"event_name": "push",
"event": {
...
},
"server_url": "https://github.com",
"api_url": "https://api.github.com",
"graphql_url": "https://api.github.com/graphql",
"ref_name": "my_branch",
"ref_protected": false,
"ref_type": "branch",
"secret_source": "Actions",
"workspace": "/home/runner/work/hello-world/hello-world",
"action": "github_step",
"event_path": "/home/runner/work/_temp/_github_workflow/event.json",
"action_repository": "",
"action_ref": "",
"path": "/home/runner/work/_temp/_runner_file_commands/add_path_b037e7b5-1c88-48e2-bf78-eaaab5e02602",
"env": "/home/runner/work/_temp/_runner_file_commands/set_env_b037e7b5-1c88-48e2-bf78-eaaab5e02602"
}
github上下文的示例用法
此示例工作流使用github.event_name上下文仅在工作流运行由pull_request事件触发时运行作业。
name: Run CI
on: [push, pull_request]
jobs:
normal_ci:
runs-on: ubuntu-latest
steps:
- name: Run normal CI
run: echo "Running normal CI"
pull_request_ci:
runs-on: ubuntu-latest
if: ${{ github.event_name == 'pull_request' }}
steps:
- name: Run PR CI
run: echo "Running PR only CI"
name: Run CI
on: [push, pull_request]
jobs:
normal_ci:
runs-on: ubuntu-latest
steps:
- name: Run normal CI
run: echo "Running normal CI"
pull_request_ci:
runs-on: ubuntu-latest
if: ${{ github.event_name == 'pull_request' }}
steps:
- name: Run PR CI
run: echo "Running PR only CI"
env上下文
env上下文包含已在工作流、作业或步骤中设置的变量。它不包含运行器进程继承的变量。有关在工作流中设置变量的更多信息,请参阅“GitHub Actions 的工作流语法”。
您可以检索存储在env上下文中的变量的值,并在工作流文件中使用这些值。您可以在工作流步骤中的任何键中使用env上下文,但id和uses键除外。有关步骤语法的更多信息,请参阅“GitHub Actions 的工作流语法”。
如果您想在运行器中使用变量的值,请使用运行器操作系统的读取环境变量的常规方法。
| 属性名称 | 类型 | 描述 |
|---|---|---|
env | 对象 | 此上下文在作业中的每个步骤都会发生变化。您可以从作业中的任何步骤访问此上下文。此对象包含下面列出的属性。 |
env.<env_name> | 字符串 | 特定环境变量的值。 |
env上下文的示例内容
env上下文的内容是变量名与其值的映射。上下文的內容可能会根据其在工作流运行中的使用位置而发生变化。在此示例中,env上下文包含两个变量。
{
"first_name": "Mona",
"super_duper_var": "totally_awesome"
}
env上下文的示例用法
此示例工作流显示在工作流、作业和步骤级别设置的env上下文中的变量。然后使用${{ env.VARIABLE-NAME }}语法在工作流中的各个步骤中检索变量值。
当定义多个具有相同名称的环境变量时,GitHub 将使用最具体的变量。例如,在步骤中定义的环境变量将在作业和工作流环境变量执行时覆盖具有相同名称的作业和工作流环境变量。在作业中为作业定义的环境变量将在作业执行时覆盖具有相同名称的工作流变量。
name: Hi Mascot
on: push
env:
mascot: Mona
super_duper_var: totally_awesome
jobs:
windows_job:
runs-on: windows-latest
steps:
- run: echo 'Hi ${{ env.mascot }}' # Hi Mona
- run: echo 'Hi ${{ env.mascot }}' # Hi Octocat
env:
mascot: Octocat
linux_job:
runs-on: ubuntu-latest
env:
mascot: Tux
steps:
- run: echo 'Hi ${{ env.mascot }}' # Hi Tux
name: Hi Mascot
on: push
env:
mascot: Mona
super_duper_var: totally_awesome
jobs:
windows_job:
runs-on: windows-latest
steps:
- run: echo 'Hi ${{ env.mascot }}' # Hi Mona
- run: echo 'Hi ${{ env.mascot }}' # Hi Octocat
env:
mascot: Octocat
linux_job:
runs-on: ubuntu-latest
env:
mascot: Tux
steps:
- run: echo 'Hi ${{ env.mascot }}' # Hi Tux
vars上下文
注意
GitHub Actions 的配置变量处于公开预览阶段,可能会发生更改。
vars上下文包含在组织、仓库和环境级别设置的自定义配置变量。有关定义可在多个工作流中使用的配置变量的更多信息,请参阅“在变量中存储信息”。
vars上下文的示例内容
vars上下文的内容是配置变量名与其值的映射。
{
"mascot": "Mona"
}
vars上下文的示例用法
此示例工作流显示如何在仓库、环境或组织级别设置的配置变量使用vars上下文自动可用。
注意
在运行器声明其环境后,环境级别的配置变量会自动可用。
如果未设置配置变量,则引用该变量的上下文的返回值将为空字符串。
以下示例显示了在整个工作流中使用vars上下文使用配置变量。以下每个配置变量都在仓库、组织或环境级别定义。
on:
workflow_dispatch:
env:
# Setting an environment variable with the value of a configuration variable
env_var: ${{ vars.ENV_CONTEXT_VAR }}
jobs:
display-variables:
name: ${{ vars.JOB_NAME }}
# You can use configuration variables with the `vars` context for dynamic jobs
if: ${{ vars.USE_VARIABLES == 'true' }}
runs-on: ${{ vars.RUNNER }}
environment: ${{ vars.ENVIRONMENT_STAGE }}
steps:
- name: Use variables
run: |
echo "repository variable : $REPOSITORY_VAR"
echo "organization variable : $ORGANIZATION_VAR"
echo "overridden variable : $OVERRIDE_VAR"
echo "variable from shell environment : $env_var"
env:
REPOSITORY_VAR: ${{ vars.REPOSITORY_VAR }}
ORGANIZATION_VAR: ${{ vars.ORGANIZATION_VAR }}
OVERRIDE_VAR: ${{ vars.OVERRIDE_VAR }}
- name: ${{ vars.HELLO_WORLD_STEP }}
if: ${{ vars.HELLO_WORLD_ENABLED == 'true' }}
uses: actions/hello-world-javascript-action@main
with:
who-to-greet: ${{ vars.GREET_NAME }}
on:
workflow_dispatch:
env:
# Setting an environment variable with the value of a configuration variable
env_var: ${{ vars.ENV_CONTEXT_VAR }}
jobs:
display-variables:
name: ${{ vars.JOB_NAME }}
# You can use configuration variables with the `vars` context for dynamic jobs
if: ${{ vars.USE_VARIABLES == 'true' }}
runs-on: ${{ vars.RUNNER }}
environment: ${{ vars.ENVIRONMENT_STAGE }}
steps:
- name: Use variables
run: |
echo "repository variable : $REPOSITORY_VAR"
echo "organization variable : $ORGANIZATION_VAR"
echo "overridden variable : $OVERRIDE_VAR"
echo "variable from shell environment : $env_var"
env:
REPOSITORY_VAR: ${{ vars.REPOSITORY_VAR }}
ORGANIZATION_VAR: ${{ vars.ORGANIZATION_VAR }}
OVERRIDE_VAR: ${{ vars.OVERRIDE_VAR }}
- name: ${{ vars.HELLO_WORLD_STEP }}
if: ${{ vars.HELLO_WORLD_ENABLED == 'true' }}
uses: actions/hello-world-javascript-action@main
with:
who-to-greet: ${{ vars.GREET_NAME }}
job上下文
job上下文包含有关当前正在运行的作业的信息。
| 属性名称 | 类型 | 描述 |
|---|---|---|
job | 对象 | 此上下文在工作流运行中的每个作业都会发生变化。您可以从作业中的任何步骤访问此上下文。此对象包含下面列出的所有属性。 |
job.container | 对象 | 有关作业容器的信息。有关容器的更多信息,请参阅“GitHub Actions 的工作流语法”。 |
job.container.id | 字符串 | 容器的 ID。 |
job.container.network | 字符串 | 容器网络的 ID。运行器将创建作业中所有容器使用的网络。 |
job.services | 对象 | 为作业创建的服务容器。有关服务容器的更多信息,请参阅“GitHub Actions 的工作流语法”。 |
job.services.<service_id>.id | 字符串 | 服务容器的 ID。 |
job.services.<service_id>.network | 字符串 | 服务容器网络的 ID。运行器将创建作业中所有容器使用的网络。 |
job.services.<service_id>.ports | 对象 | 服务容器公开的端口。 |
job.status | 字符串 | 作业的当前状态。可能的值为success、failure或cancelled。 |
job上下文的示例内容
此示例job上下文使用带有映射端口的PostgreSQL服务容器。如果作业中未使用任何容器或服务容器,则job上下文仅包含status属性。
{
"status": "success",
"container": {
"network": "github_network_53269bd575974817b43f4733536b200c"
},
"services": {
"postgres": {
"id": "60972d9aa486605e66b0dad4abb638dc3d9116f566579e418166eedb8abb9105",
"ports": {
"5432": "49153"
},
"network": "github_network_53269bd575974817b43f4733536b200c"
}
}
}
job上下文的示例用法
此示例工作流程配置了一个PostgreSQL服务容器,并自动将服务容器中的5432端口映射到主机上随机选择的可用端口。job上下文用于访问主机上分配的端口号。
name: PostgreSQL Service Example
on: push
jobs:
postgres-job:
runs-on: ubuntu-latest
services:
postgres:
image: postgres
env:
POSTGRES_PASSWORD: postgres
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
ports:
# Maps TCP port 5432 in the service container to a randomly chosen available port on the host.
- 5432
steps:
- run: pg_isready -h localhost -p ${{ job.services.postgres.ports[5432] }}
- run: echo "Run tests against Postgres"
name: PostgreSQL Service Example
on: push
jobs:
postgres-job:
runs-on: ubuntu-latest
services:
postgres:
image: postgres
env:
POSTGRES_PASSWORD: postgres
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
ports:
# Maps TCP port 5432 in the service container to a randomly chosen available port on the host.
- 5432
steps:
- run: pg_isready -h localhost -p ${{ job.services.postgres.ports[5432] }}
- run: echo "Run tests against Postgres"
jobs上下文
jobs上下文仅在可重用工作流程中可用,并且只能用于设置可重用工作流程的输出。更多信息,请参见“重用工作流程”。
| 属性名称 | 类型 | 描述 |
|---|---|---|
jobs | 对象 | 这仅在可重用工作流程中可用,并且只能用于设置可重用工作流程的输出。此对象包含下面列出的所有属性。 |
jobs.<job_id>.result | 字符串 | 可重用工作流程中作业的结果。可能的值为success、failure、cancelled或skipped。 |
jobs.<job_id>.outputs | 对象 | 可重用工作流程中作业的输出集。 |
jobs.<job_id>.outputs.<output_name> | 字符串 | 可重用工作流程中作业的特定输出的值。 |
jobs上下文的示例内容
此示例jobs上下文包含来自可重用工作流程运行的作业的结果和输出。
{
"example_job": {
"result": "success",
"outputs": {
"output1": "hello",
"output2": "world"
}
}
}
jobs上下文的示例用法
此示例可重用工作流程使用jobs上下文设置可重用工作流程的输出。请注意输出如何从步骤向上流向作业,然后流向workflow_call触发器。更多信息,请参见“重用工作流程”。
name: Reusable workflow
on:
workflow_call:
# Map the workflow outputs to job outputs
outputs:
firstword:
description: "The first output string"
value: ${{ jobs.example_job.outputs.output1 }}
secondword:
description: "The second output string"
value: ${{ jobs.example_job.outputs.output2 }}
jobs:
example_job:
name: Generate output
runs-on: ubuntu-latest
# Map the job outputs to step outputs
outputs:
output1: ${{ steps.step1.outputs.firstword }}
output2: ${{ steps.step2.outputs.secondword }}
steps:
- id: step1
run: echo "firstword=hello" >> $GITHUB_OUTPUT
- id: step2
run: echo "secondword=world" >> $GITHUB_OUTPUT
name: Reusable workflow
on:
workflow_call:
# Map the workflow outputs to job outputs
outputs:
firstword:
description: "The first output string"
value: ${{ jobs.example_job.outputs.output1 }}
secondword:
description: "The second output string"
value: ${{ jobs.example_job.outputs.output2 }}
jobs:
example_job:
name: Generate output
runs-on: ubuntu-latest
# Map the job outputs to step outputs
outputs:
output1: ${{ steps.step1.outputs.firstword }}
output2: ${{ steps.step2.outputs.secondword }}
steps:
- id: step1
run: echo "firstword=hello" >> $GITHUB_OUTPUT
- id: step2
run: echo "secondword=world" >> $GITHUB_OUTPUT
steps上下文
steps上下文包含有关当前作业中具有指定id并已运行的步骤的信息。
| 属性名称 | 类型 | 描述 |
|---|---|---|
steps | 对象 | 此上下文在作业中的每个步骤都会发生变化。您可以从作业中的任何步骤访问此上下文。此对象包含下面列出的所有属性。 |
steps.<step_id>.outputs | 对象 | 为步骤定义的输出集。更多信息,请参见“GitHub Actions 元数据语法”。 |
steps.<step_id>.conclusion | 字符串 | 应用continue-on-error后已完成步骤的结果。可能的值为success、failure、cancelled或skipped。当continue-on-error步骤失败时,outcome为failure,但最终的conclusion为success。 |
steps.<step_id>.outcome | 字符串 | 应用continue-on-error之前已完成步骤的结果。可能的值为success、failure、cancelled或skipped。当continue-on-error步骤失败时,outcome为failure,但最终的conclusion为success。 |
steps.<step_id>.outputs.<output_name> | 字符串 | 特定输出的值。 |
steps上下文的示例内容
此示例steps上下文显示了两个先前具有指定id的步骤。第一步的id名为checkout,第二步为generate_number。generate_number步骤有一个名为random_number的输出。
{
"checkout": {
"outputs": {},
"outcome": "success",
"conclusion": "success"
},
"generate_number": {
"outputs": {
"random_number": "1"
},
"outcome": "success",
"conclusion": "success"
}
}
steps上下文的示例用法
此示例工作流程在一个步骤中生成一个随机数作为输出,后续步骤使用steps上下文读取该输出的值。
name: Generate random failure
on: push
jobs:
randomly-failing-job:
runs-on: ubuntu-latest
steps:
- name: Generate 0 or 1
id: generate_number
run: echo "random_number=$(($RANDOM % 2))" >> $GITHUB_OUTPUT
- name: Pass or fail
run: |
if [[ ${{ steps.generate_number.outputs.random_number }} == 0 ]]; then exit 0; else exit 1; fi
name: Generate random failure
on: push
jobs:
randomly-failing-job:
runs-on: ubuntu-latest
steps:
- name: Generate 0 or 1
id: generate_number
run: echo "random_number=$(($RANDOM % 2))" >> $GITHUB_OUTPUT
- name: Pass or fail
run: |
if [[ ${{ steps.generate_number.outputs.random_number }} == 0 ]]; then exit 0; else exit 1; fi
runner上下文
runner上下文包含有关正在执行当前作业的运行程序的信息。
| 属性名称 | 类型 | 描述 |
|---|---|---|
runner | 对象 | 此上下文在工作流程运行中的每个作业都会发生变化。此对象包含下面列出的所有属性。 |
runner.name | 字符串 | 执行作业的运行程序的名称。此名称在工作流程运行中可能不是唯一的,因为存储库和组织级别的运行程序可以使用相同的名称。 |
runner.os | 字符串 | 执行作业的运行程序的操作系统。可能的值为Linux、Windows或macOS。 |
runner.arch | 字符串 | 执行作业的运行程序的体系结构。可能的值为X86、X64、ARM或ARM64。 |
runner.temp | 字符串 | 运行程序上临时目录的路径。此目录在每个作业的开始和结束时都会被清空。请注意,如果运行程序的用户帐户没有删除它们的权限,则文件不会被删除。 |
runner.tool_cache | 字符串 | 包含 GitHub 托管运行程序预安装工具的目录的路径。更多信息,请参见“使用 GitHub 托管运行程序”。 |
runner.debug | 字符串 | 仅当启用调试日志记录时才设置此项,并且始终具有值1。它可以用作指示器,以在您自己的作业步骤中启用其他调试或详细日志记录。 |
runner.environment | 字符串 | 执行作业的运行程序的环境。可能的值为:GitHub 提供的 GitHub 托管运行程序为github-hosted,存储库所有者配置的自托管运行程序为self-hosted。 |
runner上下文的示例内容
以下示例上下文来自 Linux GitHub 托管运行程序。
{
"os": "Linux",
"arch": "X64",
"name": "GitHub Actions 2",
"tool_cache": "/opt/hostedtoolcache",
"temp": "/home/runner/work/_temp"
}
runner上下文的示例用法
此示例工作流程使用runner上下文设置写入日志的临时目录的路径,如果工作流程失败,则会将这些日志作为工件上传。
name: Build
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build with logs
run: |
mkdir ${{ runner.temp }}/build_logs
echo "Logs from building" > ${{ runner.temp }}/build_logs/build.logs
exit 1
- name: Upload logs on fail
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: Build failure logs
path: ${{ runner.temp }}/build_logs
name: Build
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build with logs
run: |
mkdir ${{ runner.temp }}/build_logs
echo "Logs from building" > ${{ runner.temp }}/build_logs/build.logs
exit 1
- name: Upload logs on fail
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: Build failure logs
path: ${{ runner.temp }}/build_logs
secrets上下文
secrets上下文包含工作流程运行可用的密钥的名称和值。由于安全原因,组合操作无法使用secrets上下文。如果要将密钥传递给组合操作,需要将其显式地作为输入传递。有关密钥的更多信息,请参见“在 GitHub Actions 中使用密钥”。
GITHUB_TOKEN是为每个工作流程运行自动创建的密钥,并且始终包含在secrets上下文中。更多信息,请参见“自动令牌身份验证”。
警告
如果在作业中使用了密钥,GitHub 会自动屏蔽打印到日志中的密钥。应避免故意将密钥打印到日志中。
| 属性名称 | 类型 | 描述 |
|---|---|---|
secrets | 对象 | 此上下文在工作流程运行中的每个作业中都是相同的。您可以从作业中的任何步骤访问此上下文。此对象包含下面列出的所有属性。 |
secrets.GITHUB_TOKEN | 字符串 | 为每个工作流程运行自动创建的令牌。更多信息,请参见“自动令牌身份验证”。 |
secrets.<secret_name> | 字符串 | 特定密钥的值。 |
secrets上下文的示例内容
以下secrets上下文的示例内容显示了自动生成的GITHUB_TOKEN以及工作流程运行可用的其他两个密钥。
{
"github_token": "***",
"NPM_TOKEN": "***",
"SUPERSECRET": "***"
}
secrets上下文的示例用法
此示例工作流程使用GitHub CLI,这需要GITHUB_TOKEN作为GH_TOKEN输入参数的值。
name: Open new issue
on: workflow_dispatch
jobs:
open-issue:
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
steps:
- run: |
gh issue --repo ${{ github.repository }} \
create --title "Issue title" --body "Issue body"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
name: Open new issue
on: workflow_dispatch
jobs:
open-issue:
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
steps:
- run: |
gh issue --repo ${{ github.repository }} \
create --title "Issue title" --body "Issue body"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
strategy上下文
对于具有矩阵的工作流程,strategy上下文包含有关当前作业的矩阵执行策略的信息。
| 属性名称 | 类型 | 描述 |
|---|---|---|
strategy | 对象 | 此上下文在工作流程运行中的每个作业都会发生变化。您可以从工作流程中的任何作业或步骤访问此上下文。此对象包含下面列出的所有属性。 |
strategy.fail-fast | 布尔值 | 当此值评估为true时,如果矩阵中的任何作业失败,则所有正在进行的作业都将被取消。更多信息,请参见“GitHub Actions 工作流程语法”。 |
strategy.job-index | 数字 | 矩阵中当前作业的索引。**注意:**此数字是从零开始的数字。矩阵中第一个作业的索引为0。 |
strategy.job-total | 数字 | 矩阵中作业的总数。**注意:**此数字**不是**从零开始的数字。例如,对于具有四个作业的矩阵,job-total的值为4。 |
strategy.max-parallel | 数字 | 使用matrix作业策略时可以同时运行的作业的最大数量。更多信息,请参见“GitHub Actions 工作流程语法”。 |
strategy上下文的示例内容
以下strategy上下文的示例内容来自具有四个作业的矩阵,并且取自最后一个作业。请注意基于零的job-index数字与非基于零的job-total之间的区别。
{
"fail-fast": true,
"job-index": 3,
"job-total": 4,
"max-parallel": 4
}
strategy 上下文示例用法
此示例工作流使用strategy.job-index 属性为矩阵中的每个作业设置唯一的日志文件名。
name: Test strategy
on: push
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
test-group: [1, 2]
node: [14, 16]
steps:
- run: echo "Mock test logs" > test-job-${{ strategy.job-index }}.txt
- name: Upload logs
uses: actions/upload-artifact@v4
with:
name: Build log for job ${{ strategy.job-index }}
path: test-job-${{ strategy.job-index }}.txt
name: Test strategy
on: push
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
test-group: [1, 2]
node: [14, 16]
steps:
- run: echo "Mock test logs" > test-job-${{ strategy.job-index }}.txt
- name: Upload logs
uses: actions/upload-artifact@v4
with:
name: Build log for job ${{ strategy.job-index }}
path: test-job-${{ strategy.job-index }}.txt
matrix 上下文
对于具有矩阵的工作流,matrix 上下文包含在工作流文件中定义的并应用于当前作业的矩阵属性。例如,如果使用os 和node 键配置矩阵,则matrix 上下文对象将包含os 和node 属性及其当前作业正在使用的值。
matrix 上下文中没有标准属性,只有在工作流文件中定义的那些属性。
| 属性名称 | 类型 | 描述 |
|---|---|---|
matrix | 对象 | 此上下文仅适用于矩阵中的作业,并且在每次工作流运行中都会为每个作业发生变化。您可以从工作流中的任何作业或步骤访问此上下文。此对象包含下面列出的属性。 |
matrix.<property_name> | 字符串 | 矩阵属性的值。 |
matrix 上下文的示例内容
以下matrix 上下文的示例内容来自矩阵中的一个作业,该作业在工作流中定义了os 和node 矩阵属性。该作业正在执行ubuntu-latest 操作系统和 Node.js 版本16 的矩阵组合。
{
"os": "ubuntu-latest",
"node": 16
}
matrix 上下文的示例用法
此示例工作流使用os 和node 键创建一个矩阵。它使用matrix.os 属性设置每个作业的运行程序类型,并使用matrix.node 属性设置每个作业的 Node.js 版本。
name: Test matrix
on: push
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node: [14, 16]
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- name: Output node version
run: node --version
name: Test matrix
on: push
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node: [14, 16]
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- name: Output node version
run: node --version
needs 上下文
needs 上下文包含所有被定义为当前作业直接依赖项的作业的输出。请注意,这并不包括隐式依赖的作业(例如,依赖作业的依赖作业)。有关定义作业依赖项的更多信息,请参阅“GitHub Actions 的工作流语法”。
| 属性名称 | 类型 | 描述 |
|---|---|---|
needs | 对象 | 此上下文仅在具有依赖作业的工作流运行中填充,并且在每次工作流运行中都会为每个作业发生变化。您可以从工作流中的任何作业或步骤访问此上下文。此对象包含下面列出的所有属性。 |
needs.<job_id> | 对象 | 当前作业依赖的单个作业。 |
needs.<job_id>.outputs | 对象 | 当前作业依赖的作业的输出集。 |
needs.<job_id>.outputs.<output name> | 字符串 | 当前作业依赖的作业的特定输出的值。 |
needs.<job_id>.result | 字符串 | 当前作业依赖的作业的结果。可能的值为success、failure、cancelled 或skipped。 |
needs 上下文的示例内容
以下needs 上下文的示例内容显示了当前作业依赖的两个作业的信息。
{
"build": {
"result": "success",
"outputs": {
"build_id": "123456"
}
},
"deploy": {
"result": "failure",
"outputs": {}
}
}
needs 上下文的示例用法
此示例工作流包含三个作业:一个执行构建的build 作业,一个需要build 作业的deploy 作业,以及一个需要build 和deploy 作业并且仅在工作流失败时运行的debug 作业。deploy 作业还使用needs 上下文访问build 作业的输出。
name: Build and deploy
on: push
jobs:
build:
runs-on: ubuntu-latest
outputs:
build_id: ${{ steps.build_step.outputs.build_id }}
steps:
- name: Build
id: build_step
run: echo "build_id=$RANDOM" >> $GITHUB_OUTPUT
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- run: echo "Deploying build ${{ needs.build.outputs.build_id }}"
debug:
needs: [build, deploy]
runs-on: ubuntu-latest
if: ${{ failure() }}
steps:
- run: echo "Failed to build and deploy"
name: Build and deploy
on: push
jobs:
build:
runs-on: ubuntu-latest
outputs:
build_id: ${{ steps.build_step.outputs.build_id }}
steps:
- name: Build
id: build_step
run: echo "build_id=$RANDOM" >> $GITHUB_OUTPUT
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- run: echo "Deploying build ${{ needs.build.outputs.build_id }}"
debug:
needs: [build, deploy]
runs-on: ubuntu-latest
if: ${{ failure() }}
steps:
- run: echo "Failed to build and deploy"
inputs 上下文
inputs 上下文包含传递给操作、可重用工作流或手动触发的工作流的输入属性。对于可重用工作流,输入名称和类型在可重用工作流的workflow_call 事件配置中定义,输入值从调用可重用工作流的外部工作流中的jobs.<job_id>.with传递。对于手动触发的工作流,输入在工作流的workflow_dispatch 事件配置中定义。
inputs 上下文中的属性在工作流文件中定义。它们仅在可重用工作流或由workflow_dispatch 事件触发的工作流中可用。
| 属性名称 | 类型 | 描述 |
|---|---|---|
inputs | 对象 | 此上下文仅在可重用工作流或由workflow_dispatch 事件触发的工作流中可用。您可以从工作流中的任何作业或步骤访问此上下文。此对象包含下面列出的属性。 |
inputs.<name> | string 或 number 或 boolean 或 choice | 从外部工作流传递的每个输入值。 |
inputs 上下文的示例内容
以下inputs 上下文的示例内容来自定义了build_id、deploy_target 和perform_deploy 输入的工作流。
{
"build_id": 123456768,
"deploy_target": "deployment_sys_1a",
"perform_deploy": true
}
在可重用工作流中使用inputs 上下文的示例
此示例可重用工作流使用inputs 上下文获取从调用者工作流传递给可重用工作流的build_id、deploy_target 和perform_deploy 输入的值。
name: Reusable deploy workflow
on:
workflow_call:
inputs:
build_id:
required: true
type: number
deploy_target:
required: true
type: string
perform_deploy:
required: true
type: boolean
jobs:
deploy:
runs-on: ubuntu-latest
if: ${{ inputs.perform_deploy }}
steps:
- name: Deploy build to target
run: echo "Deploying build:${{ inputs.build_id }} to target:${{ inputs.deploy_target }}"
name: Reusable deploy workflow
on:
workflow_call:
inputs:
build_id:
required: true
type: number
deploy_target:
required: true
type: string
perform_deploy:
required: true
type: boolean
jobs:
deploy:
runs-on: ubuntu-latest
if: ${{ inputs.perform_deploy }}
steps:
- name: Deploy build to target
run: echo "Deploying build:${{ inputs.build_id }} to target:${{ inputs.deploy_target }}"
在手动触发的工作流中使用inputs 上下文的示例
此由workflow_dispatch 事件触发的示例工作流使用inputs 上下文获取传递给工作流的build_id、deploy_target 和perform_deploy 输入的值。
on:
workflow_dispatch:
inputs:
build_id:
required: true
type: string
deploy_target:
required: true
type: string
perform_deploy:
required: true
type: boolean
jobs:
deploy:
runs-on: ubuntu-latest
if: ${{ inputs.perform_deploy }}
steps:
- name: Deploy build to target
run: echo "Deploying build:${{ inputs.build_id }} to target:${{ inputs.deploy_target }}"
on:
workflow_dispatch:
inputs:
build_id:
required: true
type: string
deploy_target:
required: true
type: string
perform_deploy:
required: true
type: boolean
jobs:
deploy:
runs-on: ubuntu-latest
if: ${{ inputs.perform_deploy }}
steps:
- name: Deploy build to target
run: echo "Deploying build:${{ inputs.build_id }} to target:${{ inputs.deploy_target }}"