---
date: "2026-06-26T00:00:00+00:00"
slug: "scoped-workflows"
sidebar_position: 60
---

# 作用域工作流

作用域工作流（Scoped Workflows）让你把 Actions 工作流集中维护在一个**源（source）**仓库中，并让它们自动在许多其他仓库上运行，而无需把工作流文件复制到每个仓库里。

提交到源仓库作用域工作流目录下的工作流文件，会在该源所适用的每个仓库（称为**消费方（consuming）**仓库）上运行。每次运行都在**消费方仓库自身的上下文**中执行：使用它的 runner、密钥、`GITEA_TOKEN` 和分支，而工作流**内容则读取自源仓库**。这适用于在组织或实例范围内强制推行共享 CI：代码检查、安全扫描、合规或策略检查等。

## 级别

源仓库可以在两个级别注册：

- **所有者级别（Owner level）**：由组织或用户注册。该源的工作流会在该组织或用户拥有的每个仓库上运行。
- **实例级别（Instance level）**：由站点管理员注册。该源的工作流会在实例上的**每一个**仓库上运行。

同一个仓库可以同时在两个级别注册；对于每个匹配的事件，它仍只会被评估一次。

:::note
实例级别的源适用于实例上的**每一个**仓库，且被设为必需（required）的源无法被选择退出（opt out）。检测会在每个仓库的每次事件上运行。请谨慎注册。
:::

## 配置

作用域工作流存放在一个与常规工作流分开的目录中，由 `app.ini` 中 `[actions]` 段的 `SCOPED_WORKFLOW_DIRS` 控制：

```ini
[actions]
SCOPED_WORKFLOW_DIRS = .gitea/scoped_workflows
```

- 默认值为 `.gitea/scoped_workflows`。
- 可以列出多个目录（以逗号分隔）。
- **不得与** `WORKFLOW_DIRS`（常规工作流目录，默认为 `.gitea/workflows` 和 `.github/workflows`）**重叠**。
- 留空意味着没有任何目录存放作用域工作流，因此不会找到也不会运行任何作用域工作流。设置页面仍会显示、源仍可注册，但不会有任何作用域工作流运行。

把作用域工作流放在它们自己的目录中，意味着源仓库**自身**的 Actions 不受影响：只有 `SCOPED_WORKFLOW_DIRS` 下的文件才会被当作作用域工作流。

## 从一个仓库提供作用域工作流

1. 在准备作为源的仓库中，把工作流文件提交到其**默认分支**上的作用域工作流目录下，例如 `.gitea/scoped_workflows/lint.yaml`：

   ```yaml
   name: Lint
   on: [push, pull_request]
   jobs:
     lint:
       runs-on: ubuntu-latest
       steps:
         - uses: actions/checkout@v4
         - run: echo "lint the consuming repository here"
   ```

2. 将该仓库注册为源：

   - **组织**：*组织设置 -> Actions -> 作用域工作流*
   - **用户**：*用户设置 -> Actions -> 作用域工作流*
   - **实例（管理员）**：*管理后台 -> Actions -> 作用域工作流*

   搜索并添加该仓库。此后，它的作用域工作流便会适用于该级别下的消费方仓库。

源仓库也在它自己的作用域内，因此它会像其他消费方一样在自身上运行这些工作流。

## 作用域工作流如何运行

- 该运行属于**消费方**仓库，使用它的 runner、密钥、`GITEA_TOKEN` 和 ref。它在那里的表现与普通运行一致，包括重跑、日志和提交状态。
- 工作流**内容读取自源**仓库，并钉定在事件发生时源默认分支的 commit 上。
- 检测使用消费方仓库的事件，因此工作流的 `on:` 触发器（例如 `push` 和 `pull_request`）必须与该事件匹配。

## 选择退出（Opting out）

消费方仓库可以在其 **Actions** 页面（该工作流会显示在其源之下）禁用一个它不想要的作用域工作流。已被标记为**必需（required）**（见下文）的工作流，消费方仓库永远无法将其禁用，也无法选择退出。

## 必需工作流与合并门禁

在作用域工作流设置页面上，你可以把单个工作流标记为**必需（required）**，并为每个工作流给定一个或多个**状态检查模式（status-check patterns）**（每行一个 glob）。一个必需的作用域工作流：

- 无法被消费方仓库禁用。
- 会对合并请求（PR）形成合并门禁：消费方的 PR 只有在一个匹配**每一个**模式的提交状态都**通过**后才能合并（必须存在且通过，must-present-and-pass）。一个从不产生任何状态的必需检查会**阻止**合并，而不是被静默跳过，因此在消费方关闭 Actions 也无法绕过它。

作用域运行产生的状态检查 context 形如：

```
<源仓库全名>: <工作流显示名> / <job> (<event>)
```

设置页面会为每个工作流预览这些 “Expected status checks（预期状态检查）”，并标记出与你的模式匹配的项，便于你确认模式是否正确。一种常见模式是对 job 和 event 使用通配符，例如 `my-org/ci-repo: Lint / *`。

强制范围：

- 必需检查会在任何设有**分支保护规则**的目标分支上强制生效，即使该规则自身的状态检查处于关闭状态。
- **没有**保护规则的目标分支不受门禁约束。

:::warning
只有运行在会产生提交状态的事件（`push`、`pull_request`、`pull_request_target`、`release`）上的工作流才能被设为必需。仅运行在 `workflow_dispatch`、`schedule` 或 `workflow_call` 等事件上的工作流不会产生任何状态，因此把它设为必需会**永久**阻止每一个消费方 PR 的合并。设置页面在这种情况下会向你发出警告。
:::

## 可复用工作流（`uses:`）

作用域工作流可以调用可复用工作流：

- **本地**引用（`uses: ./...`）会相对于**源**仓库解析：即调用方工作流内容的来源仓库，而非消费方仓库。
- **跨仓库**引用（`uses: owner/repo/...@ref`）会以**消费方仓库的**读取权限来解析。如果它指向一个私有仓库，请确保每个消费方仓库都能读取它，否则工作流会在那里失败。

可复用工作流可以放在源仓库的 `SCOPED_WORKFLOW_DIRS`（或 `WORKFLOW_DIRS`）之下。

## 安全注意事项

源仓库的工作流内容会在它所适用的每个仓库中执行，其步骤脚本及其输出会写入该仓库的 Actions 日志，任何能查看消费方仓库 Actions 的人都能读取这些日志。

- 因此，将一个**私有**仓库注册为源，会通过这些日志泄露其工作流逻辑。只应注册那些其工作流内容可以与每个消费方仓库共享的仓库。

## 限制

- 目前不支持将 `on: schedule` 和 `on: workflow_run` 作为作用域工作流触发器。
- 作用域工作流内容读取自源的默认分支；源的其他分支不会被使用。
