Enable "Masked and hidden" visibility option for instance-level CI/CD variables in Admin UI

Summary

The "Masked and hidden" visibility option is available for project-level and group-level CI/CD variables in the UI, but it is not available for instance-level variables in the Admin Area UI. However, the backend (REST API) already fully supports creating instance variables with masked_and_hidden=true.

This means the feature works via API but is intentionally disabled in the frontend for instance variables, creating an inconsistency.

Steps to reproduce

  1. Go to Admin Area > CI/CD > Variables
  2. Click Add variable
  3. Observe that the Visibility section only offers Visible and Masked, but not "Masked and hidden"

Compare with:

  1. Go to any Project > Settings > CI/CD > Variables
  2. Click Add variable
  3. The Visibility section correctly offers Visible, Masked, and Masked and hidden

Root cause

In ci_variable_shared.vue (line ~165):

areHiddenVariablesAvailable() {
  // group and project variables can be hidden, instance variables cannot
  return Boolean(this.entity);
},

The entity prop is not set by ci_admin_variables.vue, so it defaults to an empty string '', causing Boolean('') to return false. This hides the "Masked and hidden" radio button in the variable drawer.

Backend already supports this

Creating a masked and hidden instance variable via the API works without issues:

curl --request POST \
  --header "PRIVATE-TOKEN: <admin-token>" \
  "https://gitlab.example.com/api/v4/admin/ci/variables" \
  --form "key=MY_SECRET_KEY" \
  --form "value=my-secret-value" \
  --form "masked_and_hidden=true"

This confirms that the database schema, model validations, and API layer are all ready for instance-level hidden variables.

Proposed fix

Option A — Set the entity prop in ci_admin_variables.vue:

  <ci-variable-shared
      :are-scoped-variables-available="false"
      component-name="InstanceVariables"
+     entity="instance"
      :hide-environment-scope="true"
      :mutation-data="$options.mutationData"
      :refetch-after-mutation="true"
      :query-data="$options.queryData"
  />

Option B — Decouple the logic in ci_variable_shared.vue so it no longer uses entity as a proxy:

  areHiddenVariablesAvailable() {
-   // group and project variables can be hidden, instance variables cannot
-   return Boolean(this.entity);
+   return true;
  },

Both options are minimal changes. Option A may be preferred as it also makes the entity prop consistent across all variable components.

  • #29674 (closed) (Frontend: Add "Masked and hidden" option — explicitly scoped out instance variables)
  • #390305 (closed) (Backend: Create database column for hidden variables — completed)

Environment

Reproducible on GitLab Self-Managed (tested on 18.8) and confirmed by reading the current master branch source code.

Edited by 🤖 GitLab Bot 🤖