Merge branch 'introduce-environment-search-endpoint' into 'master'
Introduce Internal API for searching environment names See merge request gitlab-org/gitlab-ce!24923
This commit is contained in:
commit
561ce0c095
|
@ -158,6 +158,16 @@ class Projects::EnvironmentsController < Projects::ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def search
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
environment_names = search_environment_names
|
||||
|
||||
render json: environment_names, status: environment_names.any? ? :ok : :no_content
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def verify_api_request!
|
||||
|
@ -181,6 +191,12 @@ class Projects::EnvironmentsController < Projects::ApplicationController
|
|||
@environment ||= project.environments.find(params[:id])
|
||||
end
|
||||
|
||||
def search_environment_names
|
||||
return [] unless params[:query]
|
||||
|
||||
project.environments.for_name_like(params[:query]).pluck_names
|
||||
end
|
||||
|
||||
def serialize_environments(request, response, nested = false)
|
||||
EnvironmentSerializer
|
||||
.new(project: @project, current_user: @current_user)
|
||||
|
|
|
@ -50,6 +50,14 @@ class Environment < ActiveRecord::Base
|
|||
end
|
||||
scope :in_review_folder, -> { where(environment_type: "review") }
|
||||
scope :for_name, -> (name) { where(name: name) }
|
||||
|
||||
##
|
||||
# Search environments which have names like the given query.
|
||||
# Do not set a large limit unless you've confirmed that it works on gitlab.com scale.
|
||||
scope :for_name_like, -> (query, limit: 5) do
|
||||
where('name LIKE ?', "#{sanitize_sql_like(query)}%").limit(limit)
|
||||
end
|
||||
|
||||
scope :for_project, -> (project) { where(project_id: project) }
|
||||
scope :with_deployment, -> (sha) { where('EXISTS (?)', Deployment.select(1).where('deployments.environment_id = environments.id').where(sha: sha)) }
|
||||
|
||||
|
@ -70,6 +78,10 @@ class Environment < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def self.pluck_names
|
||||
pluck(:name)
|
||||
end
|
||||
|
||||
def predefined_variables
|
||||
Gitlab::Ci::Variables::Collection.new
|
||||
.append(key: 'CI_ENVIRONMENT_NAME', value: name)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Introduce Internal API for searching environment names
|
||||
merge_request: 24923
|
||||
author:
|
||||
type: added
|
|
@ -224,6 +224,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
|
|||
collection do
|
||||
get :metrics, action: :metrics_redirect
|
||||
get :folder, path: 'folders/*id', constraints: { format: /(html|json)/ }
|
||||
get :search
|
||||
end
|
||||
|
||||
resources :deployments, only: [:index] do
|
||||
|
|
|
@ -422,6 +422,79 @@ describe Projects::EnvironmentsController do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'GET #search' do
|
||||
before do
|
||||
create(:environment, name: 'staging', project: project)
|
||||
create(:environment, name: 'review/patch-1', project: project)
|
||||
create(:environment, name: 'review/patch-2', project: project)
|
||||
end
|
||||
|
||||
let(:query) { 'pro' }
|
||||
|
||||
it 'responds with status code 200' do
|
||||
get :search, params: environment_params(format: :json, query: query)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
|
||||
it 'returns matched results' do
|
||||
get :search, params: environment_params(format: :json, query: query)
|
||||
|
||||
expect(json_response).to contain_exactly('production')
|
||||
end
|
||||
|
||||
context 'when query is review' do
|
||||
let(:query) { 'review' }
|
||||
|
||||
it 'returns matched results' do
|
||||
get :search, params: environment_params(format: :json, query: query)
|
||||
|
||||
expect(json_response).to contain_exactly('review/patch-1', 'review/patch-2')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when query is empty' do
|
||||
let(:query) { '' }
|
||||
|
||||
it 'returns matched results' do
|
||||
get :search, params: environment_params(format: :json, query: query)
|
||||
|
||||
expect(json_response)
|
||||
.to contain_exactly('production', 'staging', 'review/patch-1', 'review/patch-2')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when query is review/patch-3' do
|
||||
let(:query) { 'review/patch-3' }
|
||||
|
||||
it 'responds with status code 204' do
|
||||
get :search, params: environment_params(format: :json, query: query)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:no_content)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when query is partially matched in the middle of environment name' do
|
||||
let(:query) { 'patch' }
|
||||
|
||||
it 'responds with status code 204' do
|
||||
get :search, params: environment_params(format: :json, query: query)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:no_content)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when query contains a wildcard character' do
|
||||
let(:query) { 'review%' }
|
||||
|
||||
it 'prevents wildcard injection' do
|
||||
get :search, params: environment_params(format: :json, query: query)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:no_content)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def environment_params(opts = {})
|
||||
opts.reverse_merge(namespace_id: project.namespace,
|
||||
project_id: project,
|
||||
|
|
|
@ -41,6 +41,76 @@ describe Environment do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.for_name_like' do
|
||||
subject { project.environments.for_name_like(query, limit: limit) }
|
||||
|
||||
let!(:environment) { create(:environment, name: 'production', project: project) }
|
||||
let(:query) { 'pro' }
|
||||
let(:limit) { 5 }
|
||||
|
||||
it 'returns a found name' do
|
||||
is_expected.to include(environment)
|
||||
end
|
||||
|
||||
context 'when query is production' do
|
||||
let(:query) { 'production' }
|
||||
|
||||
it 'returns a found name' do
|
||||
is_expected.to include(environment)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when query is productionA' do
|
||||
let(:query) { 'productionA' }
|
||||
|
||||
it 'returns empty array' do
|
||||
is_expected.to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'when query is empty' do
|
||||
let(:query) { '' }
|
||||
|
||||
it 'returns a found name' do
|
||||
is_expected.to include(environment)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when query is nil' do
|
||||
let(:query) { }
|
||||
|
||||
it 'raises an error' do
|
||||
expect { subject }.to raise_error(NoMethodError)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when query is partially matched in the middle of environment name' do
|
||||
let(:query) { 'duction' }
|
||||
|
||||
it 'returns empty array' do
|
||||
is_expected.to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'when query contains a wildcard character' do
|
||||
let(:query) { 'produc%' }
|
||||
|
||||
it 'prevents wildcard injection' do
|
||||
is_expected.to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.pluck_names' do
|
||||
subject { described_class.pluck_names }
|
||||
|
||||
let!(:environment) { create(:environment, name: 'production', project: project) }
|
||||
|
||||
it 'plucks names' do
|
||||
is_expected.to eq(%w[production])
|
||||
end
|
||||
end
|
||||
|
||||
describe '#expire_etag_cache' do
|
||||
let(:store) { Gitlab::EtagCaching::Store.new }
|
||||
|
||||
|
|
Loading…
Reference in New Issue