Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
b8d3aa799c
commit
aaa0fba820
|
|
@ -2,7 +2,7 @@
|
||||||
import { GlModal, GlAlert } from '@gitlab/ui';
|
import { GlModal, GlAlert } from '@gitlab/ui';
|
||||||
import { mapGetters, mapActions, mapState } from 'vuex';
|
import { mapGetters, mapActions, mapState } from 'vuex';
|
||||||
import { TYPE_USER, TYPE_ITERATION, TYPE_MILESTONE } from '~/graphql_shared/constants';
|
import { TYPE_USER, TYPE_ITERATION, TYPE_MILESTONE } from '~/graphql_shared/constants';
|
||||||
import { convertToGraphQLId, getZeroBasedIdFromGraphQLId } from '~/graphql_shared/utils';
|
import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||||
import { getParameterByName, visitUrl } from '~/lib/utils/url_utility';
|
import { getParameterByName, visitUrl } from '~/lib/utils/url_utility';
|
||||||
import { __, s__ } from '~/locale';
|
import { __, s__ } from '~/locale';
|
||||||
import { fullLabelId } from '../boards_util';
|
import { fullLabelId } from '../boards_util';
|
||||||
|
|
@ -169,11 +169,11 @@ export default {
|
||||||
: null,
|
: null,
|
||||||
// Temporarily converting to milestone ID due to https://gitlab.com/gitlab-org/gitlab/-/issues/344779
|
// Temporarily converting to milestone ID due to https://gitlab.com/gitlab-org/gitlab/-/issues/344779
|
||||||
milestoneId: this.board.milestone?.id
|
milestoneId: this.board.milestone?.id
|
||||||
? convertToGraphQLId(TYPE_MILESTONE, getZeroBasedIdFromGraphQLId(this.board.milestone.id))
|
? convertToGraphQLId(TYPE_MILESTONE, getIdFromGraphQLId(this.board.milestone.id))
|
||||||
: null,
|
: null,
|
||||||
// Temporarily converting to iteration ID due to https://gitlab.com/gitlab-org/gitlab/-/issues/344779
|
// Temporarily converting to iteration ID due to https://gitlab.com/gitlab-org/gitlab/-/issues/344779
|
||||||
iterationId: this.board.iteration?.id
|
iterationId: this.board.iteration?.id
|
||||||
? convertToGraphQLId(TYPE_ITERATION, getZeroBasedIdFromGraphQLId(this.board.iteration.id))
|
? convertToGraphQLId(TYPE_ITERATION, getIdFromGraphQLId(this.board.iteration.id))
|
||||||
: null,
|
: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -268,12 +268,11 @@ export default {
|
||||||
<template>
|
<template>
|
||||||
<div class="boards-switcher js-boards-selector gl-mr-3">
|
<div class="boards-switcher js-boards-selector gl-mr-3">
|
||||||
<span class="boards-selector-wrapper js-boards-selector-wrapper">
|
<span class="boards-selector-wrapper js-boards-selector-wrapper">
|
||||||
<gl-loading-icon v-if="isBoardLoading" size="md" class="gl-mt-2" />
|
|
||||||
<gl-dropdown
|
<gl-dropdown
|
||||||
v-else
|
|
||||||
data-qa-selector="boards_dropdown"
|
data-qa-selector="boards_dropdown"
|
||||||
toggle-class="dropdown-menu-toggle js-dropdown-toggle"
|
toggle-class="dropdown-menu-toggle js-dropdown-toggle"
|
||||||
menu-class="flex-column dropdown-extended-height"
|
menu-class="flex-column dropdown-extended-height"
|
||||||
|
:loading="isBoardLoading"
|
||||||
:text="board.name"
|
:text="board.name"
|
||||||
@show="loadBoards"
|
@show="loadBoards"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,27 @@
|
||||||
|
import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import VueApollo from 'vue-apollo';
|
import VueApollo from 'vue-apollo';
|
||||||
import BoardsSelector from 'ee_else_ce/boards/components/boards_selector.vue';
|
import BoardsSelector from 'ee_else_ce/boards/components/boards_selector.vue';
|
||||||
import store from '~/boards/stores';
|
import store from '~/boards/stores';
|
||||||
import createDefaultClient from '~/lib/graphql';
|
import createDefaultClient from '~/lib/graphql';
|
||||||
import { parseBoolean } from '~/lib/utils/common_utils';
|
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||||
|
import introspectionQueryResultData from '~/sidebar/fragmentTypes.json';
|
||||||
|
|
||||||
Vue.use(VueApollo);
|
Vue.use(VueApollo);
|
||||||
|
|
||||||
|
const fragmentMatcher = new IntrospectionFragmentMatcher({
|
||||||
|
introspectionQueryResultData,
|
||||||
|
});
|
||||||
|
|
||||||
const apolloProvider = new VueApollo({
|
const apolloProvider = new VueApollo({
|
||||||
defaultClient: createDefaultClient(),
|
defaultClient: createDefaultClient(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
cacheConfig: {
|
||||||
|
fragmentMatcher,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default (params = {}) => {
|
export default (params = {}) => {
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,6 @@ const elementRenderer = (element, props = {}) => (createElement) =>
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const root = document.querySelector('#js-google-cloud');
|
const root = document.querySelector('#js-google-cloud');
|
||||||
|
const props = JSON.parse(root.getAttribute('data'));
|
||||||
// uncomment this once backend is ready
|
return new Vue({ el: root, render: elementRenderer(App, props) });
|
||||||
// const dataset = JSON.parse(root.getAttribute('data'));
|
|
||||||
const mockDataset = {
|
|
||||||
createServiceAccountUrl: '#create-url',
|
|
||||||
serviceAccounts: [],
|
|
||||||
emptyIllustrationUrl:
|
|
||||||
'https://gitlab.com/gitlab-org/gitlab-svgs/-/raw/main/illustrations/pipelines_empty.svg',
|
|
||||||
};
|
|
||||||
return new Vue({ el: root, render: elementRenderer(App, mockDataset) });
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,7 @@ const parseGid = (gid) => parseInt(`${gid}`.replace(/gid:\/\/gitlab\/.*\//g, '')
|
||||||
* @param {String} gid GraphQL global ID
|
* @param {String} gid GraphQL global ID
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
export const getIdFromGraphQLId = (gid = '') => parseGid(gid) || null;
|
export const getIdFromGraphQLId = (gid = '') => {
|
||||||
|
|
||||||
export const getZeroBasedIdFromGraphQLId = (gid = '') => {
|
|
||||||
const parsedGid = parseGid(gid);
|
const parsedGid = parseGid(gid);
|
||||||
return Number.isInteger(parsedGid) ? parsedGid : null;
|
return Number.isInteger(parsedGid) ? parsedGid : null;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,11 @@ class Projects::GoogleCloudController < Projects::ApplicationController
|
||||||
before_action :feature_flag_enabled?
|
before_action :feature_flag_enabled?
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
@js_data = {
|
||||||
|
serviceAccounts: GoogleCloud::ServiceAccountsService.new(project).find_for_project,
|
||||||
|
createServiceAccountUrl: '#mocked-url-create-service',
|
||||||
|
emptyIllustrationUrl: ActionController::Base.helpers.image_path('illustrations/pipelines_empty.svg')
|
||||||
|
}.to_json
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module GoogleCloud
|
||||||
|
##
|
||||||
|
# GCP keys used to store Google Cloud Service Accounts
|
||||||
|
GCP_KEYS = %w[GCP_PROJECT_ID GCP_SERVICE_ACCOUNT GCP_SERVICE_ACCOUNT_KEY].freeze
|
||||||
|
|
||||||
|
##
|
||||||
|
# This service deals with GCP Service Accounts in GitLab
|
||||||
|
|
||||||
|
class ServiceAccountsService < ::BaseService
|
||||||
|
##
|
||||||
|
# Find GCP Service Accounts in a GitLab project
|
||||||
|
#
|
||||||
|
# This method looks up GitLab project's CI vars
|
||||||
|
# and returns Google Cloud Service Accounts combinations
|
||||||
|
# aligning GitLab project and environment to GCP projects
|
||||||
|
|
||||||
|
def find_for_project
|
||||||
|
group_vars_by_environment.map do |environment_scope, value|
|
||||||
|
{
|
||||||
|
environment: environment_scope,
|
||||||
|
gcp_project: value['GCP_PROJECT_ID'],
|
||||||
|
service_account_exists: value['GCP_SERVICE_ACCOUNT'].present?,
|
||||||
|
service_account_key_exists: value['GCP_SERVICE_ACCOUNT_KEY'].present?
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def group_vars_by_environment
|
||||||
|
filtered_vars = @project.variables.filter { |variable| GCP_KEYS.include? variable.key }
|
||||||
|
filtered_vars.each_with_object({}) do |variable, grouped|
|
||||||
|
grouped[variable.environment_scope] ||= {}
|
||||||
|
grouped[variable.environment_scope][variable.key] = variable.value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -3,4 +3,4 @@
|
||||||
|
|
||||||
- @content_class = "limit-container-width" unless fluid_layout
|
- @content_class = "limit-container-width" unless fluid_layout
|
||||||
|
|
||||||
#js-google-cloud
|
#js-google-cloud{ data: @js_data }
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# Currently we register validator only for `dev` or `test` environment
|
# Currently we register validator only for `dev` or `test` environment
|
||||||
Gitlab::Database::QueryAnalyzer.new.hook! if Gitlab.dev_or_test_env?
|
if Gitlab.dev_or_test_env? || Gitlab::Utils.to_boolean(ENV['GITLAB_ENABLE_QUERY_ANALYZERS'], default: false)
|
||||||
|
Gitlab::Database::QueryAnalyzer.instance.hook!
|
||||||
|
end
|
||||||
|
|
|
||||||
|
|
@ -2599,33 +2599,12 @@ faster-test-job:
|
||||||
- echo "Running tests..."
|
- echo "Running tests..."
|
||||||
```
|
```
|
||||||
|
|
||||||
### `artifacts`
|
### `dependencies`
|
||||||
|
|
||||||
Use `artifacts` to specify a list of files and directories that are
|
Use the `dependencies` keyword to define a list of jobs to fetch [artifacts](#artifacts) from.
|
||||||
attached to the job when it [succeeds, fails, or always](#artifactswhen).
|
|
||||||
|
|
||||||
The artifacts are sent to GitLab after the job finishes. They are
|
|
||||||
available for download in the GitLab UI if the size is not
|
|
||||||
larger than the [maximum artifact size](../../user/gitlab_com/index.md#gitlab-cicd).
|
|
||||||
|
|
||||||
By default, jobs in later stages automatically download all the artifacts created
|
|
||||||
by jobs in earlier stages. You can control artifact download behavior in jobs with
|
|
||||||
[`dependencies`](#dependencies).
|
|
||||||
|
|
||||||
When using the [`needs`](#artifact-downloads-with-needs) keyword, jobs can only download
|
|
||||||
artifacts from the jobs defined in the `needs` configuration.
|
|
||||||
|
|
||||||
Job artifacts are only collected for successful jobs by default, and
|
|
||||||
artifacts are restored after [caches](#cache).
|
|
||||||
|
|
||||||
[Read more about artifacts](../pipelines/job_artifacts.md).
|
|
||||||
|
|
||||||
#### `dependencies`
|
|
||||||
|
|
||||||
Use the `dependencies` keyword to define a list of jobs to fetch artifacts from.
|
|
||||||
You can also set a job to download no artifacts at all.
|
You can also set a job to download no artifacts at all.
|
||||||
|
|
||||||
If you do not use `dependencies`, all `artifacts` from previous stages are passed to each job.
|
If you do not use `dependencies`, all artifacts from previous stages are passed to each job.
|
||||||
|
|
||||||
**Keyword type**: Job keyword. You can use it only as part of a job.
|
**Keyword type**: Job keyword. You can use it only as part of a job.
|
||||||
|
|
||||||
|
|
@ -2681,6 +2660,27 @@ the [stage](#stages) precedence.
|
||||||
- If the artifacts of a dependent job are [expired](#artifactsexpire_in) or
|
- If the artifacts of a dependent job are [expired](#artifactsexpire_in) or
|
||||||
[deleted](../pipelines/job_artifacts.md#delete-job-artifacts), then the job fails.
|
[deleted](../pipelines/job_artifacts.md#delete-job-artifacts), then the job fails.
|
||||||
|
|
||||||
|
### `artifacts`
|
||||||
|
|
||||||
|
Use `artifacts` to specify a list of files and directories that are
|
||||||
|
attached to the job when it [succeeds, fails, or always](#artifactswhen).
|
||||||
|
|
||||||
|
The artifacts are sent to GitLab after the job finishes. They are
|
||||||
|
available for download in the GitLab UI if the size is not
|
||||||
|
larger than the [maximum artifact size](../../user/gitlab_com/index.md#gitlab-cicd).
|
||||||
|
|
||||||
|
By default, jobs in later stages automatically download all the artifacts created
|
||||||
|
by jobs in earlier stages. You can control artifact download behavior in jobs with
|
||||||
|
[`dependencies`](#dependencies).
|
||||||
|
|
||||||
|
When using the [`needs`](#artifact-downloads-with-needs) keyword, jobs can only download
|
||||||
|
artifacts from the jobs defined in the `needs` configuration.
|
||||||
|
|
||||||
|
Job artifacts are only collected for successful jobs by default, and
|
||||||
|
artifacts are restored after [caches](#cache).
|
||||||
|
|
||||||
|
[Read more about artifacts](../pipelines/job_artifacts.md).
|
||||||
|
|
||||||
#### `artifacts:exclude`
|
#### `artifacts:exclude`
|
||||||
|
|
||||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15122) in GitLab 13.1
|
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15122) in GitLab 13.1
|
||||||
|
|
|
||||||
|
|
@ -118,8 +118,9 @@ SSO has the following effects when enabled:
|
||||||
|
|
||||||
- For groups, users can't share a project in the group outside the top-level group,
|
- For groups, users can't share a project in the group outside the top-level group,
|
||||||
even if the project is forked.
|
even if the project is forked.
|
||||||
- For a Git activity, users must be signed-in through SSO before they can push to or
|
- For Git activity over SSH and HTTPS, users must have at least one active session signed-in through SSO before they can push to or
|
||||||
pull from a GitLab repository.
|
pull from a GitLab repository.
|
||||||
|
- Credentials that are not tied to regular users (for example, access tokens and deploy keys) do not have the SSO check enforced.
|
||||||
- Users must be signed-in through SSO before they can pull images using the [Dependency Proxy](../../packages/dependency_proxy/index.md).
|
- Users must be signed-in through SSO before they can pull images using the [Dependency Proxy](../../packages/dependency_proxy/index.md).
|
||||||
<!-- Add bullet for API activity when https://gitlab.com/gitlab-org/gitlab/-/issues/9152 is complete -->
|
<!-- Add bullet for API activity when https://gitlab.com/gitlab-org/gitlab/-/issues/9152 is complete -->
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ module Gitlab
|
||||||
# times before using the primary instead.
|
# times before using the primary instead.
|
||||||
will_retry = conflict_retried < @host_list.length * 3
|
will_retry = conflict_retried < @host_list.length * 3
|
||||||
|
|
||||||
LoadBalancing::Logger.warn(
|
::Gitlab::Database::LoadBalancing::Logger.warn(
|
||||||
event: :host_query_conflict,
|
event: :host_query_conflict,
|
||||||
message: 'Query conflict on host',
|
message: 'Query conflict on host',
|
||||||
conflict_retried: conflict_retried,
|
conflict_retried: conflict_retried,
|
||||||
|
|
@ -91,7 +91,7 @@ module Gitlab
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
LoadBalancing::Logger.warn(
|
::Gitlab::Database::LoadBalancing::Logger.warn(
|
||||||
event: :no_secondaries_available,
|
event: :no_secondaries_available,
|
||||||
message: 'No secondaries were available, using primary instead',
|
message: 'No secondaries were available, using primary instead',
|
||||||
conflict_retried: conflict_retried,
|
conflict_retried: conflict_retried,
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ module Gitlab
|
||||||
job['load_balancing_strategy'] = strategy.to_s
|
job['load_balancing_strategy'] = strategy.to_s
|
||||||
|
|
||||||
if use_primary?(strategy)
|
if use_primary?(strategy)
|
||||||
Session.current.use_primary!
|
::Gitlab::Database::LoadBalancing::Session.current.use_primary!
|
||||||
elsif strategy == :retry
|
elsif strategy == :retry
|
||||||
raise JobReplicaNotUpToDate, "Sidekiq job #{worker_class} JID-#{job['jid']} couldn't use the replica."\
|
raise JobReplicaNotUpToDate, "Sidekiq job #{worker_class} JID-#{job['jid']} couldn't use the replica."\
|
||||||
" Replica was not up to date."
|
" Replica was not up to date."
|
||||||
|
|
@ -29,8 +29,8 @@ module Gitlab
|
||||||
private
|
private
|
||||||
|
|
||||||
def clear
|
def clear
|
||||||
LoadBalancing.release_hosts
|
::Gitlab::Database::LoadBalancing.release_hosts
|
||||||
Session.clear_session
|
::Gitlab::Database::LoadBalancing::Session.clear_session
|
||||||
end
|
end
|
||||||
|
|
||||||
def use_primary?(strategy)
|
def use_primary?(strategy)
|
||||||
|
|
@ -66,7 +66,7 @@ module Gitlab
|
||||||
def legacy_wal_location(job)
|
def legacy_wal_location(job)
|
||||||
wal_location = job['database_write_location'] || job['database_replica_location']
|
wal_location = job['database_write_location'] || job['database_replica_location']
|
||||||
|
|
||||||
{ Gitlab::Database::MAIN_DATABASE_NAME.to_sym => wal_location } if wal_location
|
{ ::Gitlab::Database::MAIN_DATABASE_NAME.to_sym => wal_location } if wal_location
|
||||||
end
|
end
|
||||||
|
|
||||||
def load_balancing_available?(worker_class)
|
def load_balancing_available?(worker_class)
|
||||||
|
|
@ -90,7 +90,7 @@ module Gitlab
|
||||||
end
|
end
|
||||||
|
|
||||||
def databases_in_sync?(wal_locations)
|
def databases_in_sync?(wal_locations)
|
||||||
LoadBalancing.each_load_balancer.all? do |lb|
|
::Gitlab::Database::LoadBalancing.each_load_balancer.all? do |lb|
|
||||||
if (location = wal_locations[lb.name])
|
if (location = wal_locations[lb.name])
|
||||||
lb.select_up_to_date_host(location)
|
lb.select_up_to_date_host(location)
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ module Gitlab
|
||||||
# The purpose of this class is to implement a various query analyzers based on `pg_query`
|
# The purpose of this class is to implement a various query analyzers based on `pg_query`
|
||||||
# And process them all via `Gitlab::Database::QueryAnalyzers::*`
|
# And process them all via `Gitlab::Database::QueryAnalyzers::*`
|
||||||
class QueryAnalyzer
|
class QueryAnalyzer
|
||||||
|
include ::Singleton
|
||||||
|
|
||||||
ANALYZERS = [].freeze
|
ANALYZERS = [].freeze
|
||||||
|
|
||||||
Parsed = Struct.new(
|
Parsed = Struct.new(
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import {
|
import {
|
||||||
isGid,
|
isGid,
|
||||||
getIdFromGraphQLId,
|
getIdFromGraphQLId,
|
||||||
getZeroBasedIdFromGraphQLId,
|
|
||||||
convertToGraphQLId,
|
convertToGraphQLId,
|
||||||
convertToGraphQLIds,
|
convertToGraphQLIds,
|
||||||
convertFromGraphQLIds,
|
convertFromGraphQLIds,
|
||||||
|
|
@ -54,7 +53,7 @@ describe('getIdFromGraphQLId', () => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: 'gid://gitlab/Environments/0',
|
input: 'gid://gitlab/Environments/0',
|
||||||
output: null,
|
output: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: 'gid://gitlab/Environments/123',
|
input: 'gid://gitlab/Environments/123',
|
||||||
|
|
@ -71,55 +70,6 @@ describe('getIdFromGraphQLId', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getZeroBasedIdFromGraphQLId', () => {
|
|
||||||
[
|
|
||||||
{
|
|
||||||
input: '',
|
|
||||||
output: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: null,
|
|
||||||
output: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: 2,
|
|
||||||
output: 2,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: 'gid://',
|
|
||||||
output: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: 'gid://gitlab/',
|
|
||||||
output: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: 'gid://gitlab/Environments',
|
|
||||||
output: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: 'gid://gitlab/Environments/',
|
|
||||||
output: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: 'gid://gitlab/Environments/0',
|
|
||||||
output: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: 'gid://gitlab/Environments/123',
|
|
||||||
output: 123,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: 'gid://gitlab/DesignManagement::Version/2',
|
|
||||||
output: 2,
|
|
||||||
},
|
|
||||||
].forEach(({ input, output }) => {
|
|
||||||
it(`getZeroBasedIdFromGraphQLId returns ${output} when passed ${input}`, () => {
|
|
||||||
expect(getZeroBasedIdFromGraphQLId(input)).toBe(output);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('convertToGraphQLId', () => {
|
describe('convertToGraphQLId', () => {
|
||||||
it('combines $type and $id into $result', () => {
|
it('combines $type and $id into $result', () => {
|
||||||
expect(convertToGraphQLId(mockType, mockId)).toBe(mockGid);
|
expect(convertToGraphQLId(mockType, mockId)).toBe(mockGid);
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ RSpec.describe Gitlab::Database::QueryAnalyzer do
|
||||||
|
|
||||||
def process_sql(sql)
|
def process_sql(sql)
|
||||||
ApplicationRecord.load_balancer.read_write do |connection|
|
ApplicationRecord.load_balancer.read_write do |connection|
|
||||||
described_class.new.send(:process_sql, sql, connection)
|
described_class.instance.send(:process_sql, sql, connection)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
RSpec.describe GoogleCloud::ServiceAccountsService do
|
||||||
|
let_it_be(:project) { create(:project) }
|
||||||
|
|
||||||
|
let(:service) { described_class.new(project) }
|
||||||
|
|
||||||
|
describe 'find_for_project' do
|
||||||
|
context 'when a project does not have GCP service account vars' do
|
||||||
|
before do
|
||||||
|
project.variables.build(key: 'blah', value: 'foo', environment_scope: 'world')
|
||||||
|
project.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns an empty list' do
|
||||||
|
expect(service.find_for_project.length).to eq(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when a project has GCP service account ci vars' do
|
||||||
|
before do
|
||||||
|
project.variables.build(environment_scope: '*', key: 'GCP_PROJECT_ID', value: 'prj1')
|
||||||
|
project.variables.build(environment_scope: '*', key: 'GCP_SERVICE_ACCOUNT_KEY', value: 'mock')
|
||||||
|
project.variables.build(environment_scope: 'staging', key: 'GCP_PROJECT_ID', value: 'prj2')
|
||||||
|
project.variables.build(environment_scope: 'staging', key: 'GCP_SERVICE_ACCOUNT', value: 'mock')
|
||||||
|
project.variables.build(environment_scope: 'production', key: 'GCP_PROJECT_ID', value: 'prj3')
|
||||||
|
project.variables.build(environment_scope: 'production', key: 'GCP_SERVICE_ACCOUNT', value: 'mock')
|
||||||
|
project.variables.build(environment_scope: 'production', key: 'GCP_SERVICE_ACCOUNT_KEY', value: 'mock')
|
||||||
|
project.save!
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns a list of service accounts' do
|
||||||
|
list = service.find_for_project
|
||||||
|
|
||||||
|
aggregate_failures 'testing list of service accounts' do
|
||||||
|
expect(list.length).to eq(3)
|
||||||
|
|
||||||
|
expect(list.first[:environment]).to eq('*')
|
||||||
|
expect(list.first[:gcp_project]).to eq('prj1')
|
||||||
|
expect(list.first[:service_account_exists]).to eq(false)
|
||||||
|
expect(list.first[:service_account_key_exists]).to eq(true)
|
||||||
|
|
||||||
|
expect(list.second[:environment]).to eq('staging')
|
||||||
|
expect(list.second[:gcp_project]).to eq('prj2')
|
||||||
|
expect(list.second[:service_account_exists]).to eq(true)
|
||||||
|
expect(list.second[:service_account_key_exists]).to eq(false)
|
||||||
|
|
||||||
|
expect(list.third[:environment]).to eq('production')
|
||||||
|
expect(list.third[:gcp_project]).to eq('prj3')
|
||||||
|
expect(list.third[:service_account_exists]).to eq(true)
|
||||||
|
expect(list.third[:service_account_key_exists]).to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
Reference in New Issue