功能分类
每个 Sidekiq worker、批处理后台迁移、控制器动作、测试示例 或 API 端点都必须声明一个 feature_category 属性。该属性将每个元素映射到一个功能类别。这样做是为了错误预算、警报路由和团队归属。
功能类别的列表可以在 config/feature_categories.yml 文件中找到。该文件是从用于极狐GitLab 手册和其他极狐GitLab 资源的 stages.yml 数据文件生成的。
更新 config/feature_categories.yml
偶尔会有新功能添加到极狐GitLab 的阶段、群组和产品类别中。发生这种情况时,你可以通过运行 scripts/update-feature-categories 自动更新 config/feature_categories.yml。该脚本会获取并解析 stages.yml,并生成该文件的新版本,需要将其提交到仓库中。
可观测性 团队目前维护 feature_categories.yml 文件。当文件过时,他们会自动在 Slack 上收到通知。
Gemfile
对于每个 Ruby gem 依赖项,我们应该指定需要该依赖项的功能类别。这可以明确所有权,并将升级任务委派给拥有该功能的相应群组。
工具功能类别
对于开发者体验内部工具,我们使用 feature_category: :tooling。例如,knapsack 和 gitlab-crystalball 都用于在 CI 中运行 RSpec 测试套件,它们不属于任何产品群组。
测试平台功能类别
与端到端测试基础设施相关的 gem 由开发者体验部门维护。我们使用 feature_category: :test_platform 标签。例如,capybara 在 Gemfile 和 qa/Gemfile 中均被定义,用于运行涉及 UI 的测试。它们不属于特定的产品群组。
Rails 平台功能类别
Rails 核心框架 gem 主要由后端维护者维护。例如,rails 和 zeitwerk 应该定义为 :rails_platform。
共享功能类别
:shared 功能类别不再支持用于 gem。
作为提供良好 gem 维护工作的一部分,所有 gem 都必须使用特定的功能类别。如果你不确定某个 gem 的所有权,请联系 #backend_maintainers 频道寻求帮助。
Sidekiq workers
声明使用 feature_category 类方法,如下所示。
ruby1class SomeScheduledTaskWorker 2 include ApplicationWorker 3 4 # 声明此 worker 属于 5 # `continuous_integration` 功能类别 6 feature_category :continuous_integration 7 8 # ... 9end
使用 feature_category 指定的功能类别应该在 config/feature_categories.yml 中定义。否则,spec 将失败。
从功能分类中排除 Sidekiq workers
少数跨所有功能使用的 Sidekiq worker 无法映射到单个类别。这些应该使用 feature_category :not_owned 声明来声明,如下所示:
ruby1class SomeCrossCuttingConcernWorker 2 include ApplicationWorker 3 4 # 声明此 worker 未映射到任何功能类别 5 feature_category :not_owned # rubocop:disable Gitlab/AvoidFeatureCategoryNotOwned 6 7 # ... 8end
如果可能,标记为 "not owned" 的 worker 在指标和日志中使用其调用者的类别(worker 或 HTTP 端点)。例如,ReactiveCachingWorker 可以在指标和日志中具有多个功能类别。
批处理后台迁移
长时间运行的迁移(根据时间限制指南)会被提取为批处理后台迁移。它们应该定义一个 feature_category,如下所示:
ruby1# 文件名:lib/gitlab/background_migration/my_background_migration_job.rb 2 3class MyBackgroundMigrationJob < BatchedMigrationJob 4 feature_category :gitaly 5 6 #... 7end
RuboCop::Cop::BackgroundMigration::FeatureCategory cop 确保定义了有效的 feature_category。
Rails 控制器
可以在控制器动作上使用 feature_category 类方法来指定功能类别。
可以在整个控制器上指定功能类别,使用:
rubyclass Boards::ListsController < ApplicationController feature_category :kanban_boards end
功能类别可以使用第二个参数限制在一组动作中:
rubyclass DashboardController < ApplicationController feature_category :team_planning, [:issues, :issues_calendar] feature_category :code_review_workflow, [:merge_requests] end
这些形式不能混合使用:如果控制器有多个类别,则必须列出每个单独的动作。
从功能分类中排除控制器动作
在极少数情况下,一个动作无法与功能类别关联,可以使用 not_owned 功能类别来实现。
rubyclass Admin::LogsController < ApplicationController feature_category :not_owned end
确保功能类别有效
spec/controllers/every_controller_spec.rb 将遍历所有定义的路由,并检查控制器,以查看是否所有动作都分配了类别。该 spec 还会验证使用的功能类别是否已知,以及配置中使用的动作是否仍以路由形式存在。
API 端点
目前,GraphQL API 被归类为 not_owned。目前,无需额外规范。更多信息,请参见 gitlab-com/gl-infra/scalability#583。
Grape API 端点可以使用 feature_category 类方法,就像 Rails 控制器 一样:
rubymodule API class Issues < ::API::Base feature_category :team_planning end end
第二个参数可用于为特定路由指定功能类别:
rubymodule API class Users < ::API::Base feature_category :user_profile, ['/users/:id/custom_attributes', '/users/:id/custom_attributes/:key'] end end
或者可以在动作本身中指定功能类别:
ruby1module API 2 class Users < ::API::Base 3 get ':id', feature_category: :user_profile do 4 end 5 end 6end
与 Rails 控制器一样,API 类必须为每个单独的动作指定类别,除非该类内的每个动作都使用相同的类别。
RSpec 示例
你必须为每个 RSpec 示例设置功能类别元数据。此信息用于不稳定的测试议题,以识别拥有该功能的群组。
feature_category 应该是 config/feature_categories.yml 中的一个值。
feature_category 元数据可以设置在:
考虑在同一文件中识别出多个功能类别的情况下拆分文件。
示例:
rubyRSpec.describe Admin::Geo::SettingsController, :geo, feature_category: :geo_replication do
对于没有设置 feature_category 的示例,在本地环境中运行时会添加警告。
要禁用警告,在运行 RSpec 测试时使用 RSPEC_WARN_MISSING_FEATURE_CATEGORY=false:
shellRSPEC_WARN_MISSING_FEATURE_CATEGORY=false bin/rspec spec/<test_file>
另外,我们通过 RSpec/FeatureCategory RuboCop 规则标记违规。
工具功能类别
对于工程生产力内部工具,我们使用 feature_category: :tooling。
例如在 spec/tooling/danger/specs_spec.rb 中。
共享功能类别
:shared 功能类别不再支持用于测试。
作为简化不稳定的和隔离的测试自动化 工作的一部分,所有 spec 必须使用特定的功能类别。如果你不确定某个 spec 的所有权,请联系 #g_test_governance 团队寻求帮助。有关迁移具有 shared 所有权的现有测试,请参见此议题 了解详情。
管理员部分
向管理员部分添加新部分时,添加功能类别同样重要。以前,管理员部分在代码中通常被标记为 not_owned。现在,你必须确保对管理员部分的每个新增内容都使用 feature_category 符号正确标注。