Expose automatic_rebase_enabled on project read endpoints

automatic_rebase_enabled can be set through PUT /projects/:id but no endpoint returns it, so clients cannot verify the value took effect or reconcile drift. This exposes it on Entities::Project, which covers GET /projects/:id, GET /projects, and the create/update responses.

Doing that needs an entry in the API entity exposure baseline, and the style guide asks you not to edit that file without talking to API Platform first. So please read this as the proposal for that conversation rather than a rubber stamp - the argument for why the field belongs on the project entity is in the collapsed block. Worth flagging that /rubocop/ routes to rails-backend in CODEOWNERS, not API Platform, so that review has to be asked for deliberately.

Related to #623568 (closed)

Detailed context for AI agents

Background

automatic_rebase_enabled was made writable via PUT /projects/:id in !250632 (merged) (GitLab 19.4). That MR deliberately shipped write-only. An earlier revision of it exposed the value on reads too, but that needed a new API entity concern plus two new leaf entity classes inheriting the WithCatalogSetting / WithAccessAndCatalogSetting chain, because the field cannot be added to lib/api/entities/project.rb without editing the exposure baseline (the API/EntityExposureGrowth cop). That scaffolding was judged disproportionate and dropped, with read support left as a follow-up needing an API Platform opinion first. This MR is that follow-up.

Why edit the baseline rather than add a feature-bounded entity

  • Every other merge request setting stored on the project_settings table that accepts a REST write also has a REST read on the project entity. Examples: protect_merge_request_pipelines (lib/api/entities/project.rb:145), show_diff_preview_in_email (lib/api/entities/project.rb:98), squash_option and merge_method (same file), and on the EE side web_based_commit_signing_enabled (ee/lib/ee/api/entities/project.rb:77), merge_request_title_regex (ee/lib/ee/api/entities/project.rb:87), only_allow_merge_if_all_status_checks_passed (ee/lib/ee/api/entities/project.rb:66), prevent_merge_without_jira_issue (ee/lib/ee/api/entities/project.rb:68) and reviewer_assignment_strategy (ee/lib/ee/api/entities/project.rb:70). automatic_rebase_enabled is the only exception, and it is an exception because of when the exposure-growth cop landed, not because of a design decision about where the field belongs.
  • A feature-bounded subclass would inherit all of Entities::Project (roughly 80 fields) and append one. That is not the narrowing the style guide asks for. The style guide's own example goes from UserBasic (212 endpoints) down to a narrow Ci::JobOwner used by one endpoint. Subclassing the full project entity satisfies the cop by file topology while changing nothing about the actual exposure surface.
  • The leaf classes such a subclass would extend, Projects::WithCatalogSetting and Projects::WithAccessAndCatalogSetting, are a cross product of access variant times feature concern. One concern already produces two classes; a second concern produces four. Their names also describe a single field each, which is the naming shape doc/development/api_styleguide.md:133 explicitly warns against.
  • Cost of the direct exposure: no extra query. :project_setting is already preloaded by Entities::Project.preload_relation (lib/api/entities/project.rb:196), and the field is a non-null boolean column on project_settings defaulting to false. One extra boolean per serialized project.

Process note

doc/development/api_styleguide.md:157-166 says not to edit the baseline directly, and to open a discussion with the API Platform team when a field genuinely belongs on a high impact entity. This MR is the artifact for that discussion, so it should be reviewed by API Platform before merge. Note that /rubocop/ is owned by @gitlab-org/maintainers/rails-backend in .gitlab/CODEOWNERS:64, so the baseline edit does not route to API Platform automatically; that review needs to happen deliberately.

Alternative considered and rejected

A dedicated sub resource endpoint, GET/PUT /projects/:id/merge_request_settings, with its own narrow entity. This is the only genuinely feature-bounded option and matches the existing ee/lib/api/project_security_settings.rb and ee/lib/api/project_approval_settings.rb pattern (each about 90 lines). Roughly 14 merge request related settings on project_settings could eventually live there. Rejected for this MR because it is a new API surface, it does not satisfy the issue's requirement that GET /projects/:id return the field, and it is too large a decision to make inside a single boolean issue. Worth raising separately as the home for future merge request settings.

Downstream consumer

terraform-provider-gitlab#6883 wants to read the value so the attribute can be imported and drift-detected. Related provider MR: terraform-provider-gitlab!3254.

Not in scope

  • Accepting the parameter on POST /projects. It stays ignored on create, and the existing spec asserting this is kept.
  • GraphQL exposure. No GraphQL field exists for this setting today; #519390 (closed) proposed one and it was never implemented.
  • Anonymous requests to GET /projects/:id are served by Entities::ProjectDetails, a different entity chain, so unauthenticated callers still do not get the field.

Files changed

  • lib/api/entities/project.rb: the exposure, one line, expose :automatic_rebase_enabled, documentation: { type: 'Boolean' }.
  • rubocop/cop/api/config/api_entity_exposure_baseline.yml: the field added to the lib/api/entities/project.rb allowlist, one line.
  • doc/api/projects.md: a response attribute table row in the four read sections (Retrieve a project, List all projects, List all personal projects for a user, List all projects contributions for a user), plus a version history note in each.
  • doc/api/openapi/openapi_v3.yaml: regenerated with bundle exec rake gitlab:openapi:v3:generate.
  • spec/requests/api/projects_spec.rb: the PUT spec assertion changed from expect(json_response).not_to have_key('automatic_rebase_enabled') to asserting it returns true; a read assertion added to the GET /projects/:id example; the POST ignore spec extended to assert the response returns false.

Verification performed

  • bundle exec rubocop --only API/EntityExposureGrowth lib/api/entities/project.rb: no offenses.
  • bundle exec rubocop lib/api/entities/project.rb spec/requests/api/projects_spec.rb: no offenses.
  • bundle exec rspec on the three touched examples: 3 examples, 0 failures.
  • vale and markdownlint-cli2 on doc/api/projects.md: clean.
  • The regenerated OpenAPI diff contains only the three expected automatic_rebase_enabled: type: boolean additions.

Merge request reports

Loading
Loading