Chen Zhang activity https://gitlab.com/chen-gitlab 2026-03-17T12:08:19Z tag:gitlab.com,2026-03-17:5212525499 Chen Zhang pushed to project branch main at GitLab.com / GitLab Infrastructure Team / GitLab Tenant Scale / Organizations team / Cells Progress Tracker 2026-03-17T12:08:19Z chen-gitlab Chen Zhang

Chen Zhang (4e7d5fd3) at 17 Mar 12:08

Changes to table growth

tag:gitlab.com,2026-03-17:5210582704 Chen Zhang commented on epic #1866 at GitLab.com / GitLab Infrastructure Team 2026-03-17T01:11:19Z chen-gitlab Chen Zhang

🕐 total hours spent this week by all contributors: 12

🎉 achievements:

blockers:

▶️ next:

  • Address review feedback on Steps 1-2 MRs
  • Begin gitlab-org/gitlab#591691 (Step 4: GraphQL mutation enforcement) — the last remaining in-scope POC task
  • As an alternative to the middleware approach, create an EnforcesNamespaceReadOnly concern (similar to the existing EnforcesStepUpAuthenticationForNamespace) and include it in Groups::ApplicationController and Projects::ApplicationController as a before_action - this is being discussed
  • Target completing the full POC (all 4 steps) by end of milestone 18.11
tag:gitlab.com,2026-03-16:5210065851 Chen Zhang commented on merge request !227517 at GitLab.org / GitLab 2026-03-16T20:57:40Z chen-gitlab Chen Zhang

Some minor nits, the rest LGTM

tag:gitlab.com,2026-03-16:5210065341 Chen Zhang approved merge request !227517: Don't stub Current.organization in request specs at GitLab.org / GitLab 2026-03-16T20:57:28Z chen-gitlab Chen Zhang

What does this MR do and why?

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.

References

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

tag:gitlab.com,2026-03-16:5210065146 Chen Zhang commented on merge request !227517 at GitLab.org / GitLab 2026-03-16T20:57:23Z chen-gitlab Chen Zhang

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

tag:gitlab.com,2026-03-16:5210060777 Chen Zhang commented on merge request !227517 at GitLab.org / GitLab 2026-03-16T20:55:38Z chen-gitlab Chen Zhang

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

tag:gitlab.com,2026-03-16:5210039056 Chen Zhang commented on merge request !226921 at GitLab.org / GitLab 2026-03-16T20:46:45Z chen-gitlab Chen Zhang

Thanks @rutgerwessels, good catch!

It seems to me that this MR would be effectively blocked by #558544?

tag:gitlab.com,2026-03-16:5210020025 Chen Zhang commented on merge request !226983 at GitLab.org / GitLab 2026-03-16T20:41:13Z chen-gitlab Chen Zhang

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:

  • Rails controllers: 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
  • Grape API: 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:

  1. Create an 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.
  2. For Grape, add the maintenance check in 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.

tag:gitlab.com,2026-03-14:5203651515 Chen Zhang pushed to project branch main at GitLab.com / GitLab Infrastructure Team / GitLab Tenant Scale / Organizations team / Cells Progress Tracker 2026-03-14T07:06:33Z chen-gitlab Chen Zhang

Chen Zhang (b6923ef2) at 14 Mar 07:06

Changes to table growth

tag:gitlab.com,2026-03-13:5202797168 Chen Zhang opened merge request !227343: Add namespace maintenance error page (Step 3) at GitLab.org / GitLab 2026-03-13T19:58:42Z chen-gitlab Chen Zhang

What does this MR do and why?

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)

Changes

Static error page (public/-/errors/namespace_maintenance.html)

  • Self-contained HTML page modeled on public/503.html styling
  • Uses the existing error-503-lg.svg illustration
  • Clear messaging: "This group is temporarily in maintenance mode"
  • Explains that write operations are disabled but reads still work
  • Includes "Go back" link (shown when browser history is available)

Middleware update (lib/gitlab/middleware/namespace_read_only/controller.rb)

  • HTML requests: Now return 503 with the static error page body instead of 302 redirect + flash
  • JSON requests: Unchanged (503 + JSON body + Retry-After header)
  • Both paths include Retry-After: 900 header
  • Added structured logging (Gitlab::AppLogger.warn) when write requests are blocked
  • Extracted json_maintenance_response and html_maintenance_response for clarity

Specs (spec/lib/gitlab/middleware/namespace_read_only_spec.rb)

  • Updated all HTML response expectations from 302 to 503
  • Added assertions for Content-Type, Content-Length, Retry-After headers
  • Added spec for error page content rendering
  • Added spec for Git LFS JSON requests
  • Added spec for structured logging
  • Added negative assertion ensuring JSON responses don't contain HTML

Design decisions

  • Static HTML (not HAML): Rack middleware runs before Rails controllers, so the view layer is not available. This matches the existing pattern used by public/503.html, public/404.html, etc.
  • 503 instead of 302: A proper 503 status code correctly signals to clients (browsers, API consumers, crawlers) that the service is temporarily unavailable, rather than a redirect which implies the resource moved.
  • Retry-After on both HTML and JSON: Helps automated clients know when to retry.
  • Placed in public/-/errors/: Follows the convention of public/ for static error pages, namespaced under -/errors/ to avoid path conflicts with user namespaces.

How to set up and validate locally

  1. Apply Steps 1 and 2 changes first (!226399, !226983)
  2. Open Rails console
  3. Put a namespace in maintenance: ns = Namespace.find_by_path('my-group'); ns.update_column(:state, 6)
  4. Try a write request (e.g., create an issue in that group) - should see the maintenance error page
  5. Try a read request (e.g., view the group page) - should work normally
  6. Try an API write request with Content-Type: application/json - should get JSON 503 response

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

tag:gitlab.com,2026-03-13:5202777940 Chen Zhang pushed new project branch namespace-maintenance-error-page-step3 at GitLab.org / GitLab 2026-03-13T19:51:32Z chen-gitlab Chen Zhang

Chen Zhang (b9e9ccf6) at 13 Mar 19:51

Add namespace maintenance error page (Step 3)

... and 11 more commits

tag:gitlab.com,2026-03-13:5202666074 Chen Zhang commented on issue #590009 at GitLab.org / GitLab 2026-03-13T19:06:54Z chen-gitlab Chen Zhang

Progress update (2026-03-13):

Steps 1 and 2 are code-complete with green pipelines and ready for review:

  • !226399 (Step 1: State machine transitions) — Pipeline green, awaiting review
  • !226983 (Step 2: Namespace-scoped read-only middleware) — Pipeline green, mergeable, awaiting review

Remaining work:

  • #591690 — Step 3: Web UI error page (ready to start, depends on Step 1)
  • #591691 — Step 4: GraphQL mutation enforcement (ready to start, depends on Step 1)

Steps 3 and 4 can be worked on in parallel. Ready to begin either once review feedback on Steps 1-2 is addressed.

tag:gitlab.com,2026-03-13:5202658178 Chen Zhang commented on merge request !226983 at GitLab.org / GitLab 2026-03-13T19:03:45Z chen-gitlab Chen Zhang

@abdwdd can you review this please

tag:gitlab.com,2026-03-13:5202152556 Chen Zhang pushed to project branch duo-edit-20260304-221838 at GitLab.org / GitLab 2026-03-13T16:17:34Z chen-gitlab Chen Zhang

Chen Zhang (08d37267) at 13 Mar 16:17

Fix: conditionally pass organization_id in NotesChannel

tag:gitlab.com,2026-03-13:5201887433 Chen Zhang pushed to project branch namespace-read-only-middleware-step2 at GitLab.org / GitLab 2026-03-13T15:12:00Z chen-gitlab Chen Zhang

Chen Zhang (203a7055) at 13 Mar 15:12

Fix namespace resolution for URL-encoded paths and nil session guard

tag:gitlab.com,2026-03-13:5201845654 Chen Zhang pushed to project branch duo-edit-20260304-221838 at GitLab.org / GitLab 2026-03-13T15:02:23Z chen-gitlab Chen Zhang

Chen Zhang (ed9a2a8d) at 13 Mar 15:02

Ensure default organization exists in real-time notes feature spec

tag:gitlab.com,2026-03-13:5201794092 Chen Zhang pushed to project branch namespace-read-only-middleware-step2 at GitLab.org / GitLab 2026-03-13T14:51:51Z chen-gitlab Chen Zhang

Chen Zhang (0203d144) at 13 Mar 14:51

Fix RSpec described_class scoping and RuboCop offenses

tag:gitlab.com,2026-03-13:5201760522 Chen Zhang commented on merge request !226921 at GitLab.org / GitLab 2026-03-13T14:44:13Z chen-gitlab Chen Zhang

@rutgerwessels Could you review this please

tag:gitlab.com,2026-03-12:5198465104 Chen Zhang pushed to project branch main at GitLab.com / GitLab Infrastructure Team / GitLab Tenant Scale / Organizations team / Cells Progress Tracker 2026-03-12T19:08:14Z chen-gitlab Chen Zhang

Chen Zhang (f85af1ea) at 12 Mar 19:08

Changes to table growth

tag:gitlab.com,2026-03-12:5195117462 Chen Zhang commented on merge request !226921 at GitLab.org / GitLab 2026-03-12T05:06:14Z chen-gitlab Chen Zhang

Verification: test fails without the application code change

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.