{"meta":{"title":"创建组合操作","intro":"在本教程中，你将学习如何构建组合操作。","product":"GitHub Actions","breadcrumbs":[{"href":"/zh/enterprise-cloud@latest/actions","title":"GitHub Actions"},{"href":"/zh/enterprise-cloud@latest/actions/tutorials","title":"教程"},{"href":"/zh/enterprise-cloud@latest/actions/tutorials/create-actions","title":"创建操作"},{"href":"/zh/enterprise-cloud@latest/actions/tutorials/create-actions/create-a-composite-action","title":"创建组合操作"}],"documentType":"article"},"body":"# 创建组合操作\n\n在本教程中，你将学习如何构建组合操作。\n\n## 简介\n\n在本指南中，您将了解创建和使用打包的组合操作所需的基本组件。 本指南的重点是打包操作所需的组件，因此很少讲操作代码的功能。 该操作将依次打印 \"Hello World\" 和 \"Goodbye\"，如果你提供自定义名称，则将依次打印 \"Hello \\[who-to-greet]\" 和 \"Goodbye\"。 该操作还会将随机数映射到 `random-number` 输出变量，并运行名为 `goodbye.sh` 的脚本。\n\n完成此项目后，您应了解如何构建自己的组合操作和在工作流程测试该操作。\n\n> \\[!WARNING]\n> 创建工作流和操作时，应始终考虑代码是否可能执行潜在攻击者的不受信任的输入。 某些上下文应被视为不受信任的输入，因为攻击者可能会插入自己的恶意内容。 有关详细信息，请参阅“[安全使用指南](/zh/enterprise-cloud@latest/actions/security-guides/security-hardening-for-github-actions#understanding-the-risk-of-script-injections)”。\n\n### 复合操作和可重用工作流\n\n复合操作允许你将一系列工作流作业步骤收集到单个操作中，然后可将其作为多个工作流中的单个作业步骤运行。 可重用工作流提供了另一种避免重复的方法，允许你从其他工作流中运行完整的工作流。 有关详细信息，请参阅“[重用工作流配置](/zh/enterprise-cloud@latest/actions/using-workflows/avoiding-duplication)”。\n\n## 先决条件\n\n> \\[!NOTE]\n> 此示例介绍如何在单独的存储库中创建组合操作。 但可以在同一存储库中创建组合操作。 有关详细信息，请参阅“[创建组合操作](/zh/enterprise-cloud@latest/actions/creating-actions/creating-a-composite-action#creating-a-composite-action-within-the-same-repository)”。\n\n在开始之前，将在 GitHub\n上创建一个存储库。\n\n1. 在 GitHub\n   上创建一个新的公共存储库。 可以选择任何存储库名称，或使用以下 `hello-world-composite-action` 示例。 你可以在项目推送到 GitHub\n   之后添加这些文件。 有关详细信息，请参阅“[创建新仓库](/zh/enterprise-cloud@latest/repositories/creating-and-managing-repositories/creating-a-new-repository)”。\n\n2. 将仓库克隆到计算机。 有关详细信息，请参阅“[克隆仓库](/zh/enterprise-cloud@latest/repositories/creating-and-managing-repositories/cloning-a-repository)”。\n\n3. 在您的终端中，将目录更改到您的新存储库。\n\n   ```shell copy\n   cd hello-world-composite-action\n   ```\n\n4. 在 `hello-world-composite-action` 存储库中，新建一个名为 `goodbye.sh` 的文件以及示例代码：\n\n   ```shell copy\n   echo \"echo Goodbye\" > goodbye.sh\n   ```\n\n5. 在终端中，生成 `goodbye.sh` 可执行文件。\n\n   <div class=\"ghd-tool linux\">\n\n   ```shell copy\n   chmod +x goodbye.sh\n   ```\n\n   </div>\n\n<div class=\"ghd-tool mac\">\n\n```shell copy\nchmod +x goodbye.sh\n```\n\n   </div>\n<div class=\"ghd-tool windows\">\n\n```shell copy\ngit add --chmod=+x -- goodbye.sh\n```\n\n   </div>\n\n1. 从终端签入 `goodbye.sh` 文件。\n\n   <div class=\"ghd-tool linux\">\n\n   ```shell copy\n   git add goodbye.sh\n   git commit -m \"Add goodbye script\"\n   git push\n   ```\n\n   </div>\n\n<div class=\"ghd-tool mac\">\n\n```shell copy\ngit add goodbye.sh\ngit commit -m \"Add goodbye script\"\ngit push\n```\n\n</div>\n\n<div class=\"ghd-tool windows\">\n\n```shell copy\ngit commit -m \"Add goodbye script\"\ngit push\n```\n\n   </div>\n\n## 创建操作元数据文件\n\n1. 在 `hello-world-composite-action` 存储库中，新建一个名为 `action.yml` 的文件，并添加以下示例代码。 有关此语法的详细信息，请参阅“[元数据语法参考](/zh/enterprise-cloud@latest/actions/creating-actions/metadata-syntax-for-github-actions#runs-for-composite-actions)”。\n\n   ```yaml copy\n   name: 'Hello World'\n   description: 'Greet someone'\n   inputs:\n     who-to-greet:  # id of input\n       description: 'Who to greet'\n       required: true\n       default: 'World'\n   outputs:\n     random-number:\n       description: \"Random number\"\n       value: ${{ steps.random-number-generator.outputs.random-number }}\n   runs:\n     using: \"composite\"\n     steps:\n       - name: Set Greeting\n         run: echo \"Hello $INPUT_WHO_TO_GREET.\"\n         shell: bash\n         env:\n           INPUT_WHO_TO_GREET: ${{ inputs.who-to-greet }}\n\n       - name: Random Number Generator\n         id: random-number-generator\n         run: echo \"random-number=$(echo $RANDOM)\" >> $GITHUB_OUTPUT\n         shell: bash\n\n       - name: Set GitHub Path\n         run: echo \"$GITHUB_ACTION_PATH\" >> $GITHUB_PATH\n         shell: bash\n         env:\n           GITHUB_ACTION_PATH: ${{ github.action_path }}\n\n       - name: Run goodbye.sh\n         run: goodbye.sh\n         shell: bash\n\n   ```\n\n   此文件定义 `who-to-greet` 输入，将随机生成的数字映射到 `random-number` 输出变量，将操作路径添加到运行器系统路径（以在执行期间查找 `goodbye.sh` 脚本），并运行 `goodbye.sh` 脚本。\n\n   有关管理输出的详细信息，请参阅“[元数据语法参考](/zh/enterprise-cloud@latest/actions/creating-actions/metadata-syntax-for-github-actions#outputs-for-composite-actions)”。\n\n   有关如何使用 `github.action_path` 的详细信息，请参阅“[上下文参考](/zh/enterprise-cloud@latest/actions/learn-github-actions/contexts#github-context)”。\n\n2. 从终端签入 `action.yml` 文件。\n\n   ```shell copy\n   git add action.yml\n   git commit -m \"Add action\"\n   git push\n   ```\n\n3. 从终端添加标记。 本示例使用名为 `v1` 的标记。 有关详细信息，请参阅“[关于自定义操作](/zh/enterprise-cloud@latest/actions/creating-actions/about-custom-actions#using-release-management-for-actions)”。\n\n   ```shell copy\n   git tag -a -m \"Description of this release\" v1\n   git push --follow-tags\n   ```\n\n## 在工作流程中测试您的操作\n\n以下工作流代码使用你在“[创建组合操作](/zh/enterprise-cloud@latest/actions/creating-actions/creating-a-composite-action#creating-an-action-metadata-file)”中完成的 Hello World 操作。\n\n将工作流代码复制到另一个存储库中的 `.github/workflows/main.yml` 文件中，但将 `OWNER` 和 `SHA` 分别替换为存储库所有者和要使用的提交的 SHA。 还可以将 `who-to-greet` 输入替换为你的名称。\n\n```yaml copy\non: [push]\n\njobs:\n  hello_world_job:\n    runs-on: ubuntu-latest\n    name: A job to say hello\n    steps:\n      - uses: actions/checkout@v5\n      - id: foo\n        uses: OWNER/hello-world-composite-action@SHA\n        with:\n          who-to-greet: 'Mona the Octocat'\n      - run: echo random-number \"$RANDOM_NUMBER\"\n        shell: bash\n        env:\n          RANDOM_NUMBER: ${{ steps.foo.outputs.random-number }}\n```\n\n从存储库中，单击“操作”选项卡，然后选择最新的工作流运行。\\*\\*\\*\\* 输出应包括：\"Hello Mona the Octocat\"、\"Goodbye\" 脚本的结果以及随机数字。\n\n## 在同一存储库中创建组合操作\n\n1. 创建名为 `hello-world-composite-action` 的新子文件夹，该文件夹可以放置在存储库中的任何子文件夹中。 但建议将其放置在 `.github/actions` 子文件夹中，以便于组织和整理。\n2. 在 `hello-world-composite-action` 文件夹中，执行相同的步骤以创建 `goodbye.sh` 脚本\n\n   ```shell copy\n   echo \"echo Goodbye\" > goodbye.sh\n   ```\n\n   <div class=\"ghd-tool linux\">\n\n   ```shell copy\n   chmod +x goodbye.sh\n   ```\n\n   </div>\n\n<div class=\"ghd-tool mac\">\n\n```shell copy\nchmod +x goodbye.sh\n```\n\n   </div>\n<div class=\"ghd-tool windows\">\n\n```shell copy\ngit add --chmod=+x -- goodbye.sh\n```\n\n   </div>\n<div class=\"ghd-tool linux\">\n\n```shell copy\ngit add goodbye.sh\ngit commit -m \"Add goodbye script\"\ngit push\n```\n\n   </div>\n<div class=\"ghd-tool mac\">\n\n```shell copy\ngit add goodbye.sh\ngit commit -m \"Add goodbye script\"\ngit push\n```\n\n</div>\n\n<div class=\"ghd-tool windows\">\n\n```shell copy\ngit commit -m \"Add goodbye script\"\ngit push\n```\n\n   </div>\n\n1. 在 `hello-world-composite-action` 文件夹中，根据 `action.yml` 中的步骤创建 [](/zh/enterprise-cloud@latest/actions/creating-actions/creating-a-composite-action#creating-an-action-metadata-file) 文件。\n2. 使用该操作时，在 `action.yml` 键中使用组合操作的 `uses` 文件所在的文件夹的相对路径。 下面的示例假定其位于 `.github/actions/hello-world-composite-action` 文件夹中。\n\n```yaml copy\non: [push]\n\njobs:\n  hello_world_job:\n    runs-on: ubuntu-latest\n    name: A job to say hello\n    steps:\n      - uses: actions/checkout@v5\n      - id: foo\n        uses: ./.github/actions/hello-world-composite-action\n        with:\n          who-to-greet: 'Mona the Octocat'\n      - run: echo random-number \"$RANDOM_NUMBER\"\n        shell: bash\n        env:\n          RANDOM_NUMBER: ${{ steps.foo.outputs.random-number }}\n```\n\n## GitHub\n\n上的复合操作示例\n\n可以在 GitHub\n上找到许多组合操作示例。\n\n* ```\n          [microsoft/action-python](https://github.com/microsoft/action-python)\n  ```\n* ```\n          [microsoft/gpt-review](https://github.com/microsoft/gpt-review)\n  ```\n* ```\n          [tailscale/github-action](https://github.com/tailscale/github-action)\n  ```"}