Chen Zhang (4e7d5fd3) at 17 Mar 12:08
Changes to table growth
maintenance state) — pipeline passing, in review by @abdwdd
EnforcesNamespaceReadOnly concern (similar to the existing EnforcesStepUpAuthenticationForNamespace) and include it in Groups::ApplicationController and Projects::ApplicationController as a before_action - this is being discussedSome minor nits, the rest LGTM
This MR reverts !221493
In !221493, I introduced a change that would stub Current.organization for all requests specs (Grape specs). But that can mask errors because the actual code does not always have a Current.organization: it needs to be enabled per API.
So we need this disable this for request specs until #558544 is delivered.
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Might be a good idea to also update doc/development/testing_guide/testing_with_organizations.md so that it's clearly reflecting request specs are now opt-in
I think the with_current_organization here along with a few others are redundant as we have it now on the top level block on line 5
Thanks @rutgerwessels, good catch!
It seems to me that this MR would be effectively blocked by #558544?
Thanks for the context, @rutgerwessels. That seems to be a big gap we are missing. After exploring the Organization resolution pattern, I think that moving to a controller-layer approach is the right direction here - both for consistency and for future Organization extensibility.
The Organization pattern works at two levels:
BaseActionController includes CurrentOrganization, and controllers call set_current_organization as a before_action after Rails routing has resolved params like namespace_id, group_id, id
API::Helpers defines set_current_organization, and individual API classes opt in via their before blocks. Grape has already parsed route params by that point.For namespace read-only enforcement, I'm planning to follow the same pattern:
EnforcesNamespaceReadOnly concern (similar to the existing EnforcesStepUpAuthenticationForNamespace) and include it in Groups::ApplicationController and Projects::ApplicationController as a before_action - the group/project is already loaded at that point.API::Helpers - potentially in find_group! / find_project! which are the central lookup methods all Grape endpoints already use, or as a dedicated helper called from before blocks.This eliminates the brittle PATH_PREFIXES / route_hash parsing from the middleware approach, and naturally extends to Organizations since it uses the same injection points and pattern.
@abdwdd does this direction align with what you had in mind? If so I'll draft a new work plan for this updated PoC, scratching the middleware approach.
Chen Zhang (b6923ef2) at 14 Mar 07:06
Changes to table growth
This MR implements Step 3 of the POC for read-only mode for top-level groups, as tracked in #590009 (task #591690).
It replaces the flash+redirect approach for HTML requests in the namespace read-only middleware with a proper 503 error page that clearly communicates the maintenance state to users.
Depends on: !226983 (Step 2 - namespace-scoped read-only middleware)
public/-/errors/namespace_maintenance.html)
public/503.html stylingerror-503-lg.svg illustrationlib/gitlab/middleware/namespace_read_only/controller.rb)
Retry-After header)Retry-After: 900 headerGitlab::AppLogger.warn) when write requests are blockedjson_maintenance_response and html_maintenance_response for clarityspec/lib/gitlab/middleware/namespace_read_only_spec.rb)
Content-Type, Content-Length, Retry-After headerspublic/503.html, public/404.html, etc.Retry-After on both HTML and JSON: Helps automated clients know when to retry.public/-/errors/: Follows the convention of public/ for static error pages, namespaced under -/errors/ to avoid path conflicts with user namespaces.ns = Namespace.find_by_path('my-group'); ns.update_column(:state, 6)
Content-Type: application/json - should get JSON 503 responseEvaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Chen Zhang (b9e9ccf6) at 13 Mar 19:51
Add namespace maintenance error page (Step 3)
... and 11 more commits
Progress update (2026-03-13):
Steps 1 and 2 are code-complete with green pipelines and ready for review:
Remaining work:
Steps 3 and 4 can be worked on in parallel. Ready to begin either once review feedback on Steps 1-2 is addressed.
@abdwdd can you review this please
Chen Zhang (08d37267) at 13 Mar 16:17
Fix: conditionally pass organization_id in NotesChannel
Chen Zhang (203a7055) at 13 Mar 15:12
Fix namespace resolution for URL-encoded paths and nil session guard
Chen Zhang (ed9a2a8d) at 13 Mar 15:02
Ensure default organization exists in real-time notes feature spec
Chen Zhang (0203d144) at 13 Mar 14:51
Fix RSpec described_class scoping and RuboCop offenses
@rutgerwessels Could you review this please
Chen Zhang (f85af1ea) at 12 Mar 19:08
Changes to table growth
Following the same approach used in !225973 (merged), an integration-style test was added in spec/requests/api/notes_spec.rb that asserts NotesFinder receives organization_id when the REST API note endpoints are called.
Test passes with the application code change:
$ bundle exec rspec spec/requests/api/notes_spec.rb -e 'passes organization_id to NotesFinder'
1 example, 0 failures
Test fails without the application code change (after removing the finder_params[:organization_id] = Current.organization.id line):
$ sed -i '' '/finder_params\[:organization_id\] = Current.organization.id/d' lib/api/helpers/notes_helpers.rb
$ bundle exec rspec spec/requests/api/notes_spec.rb -e 'passes organization_id to NotesFinder'
Failures:
1) API::Notes organization_id propagation to NotesFinder passes organization_id to NotesFinder
Failure/Error: noteable = NotesFinder.new(current_user, params).target
#<NotesFinder (class)> received :new with unexpected arguments
expected: (#<User id:3 @user1>, hash_including(:organization_id=>1001))
got: (#<User id:3 @user1>, {:project=>#<Project id:2 namespace1/project-1>>,
:target_iid=>1, :target_type=>"issue"})
1 example, 1 failure
This confirms the code change is necessary and properly covered.