Commit c3c9032b authored by Lin Jen-Shin's avatar Lin Jen-Shin

Check if the feature is available

parent af207c15
...@@ -22,9 +22,9 @@ class Projects::VariablesController < Projects::ApplicationController ...@@ -22,9 +22,9 @@ class Projects::VariablesController < Projects::ApplicationController
end end
def create def create
@variable = Ci::Variable.new(variable_params) @variable = @project.variables.new(variable_params)
if @variable.valid? && @project.variables << @variable if @variable.save
flash[:notice] = 'Variables were successfully updated.' flash[:notice] = 'Variables were successfully updated.'
redirect_to namespace_project_settings_ci_cd_path(project.namespace, project) redirect_to namespace_project_settings_ci_cd_path(project.namespace, project)
else else
......
...@@ -18,6 +18,18 @@ module EE ...@@ -18,6 +18,18 @@ module EE
format: { with: ::Gitlab::Regex.environment_scope_regex, format: { with: ::Gitlab::Regex.environment_scope_regex,
message: ::Gitlab::Regex.environment_scope_regex_message } message: ::Gitlab::Regex.environment_scope_regex_message }
) )
validate :updating_environment_scope
private
def updating_environment_scope
return unless environment_scope_changed?
unless project.feature_available?(:variable_environment_scope)
errors.add(:environment_scope, 'is not enabled for this project')
end
end
end end
end end
end end
......
...@@ -78,7 +78,8 @@ module EE ...@@ -78,7 +78,8 @@ module EE
end end
def secret_variables_for(ref:, environment: nil) def secret_variables_for(ref:, environment: nil)
return super.where(environment_scope: '*') unless environment return super.where(environment_scope: '*') unless
environment && feature_available?(:variable_environment_scope)
query = super query = super
......
...@@ -9,6 +9,7 @@ class License < ActiveRecord::Base ...@@ -9,6 +9,7 @@ class License < ActiveRecord::Base
OBJECT_STORAGE_FEATURE = 'GitLab_ObjectStorage'.freeze OBJECT_STORAGE_FEATURE = 'GitLab_ObjectStorage'.freeze
ELASTIC_SEARCH_FEATURE = 'GitLab_ElasticSearch'.freeze ELASTIC_SEARCH_FEATURE = 'GitLab_ElasticSearch'.freeze
RELATED_ISSUES_FEATURE = 'RelatedIssues'.freeze RELATED_ISSUES_FEATURE = 'RelatedIssues'.freeze
VARIABLE_ENVIRONMENT_SCOPE_FEATURE = 'GitLab_VARIABLE_ENVIRONMENT_SCOPE'.freeze
FEATURE_CODES = { FEATURE_CODES = {
geo: GEO_FEATURE, geo: GEO_FEATURE,
...@@ -17,6 +18,7 @@ class License < ActiveRecord::Base ...@@ -17,6 +18,7 @@ class License < ActiveRecord::Base
object_storage: OBJECT_STORAGE_FEATURE, object_storage: OBJECT_STORAGE_FEATURE,
elastic_search: ELASTIC_SEARCH_FEATURE, elastic_search: ELASTIC_SEARCH_FEATURE,
related_issues: RELATED_ISSUES_FEATURE, related_issues: RELATED_ISSUES_FEATURE,
variable_environment_scope: VARIABLE_ENVIRONMENT_SCOPE_FEATURE,
# Features that make sense to Namespace: # Features that make sense to Namespace:
deploy_board: DEPLOY_BOARD_FEATURE, deploy_board: DEPLOY_BOARD_FEATURE,
file_lock: FILE_LOCK_FEATURE file_lock: FILE_LOCK_FEATURE
...@@ -39,7 +41,8 @@ class License < ActiveRecord::Base ...@@ -39,7 +41,8 @@ class License < ActiveRecord::Base
{ GEO_FEATURE => 1 }, { GEO_FEATURE => 1 },
{ AUDITOR_USER_FEATURE => 1 }, { AUDITOR_USER_FEATURE => 1 },
{ SERVICE_DESK_FEATURE => 1 }, { SERVICE_DESK_FEATURE => 1 },
{ OBJECT_STORAGE_FEATURE => 1 } { OBJECT_STORAGE_FEATURE => 1 },
{ VARIABLE_ENVIRONMENT_SCOPE_FEATURE => 1 }
].freeze ].freeze
EEU_FEATURES = [ EEU_FEATURES = [
......
%h4.prepend-top-0 %h4.prepend-top-0
Secret variables Secret variables
= link_to icon('question-circle'), help_page_path('ci/variables/README', anchor: 'secret-variables'), target: '_blank' = link_to icon('question-circle'), help_page_path('ci/variables/README', anchor: 'secret-variables'), target: '_blank'
%p - if @project.feature_available?(:variable_environment_scope)
These variables will be set to environment by the runner, and could be protected by exposing only to protected branches or tags, or some particular environments. %p
These variables will be set to environment by the runner, and could be protected by exposing only to protected branches or tags, or some particular environments.
- else
%p
These variables will be set to environment by the runner, and could be protected by exposing only to protected branches or tags.
%p %p
So you can use them for passwords, secret keys or whatever you want. So you can use them for passwords, secret keys or whatever you want.
%p %p
......
...@@ -7,13 +7,14 @@ ...@@ -7,13 +7,14 @@
.form-group .form-group
= f.label :value, "Value", class: "label-light" = f.label :value, "Value", class: "label-light"
= f.text_area :value, class: "form-control", placeholder: "PROJECT_VARIABLE" = f.text_area :value, class: "form-control", placeholder: "PROJECT_VARIABLE"
.form-group - if @project.feature_available?(:variable_environment_scope)
= f.label :environment_scope, "Environment scope", class: "label-light" .form-group
= f.text_field :environment_scope, class: "form-control", placeholder: "*" = f.label :environment_scope, "Environment scope", class: "label-light"
.help-block = f.text_field :environment_scope, class: "form-control", placeholder: "*"
This variable will be passed only to jobs with a matching environment name. .help-block
<code>*</code> is a wildcard that matches all environments (existing or not). This variable will be passed only to jobs with a matching environment name.
= link_to icon('question-circle'), help_page_path('ci/variables/README', anchor: 'limiting-environment-scopes-of-secret-variables'), target: '_blank' <code>*</code> is a wildcard that matches all environments (existing or not).
= link_to icon('question-circle'), help_page_path('ci/variables/README', anchor: 'limiting-environment-scopes-of-secret-variables'), target: '_blank'
.form-group .form-group
.checkbox .checkbox
= f.label :protected do = f.label :protected do
......
...@@ -9,7 +9,8 @@ ...@@ -9,7 +9,8 @@
%th Key %th Key
%th Value %th Value
%th Protected %th Protected
%th Environment scope - if @project.feature_available?(:variable_environment_scope)
%th Environment scope
%th %th
%tbody %tbody
- @project.variables.order_key_asc.each do |variable| - @project.variables.order_key_asc.each do |variable|
...@@ -18,7 +19,8 @@ ...@@ -18,7 +19,8 @@
%td.variable-key= variable.key %td.variable-key= variable.key
%td.variable-value{ "data-value" => variable.value }****** %td.variable-value{ "data-value" => variable.value }******
%td.variable-protected= Gitlab::Utils.boolean_to_yes_no(variable.protected) %td.variable-protected= Gitlab::Utils.boolean_to_yes_no(variable.protected)
%td.variable-environment-scope= variable.environment_scope - if @project.feature_available?(:variable_environment_scope)
%td.variable-environment-scope= variable.environment_scope
%td.variable-menu %td.variable-menu
= link_to namespace_project_variable_path(@project.namespace, @project, variable), class: "btn btn-transparent btn-variable-edit" do = link_to namespace_project_variable_path(@project.namespace, @project, variable), class: "btn btn-transparent btn-variable-edit" do
%span.sr-only %span.sr-only
......
...@@ -753,7 +753,9 @@ module API ...@@ -753,7 +753,9 @@ module API
expose :protected?, as: :protected expose :protected?, as: :protected
# EE # EE
expose :environment_scope expose :environment_scope, if: ->(variable, options) {
variable.project.feature_available?(:variable_environment_scope)
}
end end
class Pipeline < PipelineBasic class Pipeline < PipelineBasic
......
...@@ -6,6 +6,9 @@ describe 'Project variables', js: true do ...@@ -6,6 +6,9 @@ describe 'Project variables', js: true do
let(:variable) { create(:ci_variable, key: 'test_key', value: 'test value') } let(:variable) { create(:ci_variable, key: 'test_key', value: 'test value') }
before do before do
# EE
stub_feature(:variable_environment_scope)
login_as(user) login_as(user)
project.team << [user, :master] project.team << [user, :master]
project.variables << variable project.variables << variable
......
...@@ -2,8 +2,7 @@ require 'spec_helper' ...@@ -2,8 +2,7 @@ require 'spec_helper'
describe EE::Gitlab::ServiceDesk, lib: true do describe EE::Gitlab::ServiceDesk, lib: true do
before do before do
allow_any_instance_of(License).to receive(:feature_available?).and_call_original stub_feature(:service_desk)
allow_any_instance_of(License).to receive(:feature_available?).with(:service_desk) { true }
allow(::Gitlab::IncomingEmail).to receive(:enabled?) { true } allow(::Gitlab::IncomingEmail).to receive(:enabled?) { true }
allow(::Gitlab::IncomingEmail).to receive(:supports_wildcard?) { true } allow(::Gitlab::IncomingEmail).to receive(:supports_wildcard?) { true }
end end
......
...@@ -1412,6 +1412,8 @@ describe Ci::Build, :models do ...@@ -1412,6 +1412,8 @@ describe Ci::Build, :models do
end end
before do before do
stub_feature(:variable_environment_scope)
build.update(environment: 'staging') build.update(environment: 'staging')
create(:environment, name: 'staging', project: build.project) create(:environment, name: 'staging', project: build.project)
......
...@@ -12,8 +12,14 @@ describe Ci::Variable, models: true do ...@@ -12,8 +12,14 @@ describe Ci::Variable, models: true do
it { is_expected.not_to allow_value('foo/bar').for(:key) } it { is_expected.not_to allow_value('foo/bar').for(:key) }
# EE # EE
it { is_expected.to allow_value('review/*').for(:environment_scope) } context 'with variable_environment_scope enabled' do
it { is_expected.not_to allow_value('').for(:environment_scope) } before do
stub_feature(:variable_environment_scope)
end
it { is_expected.to allow_value('review/*').for(:environment_scope) }
it { is_expected.not_to allow_value('').for(:environment_scope) }
end
let(:key_scope) do let(:key_scope) do
[:project_id, :environment_scope] # EE [:project_id, :environment_scope] # EE
......
...@@ -2293,6 +2293,10 @@ describe Project, models: true do ...@@ -2293,6 +2293,10 @@ describe Project, models: true do
project.secret_variables_for(ref: 'ref', environment: environment) project.secret_variables_for(ref: 'ref', environment: environment)
end end
before do
stub_feature(:variable_environment_scope)
end
context 'when environment scope is exactly matched' do context 'when environment scope is exactly matched' do
before do before do
secret_variable.update(environment_scope: 'review/name') secret_variable.update(environment_scope: 'review/name')
......
...@@ -92,6 +92,8 @@ describe API::Variables do ...@@ -92,6 +92,8 @@ describe API::Variables do
# EE # EE
it 'creates variable with a specific environment scope' do it 'creates variable with a specific environment scope' do
stub_feature(:variable_environment_scope)
expect do expect do
post api("/projects/#{project.id}/variables", user), key: 'TEST_VARIABLE_2', value: 'VALUE_2', environment_scope: 'review/*' post api("/projects/#{project.id}/variables", user), key: 'TEST_VARIABLE_2', value: 'VALUE_2', environment_scope: 'review/*'
end.to change{project.variables.count}.by(1) end.to change{project.variables.count}.by(1)
...@@ -104,6 +106,8 @@ describe API::Variables do ...@@ -104,6 +106,8 @@ describe API::Variables do
# EE # EE
it 'allows duplicated variable key given different environment scopes' do it 'allows duplicated variable key given different environment scopes' do
stub_feature(:variable_environment_scope)
expect do expect do
post api("/projects/#{project.id}/variables", user), key: variable.key, value: 'VALUE_2', environment_scope: 'review/*' post api("/projects/#{project.id}/variables", user), key: variable.key, value: 'VALUE_2', environment_scope: 'review/*'
end.to change{project.variables.count}.by(1) end.to change{project.variables.count}.by(1)
......
...@@ -57,6 +57,7 @@ RSpec.configure do |config| ...@@ -57,6 +57,7 @@ RSpec.configure do |config|
config.include StubGitlabData config.include StubGitlabData
config.include ApiHelpers, :api config.include ApiHelpers, :api
config.include MigrationsHelpers, :migration config.include MigrationsHelpers, :migration
config.include EE::LicenseHelpers
config.include Rails.application.routes.url_helpers, type: :routing config.include Rails.application.routes.url_helpers, type: :routing
config.infer_spec_type_from_file_location! config.infer_spec_type_from_file_location!
......
module EE
module LicenseHelpers
def stub_feature(feature, enabled = true)
allow_any_instance_of(License).to receive(:feature_available?)
.and_call_original
allow_any_instance_of(License).to receive(:feature_available?)
.with(feature) { enabled }
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment