diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-11-28 15:10:10 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-11-28 15:10:10 +0300 |
commit | 22fd199237e247c36de5b982d444cedc194126e6 (patch) | |
tree | 1a5ad68a1dffdf37dfae0d1267bf3bcc04c292cb /app | |
parent | 97b93f6d05b26e57a4d6a6d33a46aacb5f3235a6 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
17 files changed, 211 insertions, 88 deletions
diff --git a/app/assets/javascripts/ci_variable_list/components/ci_group_variables.vue b/app/assets/javascripts/ci_variable_list/components/ci_group_variables.vue index c8f5ac1736d..4466a6a8081 100644 --- a/app/assets/javascripts/ci_variable_list/components/ci_group_variables.vue +++ b/app/assets/javascripts/ci_variable_list/components/ci_group_variables.vue @@ -46,6 +46,7 @@ export default { :id="graphqlId" :are-scoped-variables-available="areScopedVariablesAvailable" component-name="GroupVariables" + entity="group" :full-path="groupPath" :mutation-data="$options.mutationData" :query-data="$options.queryData" diff --git a/app/assets/javascripts/ci_variable_list/components/ci_project_variables.vue b/app/assets/javascripts/ci_variable_list/components/ci_project_variables.vue index 2c4818e20c1..6326940148a 100644 --- a/app/assets/javascripts/ci_variable_list/components/ci_project_variables.vue +++ b/app/assets/javascripts/ci_variable_list/components/ci_project_variables.vue @@ -48,6 +48,7 @@ export default { :id="graphqlId" :are-scoped-variables-available="true" component-name="ProjectVariables" + entity="project" :full-path="projectFullPath" :mutation-data="$options.mutationData" :query-data="$options.queryData" diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_settings.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_settings.vue index 94fd6c3892c..3c6114b38ce 100644 --- a/app/assets/javascripts/ci_variable_list/components/ci_variable_settings.vue +++ b/app/assets/javascripts/ci_variable_list/components/ci_variable_settings.vue @@ -14,6 +14,11 @@ export default { required: false, default: false, }, + entity: { + type: String, + required: false, + default: '', + }, environments: { type: Array, required: false, @@ -27,7 +32,11 @@ export default { isLoading: { type: Boolean, required: false, - default: false, + }, + maxVariableLimit: { + type: Number, + required: false, + default: 0, }, variables: { type: Array, @@ -75,7 +84,9 @@ export default { <div class="row"> <div class="col-lg-12"> <ci-variable-table + :entity="entity" :is-loading="isLoading" + :max-variable-limit="maxVariableLimit" :variables="variables" @set-selected-variable="setSelectedVariable" /> diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_shared.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_shared.vue index 7ee250cea98..6e39bda0b07 100644 --- a/app/assets/javascripts/ci_variable_list/components/ci_variable_shared.vue +++ b/app/assets/javascripts/ci_variable_list/components/ci_variable_shared.vue @@ -26,6 +26,11 @@ export default { required: true, type: String, }, + entity: { + required: false, + type: String, + default: '', + }, fullPath: { required: false, type: String, @@ -90,6 +95,7 @@ export default { isInitialLoading: true, isLoadingMoreItems: false, loadingCounter: 0, + maxVariableLimit: 0, pageInfo: {}, }; }, @@ -107,6 +113,8 @@ export default { return this.queryData.ciVariables.lookup(data)?.nodes || []; }, result({ data }) { + this.maxVariableLimit = this.queryData.ciVariables.lookup(data)?.limit || 0; + this.pageInfo = this.queryData.ciVariables.lookup(data)?.pageInfo || this.pageInfo; this.hasNextPage = this.pageInfo?.hasNextPage || false; @@ -221,9 +229,11 @@ export default { <template> <ci-variable-settings :are-scoped-variables-available="areScopedVariablesAvailable" + :entity="entity" :hide-environment-scope="hideEnvironmentScope" :is-loading="isLoading" :variables="ciVariables" + :max-variable-limit="maxVariableLimit" :environments="environments" @add-variable="addVariable" @delete-variable="deleteVariable" diff --git a/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue b/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue index 3cdcb68e919..b933586be84 100644 --- a/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue +++ b/app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue @@ -1,8 +1,21 @@ <script> -import { GlButton, GlLoadingIcon, GlModalDirective, GlTable, GlTooltipDirective } from '@gitlab/ui'; -import { s__, __ } from '~/locale'; +import { + GlAlert, + GlButton, + GlLoadingIcon, + GlModalDirective, + GlTable, + GlTooltipDirective, +} from '@gitlab/ui'; +import { __, s__, sprintf } from '~/locale'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; -import { ADD_CI_VARIABLE_MODAL_ID, variableText } from '../constants'; +import { + ADD_CI_VARIABLE_MODAL_ID, + DEFAULT_EXCEEDS_VARIABLE_LIMIT_TEXT, + EXCEEDS_VARIABLE_LIMIT_TEXT, + MAXIMUM_VARIABLE_LIMIT_REACHED, + variableText, +} from '../constants'; import { convertEnvironmentScope } from '../utils'; export default { @@ -41,6 +54,7 @@ export default { }, ], components: { + GlAlert, GlButton, GlLoadingIcon, GlTable, @@ -51,10 +65,19 @@ export default { }, mixins: [glFeatureFlagsMixin()], props: { + entity: { + type: String, + required: false, + default: '', + }, isLoading: { type: Boolean, required: true, }, + maxVariableLimit: { + type: Number, + required: true, + }, variables: { type: Array, required: true, @@ -66,6 +89,23 @@ export default { }; }, computed: { + exceedsVariableLimit() { + return this.maxVariableLimit > 0 && this.variables.length >= this.maxVariableLimit; + }, + exceedsVariableLimitText() { + if (this.exceedsVariableLimit && this.entity) { + return sprintf(EXCEEDS_VARIABLE_LIMIT_TEXT, { + entity: this.entity, + currentVariableCount: this.variables.length, + maxVariableLimit: this.maxVariableLimit, + }); + } + + return DEFAULT_EXCEEDS_VARIABLE_LIMIT_TEXT; + }, + showAlert() { + return !this.isLoading && this.exceedsVariableLimit; + }, valuesButtonText() { return this.areValuesHidden ? __('Reveal values') : __('Hide values'); }, @@ -107,14 +147,23 @@ export default { return options.join(', '); }, }, + maximumVariableLimitReached: MAXIMUM_VARIABLE_LIMIT_REACHED, }; </script> <template> <div class="ci-variable-table" data-testid="ci-variable-table"> <gl-loading-icon v-if="isLoading" /> + <gl-alert + v-if="showAlert" + :dismissible="false" + :title="$options.maximumVariableLimitReached" + variant="info" + > + {{ exceedsVariableLimitText }} + </gl-alert> <gl-table - v-else + v-if="!isLoading" :fields="fields" :items="variablesWithOptions" tbody-tr-class="js-ci-variable-row" @@ -215,6 +264,14 @@ export default { </p> </template> </gl-table> + <gl-alert + v-if="showAlert" + :dismissible="false" + :title="$options.maximumVariableLimitReached" + variant="info" + > + {{ exceedsVariableLimitText }} + </gl-alert> <div class="ci-variable-actions gl-display-flex gl-mt-5"> <gl-button v-gl-modal-directive="$options.modalId" @@ -223,6 +280,7 @@ export default { variant="confirm" category="primary" :aria-label="__('Add')" + :disabled="exceedsVariableLimit" @click="setSelectedVariable()" >{{ __('Add variable') }}</gl-button > diff --git a/app/assets/javascripts/ci_variable_list/constants.js b/app/assets/javascripts/ci_variable_list/constants.js index ccad08ef8b6..10dcf168be8 100644 --- a/app/assets/javascripts/ci_variable_list/constants.js +++ b/app/assets/javascripts/ci_variable_list/constants.js @@ -1,4 +1,4 @@ -import { __ } from '~/locale'; +import { __, s__ } from '~/locale'; export const ADD_CI_VARIABLE_MODAL_ID = 'add-ci-variable'; @@ -73,6 +73,15 @@ export const CONTAINS_VARIABLE_REFERENCE_MESSAGE = __( ); export const ENVIRONMENT_SCOPE_LINK_TITLE = __('Learn more'); +export const EXCEEDS_VARIABLE_LIMIT_TEXT = s__( + 'CiVariables|This %{entity} has %{currentVariableCount} defined CI/CD variables. The maximum number of variables per %{entity} is %{maxVariableLimit}. To add new variables, you must reduce the number of defined variables.', +); +export const DEFAULT_EXCEEDS_VARIABLE_LIMIT_TEXT = s__( + 'CiVariables|You have reached the maximum number of variables available. To add new variables, you must reduce the number of defined variables.', +); +export const MAXIMUM_VARIABLE_LIMIT_REACHED = s__( + 'CiVariables|Maximum number of variables reached.', +); export const ADD_VARIABLE_ACTION = 'ADD_VARIABLE'; export const EDIT_VARIABLE_ACTION = 'EDIT_VARIABLE'; diff --git a/app/assets/javascripts/ci_variable_list/graphql/queries/group_variables.query.graphql b/app/assets/javascripts/ci_variable_list/graphql/queries/group_variables.query.graphql index b5555fe4401..67ed0a6cace 100644 --- a/app/assets/javascripts/ci_variable_list/graphql/queries/group_variables.query.graphql +++ b/app/assets/javascripts/ci_variable_list/graphql/queries/group_variables.query.graphql @@ -5,6 +5,7 @@ query getGroupVariables($after: String, $first: Int = 100, $fullPath: ID!) { group(fullPath: $fullPath) { id ciVariables(after: $after, first: $first) { + limit pageInfo { ...PageInfo } diff --git a/app/assets/javascripts/ci_variable_list/graphql/queries/project_variables.query.graphql b/app/assets/javascripts/ci_variable_list/graphql/queries/project_variables.query.graphql index 08b5bf7af16..1bce065868e 100644 --- a/app/assets/javascripts/ci_variable_list/graphql/queries/project_variables.query.graphql +++ b/app/assets/javascripts/ci_variable_list/graphql/queries/project_variables.query.graphql @@ -5,6 +5,7 @@ query getProjectVariables($after: String, $first: Int = 100, $fullPath: ID!) { project(fullPath: $fullPath) { id ciVariables(after: $after, first: $first) { + limit pageInfo { ...PageInfo } diff --git a/app/assets/javascripts/integrations/edit/components/integration_form.vue b/app/assets/javascripts/integrations/edit/components/integration_form.vue index 881752b018e..3471c1746a9 100644 --- a/app/assets/javascripts/integrations/edit/components/integration_form.vue +++ b/app/assets/javascripts/integrations/edit/components/integration_form.vue @@ -128,6 +128,14 @@ export default { } return !this.hasSections && this.helpHtml; }, + shouldUpgradeSlack() { + return ( + this.isSlackIntegration && + this.glFeatures.integrationSlackAppNotifications && + this.customState.shouldUpgradeSlack && + (this.hasFieldsWithoutSection || this.hasSections) + ); + }, }, methods: { ...mapActions(['setOverride', 'requestJiraIssueTypes']), @@ -278,16 +286,18 @@ export default { </div> </section> + <div v-if="shouldUpgradeSlack" class="gl-border-t"> + <gl-alert + :dismissible="false" + :title="$options.slackUpgradeInfo.title" + variant="warning" + :primary-button-link="customState.upgradeSlackUrl" + :primary-button-text="$options.slackUpgradeInfo.btnText" + class="gl-mb-8 gl-mt-5" + /> + </div> + <template v-if="hasSections"> - <div v-if="customState.shouldUpgradeSlack && isSlackIntegration" class="gl-border-t"> - <gl-alert - :title="$options.slackUpgradeInfo.title" - variant="warning" - :primary-button-link="customState.upgradeSlackUrl" - :primary-button-text="$options.slackUpgradeInfo.btnText" - class="gl-mb-8 gl-mt-5" - /> - </div> <div v-for="(section, index) in customState.sections" :key="section.type" diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb index b1afac1f1c7..1dfa8cdf133 100644 --- a/app/controllers/groups/settings/ci_cd_controller.rb +++ b/app/controllers/groups/settings/ci_cd_controller.rb @@ -15,6 +15,8 @@ module Groups urgency :low def show + @entity = :group + @variable_limit = ::Plan.default.actual_limits.group_ci_variables end def update diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index a545c2e5b3c..cf07de4dc29 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -18,6 +18,9 @@ module Projects urgency :low def show + @entity = :project + @variable_limit = ::Plan.default.actual_limits.project_ci_variables + if Feature.enabled?(:ci_pipeline_triggers_settings_vue_ui, @project) triggers = ::Ci::TriggerSerializer.new.represent( @project.triggers, current_user: current_user, project: @project diff --git a/app/models/concerns/counter_attribute.rb b/app/models/concerns/counter_attribute.rb index 03e062a9855..4dfaae674bf 100644 --- a/app/models/concerns/counter_attribute.rb +++ b/app/models/concerns/counter_attribute.rb @@ -17,6 +17,18 @@ # counter_attribute :storage_size # end # +# It's possible to define a conditional counter attribute. You need to pass a proc +# that must accept a single argument, the object instance on which this concern is +# included. +# +# @example: +# +# class ProjectStatistics +# include CounterAttribute +# +# counter_attribute :conditional_one, if: -> { |object| object.use_counter_attribute? } +# end +# # To increment the counter we can use the method: # delayed_increment_counter(:commit_count, 3) # @@ -49,12 +61,15 @@ module CounterAttribute WORKER_LOCK_TTL = 10.minutes class_methods do - def counter_attribute(attribute) - counter_attributes << attribute + def counter_attribute(attribute, if: nil) + counter_attributes << { + attribute: attribute, + if_proc: binding.local_variable_get(:if) # can't read `if` directly + } end def counter_attributes - @counter_attributes ||= Set.new + @counter_attributes ||= [] end def after_flush_callbacks @@ -65,10 +80,14 @@ module CounterAttribute def counter_attribute_after_flush(&callback) after_flush_callbacks << callback end + end - def counter_attribute_enabled?(attribute) - counter_attributes.include?(attribute) - end + def counter_attribute_enabled?(attribute) + counter_attribute = self.class.counter_attributes.find { |registered| registered[:attribute] == attribute } + return false unless counter_attribute + return true unless counter_attribute[:if_proc] + + counter_attribute[:if_proc].call(self) end # This method must only be called by FlushCounterIncrementsWorker @@ -167,10 +186,6 @@ module CounterAttribute counter_key(attribute) + ':lock' end - def counter_attribute_enabled?(attribute) - self.class.counter_attribute_enabled?(attribute) - end - private def database_lock_key diff --git a/app/models/integrations/base_chat_notification.rb b/app/models/integrations/base_chat_notification.rb index c7ab9befd12..78d7dc60ed9 100644 --- a/app/models/integrations/base_chat_notification.rb +++ b/app/models/integrations/base_chat_notification.rb @@ -108,15 +108,13 @@ module Integrations end def execute(data) - return unless supported_events.include?(data[:object_kind]) - - return unless webhook.present? - object_kind = data[:object_kind] + return false unless should_execute?(object_kind) + data = custom_data(data) - return unless notify_label?(data) + return false unless notify_label?(data) # WebHook events often have an 'update' event that follows a 'open' or # 'close' action. Ignore update events for now to prevent duplicate @@ -182,6 +180,11 @@ module Integrations private + def should_execute?(object_kind) + supported_events.include?(object_kind) && + (!requires_webhook? || webhook.present?) + end + def log_usage(_, _) # Implement in child class end diff --git a/app/models/project_statistics.rb b/app/models/project_statistics.rb index 0570be85ad1..fb0ad178c91 100644 --- a/app/models/project_statistics.rb +++ b/app/models/project_statistics.rb @@ -11,6 +11,7 @@ class ProjectStatistics < ApplicationRecord attribute :snippets_size, default: 0 counter_attribute :build_artifacts_size + counter_attribute :packages_size, if: -> (statistics) { Feature.enabled?(:packages_size_counter_attribute, statistics.project) } counter_attribute_after_flush do |project_statistic| project_statistic.refresh_storage_size! @@ -22,7 +23,7 @@ class ProjectStatistics < ApplicationRecord COLUMNS_TO_REFRESH = [:repository_size, :wiki_size, :lfs_objects_size, :commit_count, :snippets_size, :uploads_size, :container_registry_size].freeze INCREMENTABLE_COLUMNS = { - packages_size: %i[storage_size], + packages_size: %i[storage_size], # remove this along with packages_size_counter_attribute pipeline_artifacts_size: %i[storage_size], snippets_size: %i[storage_size] }.freeze @@ -124,20 +125,20 @@ class ProjectStatistics < ApplicationRecord # # For non-counter attributes, storage_size is updated depending on key => [columns] in INCREMENTABLE_COLUMNS def self.increment_statistic(project, key, amount) - raise ArgumentError, "Cannot increment attribute: #{key}" unless incrementable_attribute?(key) - return if amount == 0 - project.statistics.try do |project_statistics| - if counter_attribute_enabled?(key) - project_statistics.delayed_increment_counter(key, amount) - else - project_statistics.legacy_increment_statistic(key, amount) - end + project_statistics.increment_statistic(key, amount) end end - def self.incrementable_attribute?(key) - INCREMENTABLE_COLUMNS.key?(key) || counter_attribute_enabled?(key) + def increment_statistic(key, amount) + raise ArgumentError, "Cannot increment attribute: #{key}" unless incrementable_attribute?(key) + return if amount == 0 + + if counter_attribute_enabled?(key) + delayed_increment_counter(key, amount) + else + legacy_increment_statistic(key, amount) + end end def legacy_increment_statistic(key, amount) @@ -149,6 +150,10 @@ class ProjectStatistics < ApplicationRecord private + def incrementable_attribute?(key) + INCREMENTABLE_COLUMNS.key?(key) || counter_attribute_enabled?(key) + end + def storage_size_components STORAGE_SIZE_COMPONENTS end diff --git a/app/services/event_create_service.rb b/app/services/event_create_service.rb index 662980fe506..03a3c962752 100644 --- a/app/services/event_create_service.rb +++ b/app/services/event_create_service.rb @@ -10,6 +10,10 @@ class EventCreateService IllegalActionError = Class.new(StandardError) + DEGIGN_EVENT_LABEL = 'usage_activity_by_stage_monthly.create.action_monthly_active_users_design_management' + MR_EVENT_LABEL = 'usage_activity_by_stage_monthly.create.merge_requests_users' + MR_EVENT_PROPERTY = 'merge_requests_users' + def open_issue(issue, current_user) create_record_event(issue, current_user, :created) end @@ -26,9 +30,11 @@ class EventCreateService create_record_event(merge_request, current_user, :created).tap do track_event(event_action: :created, event_target: MergeRequest, author_id: current_user.id) track_snowplow_event( - :created, - merge_request, - current_user + action: :created, + project: merge_request.project, + user: current_user, + label: MR_EVENT_LABEL, + property: MR_EVENT_PROPERTY ) end end @@ -37,9 +43,11 @@ class EventCreateService create_record_event(merge_request, current_user, :closed).tap do track_event(event_action: :closed, event_target: MergeRequest, author_id: current_user.id) track_snowplow_event( - :closed, - merge_request, - current_user + action: :closed, + project: merge_request.project, + user: current_user, + label: MR_EVENT_LABEL, + property: MR_EVENT_PROPERTY ) end end @@ -52,9 +60,11 @@ class EventCreateService create_record_event(merge_request, current_user, :merged).tap do track_event(event_action: :merged, event_target: MergeRequest, author_id: current_user.id) track_snowplow_event( - :merged, - merge_request, - current_user + action: :merged, + project: merge_request.project, + user: current_user, + label: MR_EVENT_LABEL, + property: MR_EVENT_PROPERTY ) end end @@ -80,11 +90,12 @@ class EventCreateService if note.is_a?(DiffNote) && note.for_merge_request? track_event(event_action: :commented, event_target: MergeRequest, author_id: current_user.id) track_snowplow_event( - :commented, - note, - current_user + action: :commented, + project: note.project, + user: current_user, + label: MR_EVENT_LABEL, + property: MR_EVENT_PROPERTY ) - end end end @@ -117,17 +128,10 @@ class EventCreateService records = create.zip([:created].cycle) + update.zip([:updated].cycle) return [] if records.empty? - if create.any? - old_track_snowplow_event(create.first, current_user, - Gitlab::UsageDataCounters::TrackUniqueEvents::DESIGN_ACTION, - :create, 'design_users') - end + event_meta = { user: current_user, label: DEGIGN_EVENT_LABEL, property: Gitlab::UsageDataCounters::TrackUniqueEvents::DESIGN_ACTION } + track_snowplow_event(action: :create, project: create.first.project, **event_meta) if create.any? - if update.any? - old_track_snowplow_event(update.first, current_user, - Gitlab::UsageDataCounters::TrackUniqueEvents::DESIGN_ACTION, - :update, 'design_users') - end + track_snowplow_event(action: :update, project: update.first.project, **event_meta) if update.any? create_record_events(records, current_user) end @@ -135,9 +139,13 @@ class EventCreateService def destroy_designs(designs, current_user) return [] unless designs.present? - old_track_snowplow_event(designs.first, current_user, - Gitlab::UsageDataCounters::TrackUniqueEvents::DESIGN_ACTION, - :destroy, 'design_users') + track_snowplow_event( + action: :destroy, + project: designs.first.project, + user: current_user, + label: DEGIGN_EVENT_LABEL, + property: Gitlab::UsageDataCounters::TrackUniqueEvents::DESIGN_ACTION + ) create_record_events(designs.zip([:destroyed].cycle), current_user) end @@ -270,33 +278,18 @@ class EventCreateService Gitlab::UsageDataCounters::TrackUniqueEvents.track_event(**params) end - # This will be deleted as a part of - # https://gitlab.com/groups/gitlab-org/-/epics/8641 - # once all the events are fixed - def old_track_snowplow_event(record, current_user, category, action, label) + def track_snowplow_event(action:, project:, user:, label:, property:) return unless Feature.enabled?(:route_hll_to_snowplow_phase2) - project = record.project - Gitlab::Tracking.event( - category.to_s, - action.to_s, - label: label, - project: project, - namespace: project.namespace, - user: current_user - ) - end - - def track_snowplow_event(action, record, user) - project = record.project Gitlab::Tracking.event( self.class.to_s, action.to_s, - label: 'usage_activity_by_stage_monthly.create.merge_requests_users', + label: label, namespace: project.namespace, user: user, project: project, - context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: 'merge_requests_users').to_context] + property: property.to_s, + context: [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: property.to_s).to_context] ) end end diff --git a/app/views/ci/variables/_content.html.haml b/app/views/ci/variables/_content.html.haml index b597c2d442a..97d96a50860 100644 --- a/app/views/ci/variables/_content.html.haml +++ b/app/views/ci/variables/_content.html.haml @@ -1,4 +1,4 @@ -= _('Variables store information, like passwords and secret keys, that you can use in job scripts.') += format(_('CiVariables|Variables store information, like passwords and secret keys, that you can use in job scripts. Each %{entity} can define a maximum of %{limit} variables.'), entity: entity, limit: variable_limit).html_safe = link_to s_('Learn more.'), help_page_path('ci/variables/index'), target: '_blank', rel: 'noopener noreferrer' %p = _('Variables can be:') diff --git a/app/views/ci/variables/_header.html.haml b/app/views/ci/variables/_header.html.haml index d6a9ce72d03..dfcf8f39533 100644 --- a/app/views/ci/variables/_header.html.haml +++ b/app/views/ci/variables/_header.html.haml @@ -7,4 +7,4 @@ = expanded ? _('Collapse') : _('Expand') %p - = render "ci/variables/content" + = render "ci/variables/content", entity: @entity, variable_limit: @variable_limit |