Filter cdEnvironments by tier

What does this MR do and why?

Add an optional tier: CdEnvironmentTier argument to Organization.cdEnvironments. When provided, the resolver scopes the result to environments matching that tier. When omitted, all environments in the organization are returned (mirroring the "All types" tab on the environments page).

Behind the ai_native_deploy feature flag (default off), authorized by :read_cd_environment on the organization. Same gate as the existing field.

Database

The resolver composes Cd::Environment.in_organization with the new Cd::Environment.with_tier scope. When the tier argument is provided, the query is:

SELECT cd_environments.*
FROM cd_environments
WHERE cd_environments.organization_id = $1
  AND cd_environments.tier = $2
ORDER BY cd_environments.id DESC
LIMIT 101;

Query plan: https://console.postgres.ai/gitlab/projects/gitlab-production-main/sessions/53279/commands/155255. Note that the CD feature is still being built, and the CD-related tables don't have any data in production yet.

References

Screenshots or screen recordings

Scenario Screenshot
cdEnvironments with no filter Screenshot_2026-06-29_at_11.41.05_am
cdEnvironments with tier filter Screenshot_2026-06-29_at_11.41.31_am

How to set up and validate locally

  1. Enable the ai_native_deploy feature flag.

  2. Sign in as an organization owner and create environments across two tiers:

    mutation {
      cdEnvironmentCreate(input: {
        organizationId: "gid://gitlab/Organizations::Organization/1",
        name: "Production",
        tier: PRODUCTION
      }) {
        environment { id name tier }
        errors
      }
    }
    mutation {
      cdEnvironmentCreate(input: {
        organizationId: "gid://gitlab/Organizations::Organization/1",
        name: "Staging",
        tier: STAGING
      }) {
        environment { id name tier }
        errors
      }
    }
  3. Query the list with no filter to confirm both environments come back:

    query {
      organization(id: "gid://gitlab/Organizations::Organization/1") {
        cdEnvironments {
          nodes { name tier }
        }
      }
    }
  4. Query the list with the tier filter and confirm only the matching env comes back:

    query {
      organization(id: "gid://gitlab/Organizations::Organization/1") {
        cdEnvironments(tier: PRODUCTION) {
          nodes { name tier }
        }
      }
    }
  5. Confirm the field is gated:

    • Disable ai_native_deploycdEnvironments returns null.
    • Query as a non-owner organization member → cdEnvironments returns null.

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.

Edited by Agnes Slota

Merge request reports

Loading