# 创建组合操作

在本教程中，你将学习如何构建组合操作。

> \[!NOTE]
> GitHub Enterprise Server 目前不支持 GitHub 托管的运行器。

## 简介

在本指南中，您将了解创建和使用打包的组合操作所需的基本组件。 本指南的重点是打包操作所需的组件，因此很少讲操作代码的功能。 该操作将依次打印 "Hello World" 和 "Goodbye"，如果你提供自定义名称，则将依次打印 "Hello \[who-to-greet]" 和 "Goodbye"。 该操作还会将随机数映射到 `random-number` 输出变量，并运行名为 `goodbye.sh` 的脚本。

完成此项目后，您应了解如何构建自己的组合操作和在工作流程测试该操作。

> \[!WARNING]
> 创建工作流和操作时，应始终考虑代码是否可能执行潜在攻击者的不受信任的输入。 某些上下文应被视为不受信任的输入，因为攻击者可能会插入自己的恶意内容。 有关详细信息，请参阅“[安全使用指南](/zh/enterprise-server@3.22/actions/reference/security/secure-use#good-practices-for-mitigating-script-injection-attacks)”。

### 复合操作和可重用工作流

复合操作允许你将一系列工作流作业步骤收集到单个操作中，然后可将其作为多个工作流中的单个作业步骤运行。 可重用工作流提供了另一种避免重复的方法，允许你从其他工作流中运行完整的工作流。 有关详细信息，请参阅“[重用工作流配置](/zh/enterprise-server@3.22/actions/concepts/workflows-and-actions/reusing-workflow-configurations)”。

## 先决条件

> \[!NOTE]
> 此示例介绍如何在单独的存储库中创建组合操作。 但可以在同一存储库中创建组合操作。 有关详细信息，请参阅“[创建组合操作](/zh/enterprise-server@3.22/actions/tutorials/create-actions/create-a-composite-action#creating-a-composite-action-within-the-same-repository)”。

在开始之前，你将创建一个存储库 GitHub。

1. 在 . 上 GitHub创建新的公共存储库。 可以选择任何存储库名称，或使用以下 `hello-world-composite-action` 示例。 将项目推送到 GitHub后，可以添加这些文件。 有关详细信息，请参阅“[创建新仓库](/zh/enterprise-server@3.22/repositories/creating-and-managing-repositories/creating-a-new-repository)”。

2. 将仓库克隆到计算机。 有关详细信息，请参阅“[克隆仓库](/zh/enterprise-server@3.22/repositories/creating-and-managing-repositories/cloning-a-repository)”。

3. 在您的终端中，将目录更改到您的新存储库。

   ```shell copy
   cd hello-world-composite-action
   ```

4. 在 `hello-world-composite-action` 存储库中，新建一个名为 `goodbye.sh` 的文件以及示例代码：

   ```shell copy
   echo "echo Goodbye" > goodbye.sh
   ```

5. 在终端中，生成 `goodbye.sh` 可执行文件。

   <div class="ghd-tool linux">

   ```shell copy
   chmod +x goodbye.sh
   ```

   </div>

   <div class="ghd-tool mac">

   ```shell copy
   chmod +x goodbye.sh
   ```

   </div>

   <div class="ghd-tool windows">

   ```shell copy
   git add --chmod=+x -- goodbye.sh
   ```

   </div>

6. 从终端签入 `goodbye.sh` 文件。

   <div class="ghd-tool linux">

   ```shell copy
   git add goodbye.sh
   git commit -m "Add goodbye script"
   git push
   ```

   </div>

   <div class="ghd-tool mac">

   ```shell copy
   git add goodbye.sh
   git commit -m "Add goodbye script"
   git push
   ```

   </div>

   <div class="ghd-tool windows">

   ```shell copy
   git commit -m "Add goodbye script"
   git push
   ```

   </div>

## 创建操作元数据文件

1. 在 `hello-world-composite-action` 存储库中，新建一个名为 `action.yml` 的文件，并添加以下示例代码。 有关此语法的详细信息，请参阅“[元数据语法参考](/zh/enterprise-server@3.22/actions/reference/workflows-and-actions/metadata-syntax#runs-for-composite-actions)”。

   ```yaml copy
   name: 'Hello World'
   description: 'Greet someone'
   inputs:
     who-to-greet:  # id of input
       description: 'Who to greet'
       required: true
       default: 'World'
   outputs:
     random-number:
       description: "Random number"
       value: ${{ steps.random-number-generator.outputs.random-number }}
   runs:
     using: "composite"
     steps:
       - name: Set Greeting
         run: echo "Hello $INPUT_WHO_TO_GREET."
         shell: bash
         env:
           INPUT_WHO_TO_GREET: ${{ inputs.who-to-greet }}

       - name: Random Number Generator
         id: random-number-generator
         run: echo "random-number=$(echo $RANDOM)" >> $GITHUB_OUTPUT
         shell: bash

       - name: Set GitHub Path
         run: echo "$GITHUB_ACTION_PATH" >> $GITHUB_PATH
         shell: bash
         env:
           GITHUB_ACTION_PATH: ${{ github.action_path }}

       - name: Run goodbye.sh
         run: goodbye.sh
         shell: bash

   ```

   此文件定义 `who-to-greet` 输入，将随机生成的数字映射到 `random-number` 输出变量，将操作路径添加到运行器系统路径（以在执行期间查找 `goodbye.sh` 脚本），并运行 `goodbye.sh` 脚本。

   有关管理输出的详细信息，请参阅“[元数据语法参考](/zh/enterprise-server@3.22/actions/reference/workflows-and-actions/metadata-syntax#outputs-for-composite-actions)”。

   有关如何使用 `github.action_path` 的详细信息，请参阅“[上下文参考](/zh/enterprise-server@3.22/actions/reference/workflows-and-actions/contexts#github-context)”。

2. 从终端签入 `action.yml` 文件。

   ```shell copy
   git add action.yml
   git commit -m "Add action"
   git push
   ```

3. 从终端添加标记。 本示例使用名为 `v1` 的标记。 有关详细信息，请参阅“[管理自定义操作](/zh/enterprise-server@3.22/actions/how-tos/create-and-publish-actions/manage-custom-actions#using-release-management-for-actions)”。

   ```shell copy
   git tag -a -m "Description of this release" v1
   git push --follow-tags
   ```

## 在工作流程中测试您的操作

以下工作流代码使用你在“[创建组合操作](/zh/enterprise-server@3.22/actions/tutorials/create-actions/create-a-composite-action#creating-an-action-metadata-file)”中完成的 Hello World 操作。

将工作流代码复制到另一个存储库中的 `.github/workflows/main.yml` 文件中，但将 `OWNER` 和 `SHA` 分别替换为存储库所有者和要使用的提交的 SHA。 还可以将 `who-to-greet` 输入替换为你的名称。

```yaml copy
on: [push]

jobs:
  hello_world_job:
    runs-on: ubuntu-latest
    name: A job to say hello
    steps:
      - uses: actions/checkout@v6
      - id: foo
        uses: OWNER/hello-world-composite-action@SHA
        with:
          who-to-greet: 'Mona the Octocat'
      - run: echo random-number "$RANDOM_NUMBER"
        shell: bash
        env:
          RANDOM_NUMBER: ${{ steps.foo.outputs.random-number }}
```

从存储库中，单击“操作”选项卡，然后选择最新的工作流运行。\*\*\*\* 输出应包括："Hello Mona the Octocat"、"Goodbye" 脚本的结果以及随机数字。

## 在同一存储库中创建组合操作

1. 创建名为 `hello-world-composite-action` 的新子文件夹，该文件夹可以放置在存储库中的任何子文件夹中。 但建议将其放置在 `.github/actions` 子文件夹中，以便于组织和整理。

2. 在 `hello-world-composite-action` 文件夹中，执行相同的步骤以创建 `goodbye.sh` 脚本

   ```shell copy
   echo "echo Goodbye" > goodbye.sh
   ```

   <div class="ghd-tool linux">

   ```shell copy
   chmod +x goodbye.sh
   ```

   </div>

   <div class="ghd-tool mac">

   ```shell copy
   chmod +x goodbye.sh
   ```

   </div>

   <div class="ghd-tool windows">

   ```shell copy
   git add --chmod=+x -- goodbye.sh
   ```

   </div>

   <div class="ghd-tool linux">

   ```shell copy
   git add goodbye.sh
   git commit -m "Add goodbye script"
   git push
   ```

   </div>

   <div class="ghd-tool mac">

   ```shell copy
   git add goodbye.sh
   git commit -m "Add goodbye script"
   git push
   ```

   </div>

   <div class="ghd-tool windows">

   ```shell copy
   git commit -m "Add goodbye script"
   git push
   ```

   </div>

3. 在 `hello-world-composite-action` 文件夹中，根据 `action.yml` 中的步骤创建 [](/zh/enterprise-server@3.22/actions/tutorials/create-actions/create-a-composite-action#creating-an-action-metadata-file) 文件。

4. 使用该操作时，在 `action.yml` 键中使用组合操作的 `uses` 文件所在的文件夹的相对路径。 下面的示例假定其位于 `.github/actions/hello-world-composite-action` 文件夹中。

```yaml copy
on: [push]

jobs:
  hello_world_job:
    runs-on: ubuntu-latest
    name: A job to say hello
    steps:
      - uses: actions/checkout@v6
      - id: foo
        uses: ./.github/actions/hello-world-composite-action
        with:
          who-to-greet: 'Mona the Octocat'
      - run: echo random-number "$RANDOM_NUMBER"
        shell: bash
        env:
          RANDOM_NUMBER: ${{ steps.foo.outputs.random-number }}
```