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_settingstable 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_optionandmerge_method(same file), and on the EE sideweb_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) andreviewer_assignment_strategy(ee/lib/ee/api/entities/project.rb:70).automatic_rebase_enabledis 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 fromUserBasic(212 endpoints) down to a narrowCi::JobOwnerused 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::WithCatalogSettingandProjects::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_settingis already preloaded byEntities::Project.preload_relation(lib/api/entities/project.rb:196), and the field is a non-null boolean column onproject_settingsdefaulting 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/:idare served byEntities::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 thelib/api/entities/project.rballowlist, 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 withbundle exec rake gitlab:openapi:v3:generate.spec/requests/api/projects_spec.rb: thePUTspec assertion changed fromexpect(json_response).not_to have_key('automatic_rebase_enabled')to asserting it returns true; a read assertion added to theGET /projects/:idexample; thePOSTignore 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 rspecon the three touched examples: 3 examples, 0 failures.valeandmarkdownlint-cli2ondoc/api/projects.md: clean.- The regenerated OpenAPI diff contains only the three expected
automatic_rebase_enabled: type: booleanadditions.