summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml45
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml1
-rw-r--r--.rubocop_todo.yml1
-rw-r--r--app/assets/javascripts/filtered_search/constants.js2
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js2
-rw-r--r--app/assets/javascripts/filtered_search/visual_token_value.js3
-rw-r--r--app/assets/javascripts/ide/services/index.js8
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/actions.js1
-rw-r--r--app/assets/javascripts/ide/stores/utils.js11
-rw-r--r--app/assets/javascripts/mr_popover/queries/merge_request.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment.vue16
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue3
-rw-r--r--app/assets/stylesheets/pages/settings.scss5
-rw-r--r--app/controllers/clusters/clusters_controller.rb2
-rw-r--r--app/controllers/concerns/issuable_collections.rb6
-rw-r--r--app/helpers/services_helper.rb2
-rw-r--r--app/models/clusters/cluster.rb27
-rw-r--r--app/models/clusters/platforms/kubernetes.rb13
-rw-r--r--app/models/project_services/deployment_service.rb39
-rw-r--r--app/models/project_services/kubernetes_service.rb49
-rw-r--r--app/models/project_services/mock_deployment_service.rb16
-rw-r--r--app/models/service.rb4
-rw-r--r--app/views/admin/services/_deprecated_message.html.haml3
-rw-r--r--app/views/admin/services/_form.html.haml5
-rw-r--r--app/views/admin/services/edit.html.haml3
-rw-r--r--app/views/clusters/clusters/gcp/_form.html.haml9
-rw-r--r--app/views/clusters/platforms/kubernetes/_form.html.haml2
-rw-r--r--app/views/projects/merge_requests/_mr_box.html.haml4
-rw-r--r--app/views/shared/projects/_search_form.html.haml2
-rw-r--r--changelogs/unreleased/-30974-issue-search-by-number.yml5
-rw-r--r--changelogs/unreleased/55362-refresh-blank-service-account-token.yml5
-rw-r--r--changelogs/unreleased/55902-disable-creation-of-non-rbac-kubernetes-clusters.yml5
-rw-r--r--changelogs/unreleased/56737-commits-and-mr-events-on-jira-api.yml5
-rw-r--r--changelogs/unreleased/59023-fix-web-ide-creating-branches-off-new-commits.yml5
-rw-r--r--changelogs/unreleased/60617-allow-switching-from-gitlab-managed-to-unmanaged-clusters.yml5
-rw-r--r--changelogs/unreleased/62685-add-index-invite-email-to-members.yml5
-rw-r--r--changelogs/unreleased/63079-exclude-k8s-namespaces-with-no-service-account-token.yml6
-rw-r--r--changelogs/unreleased/63261-the-graphql-query-for-the-mr-popover-failes-on-the-frontend.yml6
-rw-r--r--changelogs/unreleased/hashed-storage-enabled-default.yml5
-rw-r--r--changelogs/unreleased/migrate_k8s_service_integration.yml5
-rw-r--r--changelogs/unreleased/readonly_k8s_integration.yml5
-rw-r--r--changelogs/unreleased/visual-review-apps-fix-dropdown.yml5
-rw-r--r--config/application.rb30
-rw-r--r--db/migrate/20190527011309_add_required_template_name_to_application_settings.rb15
-rw-r--r--db/migrate/20190610142825_add_index_to_members_invite_email.rb21
-rw-r--r--db/migrate/20190613030606_enable_hashed_storage_by_default.rb15
-rw-r--r--db/post_migrate/20190517153211_migrate_k8s_service_integration.rb104
-rw-r--r--db/post_migrate/20190611161642_add_index_to_events_and_audit_events_created_at_author_id.rb25
-rw-r--r--db/schema.rb8
-rw-r--r--doc/administration/repository_storage_types.md14
-rw-r--r--doc/api/graphql/index.md2
-rw-r--r--doc/api/services.md51
-rw-r--r--doc/ci/merge_request_pipelines/index.md12
-rw-r--r--doc/ci/yaml/README.md18
-rw-r--r--doc/integration/elasticsearch.md14
-rw-r--r--doc/user/group/clusters/index.md4
-rw-r--r--doc/user/project/clusters/index.md8
-rw-r--r--doc/user/project/repository/reducing_the_repo_size_using_git.md23
-rw-r--r--doc/workflow/todos.md2
-rw-r--r--lib/api/entities.rb2
-rw-r--r--lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb2
-rw-r--r--lib/gitlab/ci/config.rb15
-rw-r--r--locale/gitlab.pot6
-rw-r--r--qa/Rakefile5
-rw-r--r--qa/qa/page/dashboard/projects.rb8
-rw-r--r--qa/qa/page/merge_request/show.rb8
-rw-r--r--qa/qa/resource/label.rb2
-rw-r--r--qa/qa/resource/project.rb6
-rw-r--r--qa/qa/resource/project_milestone.rb15
-rw-r--r--qa/qa/resource/sandbox.rb4
-rw-r--r--qa/qa/runtime/address.rb2
-rw-r--r--qa/qa/runtime/browser.rb19
-rw-r--r--qa/qa/runtime/env.rb23
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb80
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb59
-rw-r--r--qa/qa/tools/generate_perf_testdata.rb185
-rw-r--r--qa/spec/runtime/env_spec.rb6
-rw-r--r--qa/spec/specs/runner_spec.rb68
-rw-r--r--spec/controllers/admin/clusters_controller_spec.rb4
-rw-r--r--spec/controllers/concerns/issuable_collections_spec.rb11
-rw-r--r--spec/controllers/groups/clusters_controller_spec.rb4
-rw-r--r--spec/controllers/projects/branches_controller_spec.rb22
-rw-r--r--spec/controllers/projects/clusters_controller_spec.rb4
-rw-r--r--spec/controllers/projects/services_controller_spec.rb26
-rw-r--r--spec/factories/clusters/kubernetes_namespaces.rb4
-rw-r--r--spec/factories/services.rb2
-rw-r--r--spec/features/projects/clusters/gcp_spec.rb4
-rw-r--r--spec/features/projects/clusters/interchangeability_spec.rb16
-rw-r--r--spec/features/projects/environments/environment_spec.rb18
-rw-r--r--spec/features/projects/environments/environments_spec.rb18
-rw-r--r--spec/finders/fork_projects_finder_spec.rb2
-rw-r--r--spec/frontend/ide/services/index_spec.js55
-rw-r--r--spec/javascripts/ide/stores/modules/commit/actions_spec.js18
-rw-r--r--spec/javascripts/ide/stores/utils_spec.js4
-rw-r--r--spec/lib/gitlab/ci/build/policy/kubernetes_spec.rb18
-rw-r--r--spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb8
-rw-r--r--spec/migrations/migrate_k8s_service_integration_spec.rb161
-rw-r--r--spec/models/ci/pipeline_schedule_spec.rb6
-rw-r--r--spec/models/ci/pipeline_spec.rb37
-rw-r--r--spec/models/clusters/cluster_spec.rb91
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb56
-rw-r--r--spec/models/environment_spec.rb42
-rw-r--r--spec/models/project_services/kubernetes_service_spec.rb44
-rw-r--r--spec/models/project_spec.rb31
-rw-r--r--spec/models/service_spec.rb6
-rw-r--r--spec/requests/api/services_spec.rb27
-rw-r--r--spec/serializers/environment_entity_spec.rb10
-rw-r--r--spec/services/projects/after_rename_service_spec.rb1
-rw-r--r--spec/services/projects/create_service_spec.rb2
-rw-r--r--spec/services/projects/fork_service_spec.rb3
-rw-r--r--spec/support/prometheus/additional_metrics_shared_examples.rb17
-rw-r--r--spec/support/shared_contexts/services_shared_context.rb3
-rw-r--r--spec/workers/reactive_caching_worker_spec.rb10
113 files changed, 1383 insertions, 636 deletions
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index 6afa668af22..75c79bb213f 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -1,11 +1,10 @@
.assets-compile-cache: &assets-compile-cache
cache:
- key: "assets-compile:vendor_ruby:.yarn-cache:tmp_cache_assets_sprockets:v5"
+ key: "assets-compile:vendor_ruby:.yarn-cache:tmp_cache_assets_sprockets:v6"
paths:
- vendor/ruby/
- .yarn-cache/
- tmp/cache/assets/sprockets
- policy: pull-push
.use-pg: &use-pg
services:
@@ -13,7 +12,7 @@
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- name: redis:alpine
-gitlab:assets:compile:
+.gitlab:assets:compile-metadata:
<<: *assets-compile-cache
extends: .dedicated-no-docs-pull-cache-job
image: dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-git-2.21-chrome-73.0-node-12.x-yarn-1.16-graphicsmagick-1.3.29-docker-18.06.1
@@ -58,7 +57,23 @@ gitlab:assets:compile:
- docker
- gitlab-org
-compile-assets:
+gitlab:assets:compile:
+ extends: .gitlab:assets:compile-metadata
+ cache:
+ policy: pull-push
+ only:
+ - master@gitlab-org/gitlab-ce
+ - master@gitlab-org/gitlab-ee
+
+gitlab:assets:compile pull-cache:
+ extends: .gitlab:assets:compile-metadata
+ cache:
+ policy: pull
+ except:
+ - master@gitlab-org/gitlab-ce
+ - master@gitlab-org/gitlab-ee
+
+.compile-assets-metadata:
extends: .dedicated-runner
<<: *use-pg
<<: *assets-compile-cache
@@ -77,9 +92,23 @@ compile-assets:
paths:
- node_modules
- public/assets
+
+compile-assets:
+ extends: .compile-assets-metadata
+ cache:
+ policy: pull-push
+ only:
+ - master@gitlab-org/gitlab-ce
+ - master@gitlab-org/gitlab-ee
+
+compile-assets pull-cache:
+ extends: .compile-assets-metadata
+ cache:
+ policy: pull
except:
- refs:
- - /(^docs[\/-].*|.*-docs$)/
+ - master@gitlab-org/gitlab-ce
+ - master@gitlab-org/gitlab-ee
+ - /(^docs[\/-].*|.*-docs$)/
gitlab:ui:visual:
extends: .dedicated-runner
@@ -87,6 +116,7 @@ gitlab:ui:visual:
allow_failure: true
dependencies:
- compile-assets
+ - compile-assets pull-cache
script:
# Remove node modules from GitLab that may conflict with gitlab-ui
- rm -r node_modules
@@ -116,6 +146,7 @@ karma:
<<: *use-pg
dependencies:
- compile-assets
+ - compile-assets pull-cache
- setup-test-env
variables:
# we override the max_old_space_size to prevent OOM errors
@@ -142,6 +173,7 @@ jest:
<<: *use-pg
dependencies:
- compile-assets
+ - compile-assets pull-cache
- setup-test-env
script:
- scripts/gitaly-test-spawn
@@ -232,6 +264,7 @@ jsdoc:
stage: post-test
dependencies:
- compile-assets
+ - compile-assets pull-cache
before_script: []
script:
- date
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index 68280506da2..8534b15e16b 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -236,6 +236,7 @@ static-analysis:
extends: .dedicated-no-docs-no-db-pull-cache-job
dependencies:
- compile-assets
+ - compile-assets pull-cache
- setup-test-env
script:
- scripts/static-analysis
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 63b1685feda..698570efb07 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -799,7 +799,6 @@ Style/SelfAssignment:
Exclude:
- 'app/models/concerns/bulk_member_access_load.rb'
- 'app/serializers/base_serializer.rb'
- - 'spec/features/projects/clusters/interchangeability_spec.rb'
- 'spec/support/import_export/configuration_helper.rb'
# Offense count: 50
diff --git a/app/assets/javascripts/filtered_search/constants.js b/app/assets/javascripts/filtered_search/constants.js
new file mode 100644
index 00000000000..8ca0e94cfeb
--- /dev/null
+++ b/app/assets/javascripts/filtered_search/constants.js
@@ -0,0 +1,2 @@
+/* eslint-disable import/prefer-default-export */
+export const TOKEN_TYPES = ['author', 'assignee'];
diff --git a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
index 315cd6f64da..7f6457242ef 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
@@ -1,4 +1,4 @@
-import VisualTokenValue from 'ee_else_ce/filtered_search/visual_token_value';
+import VisualTokenValue from './visual_token_value';
import { objectToQueryString } from '~/lib/utils/common_utils';
import FilteredSearchContainer from './container';
diff --git a/app/assets/javascripts/filtered_search/visual_token_value.js b/app/assets/javascripts/filtered_search/visual_token_value.js
index a54b445fb0a..018207541b3 100644
--- a/app/assets/javascripts/filtered_search/visual_token_value.js
+++ b/app/assets/javascripts/filtered_search/visual_token_value.js
@@ -6,6 +6,7 @@ import DropdownUtils from '~/filtered_search/dropdown_utils';
import Flash from '~/flash';
import UsersCache from '~/lib/utils/users_cache';
import { __ } from '~/locale';
+import { TOKEN_TYPES } from 'ee_else_ce/filtered_search/constants';
export default class VisualTokenValue {
constructor(tokenValue, tokenType) {
@@ -22,7 +23,7 @@ export default class VisualTokenValue {
if (tokenType === 'label') {
this.updateLabelTokenColor(tokenValueContainer);
- } else if (tokenType === 'author' || tokenType === 'assignee') {
+ } else if (TOKEN_TYPES.includes(tokenType)) {
this.updateUserTokenAppearance(tokenValueContainer, tokenValueElement);
} else if (tokenType === 'my-reaction') {
this.updateEmojiTokenAppearance(tokenValueContainer, tokenValueElement);
diff --git a/app/assets/javascripts/ide/services/index.js b/app/assets/javascripts/ide/services/index.js
index ba33b6826d6..840761f68db 100644
--- a/app/assets/javascripts/ide/services/index.js
+++ b/app/assets/javascripts/ide/services/index.js
@@ -56,7 +56,13 @@ export default {
return Api.branchSingle(projectId, currentBranchId);
},
commit(projectId, payload) {
- return Api.commitMultiple(projectId, payload);
+ // Currently the `commit` endpoint does not support `start_sha` so we
+ // have to make the request in the FE. This is not ideal and will be
+ // resolved soon. https://gitlab.com/gitlab-org/gitlab-ce/issues/59023
+ const { branch, start_sha: ref } = payload;
+ const branchPromise = ref ? Api.createBranch(projectId, { ref, branch }) : Promise.resolve();
+
+ return branchPromise.then(() => Api.commitMultiple(projectId, payload));
},
getFiles(projectUrl, branchId) {
const url = `${projectUrl}/files/${branchId}`;
diff --git a/app/assets/javascripts/ide/stores/modules/commit/actions.js b/app/assets/javascripts/ide/stores/modules/commit/actions.js
index 51062f092ad..ff1255ce749 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/actions.js
@@ -142,6 +142,7 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
getters,
state,
rootState,
+ rootGetters,
});
return service.commit(rootState.currentProjectId, payload);
diff --git a/app/assets/javascripts/ide/stores/utils.js b/app/assets/javascripts/ide/stores/utils.js
index bcc9ca60d9b..4e7a8765abe 100644
--- a/app/assets/javascripts/ide/stores/utils.js
+++ b/app/assets/javascripts/ide/stores/utils.js
@@ -135,7 +135,14 @@ export const getCommitFiles = stagedFiles =>
});
}, []);
-export const createCommitPayload = ({ branch, getters, newBranch, state, rootState }) => ({
+export const createCommitPayload = ({
+ branch,
+ getters,
+ newBranch,
+ state,
+ rootState,
+ rootGetters,
+}) => ({
branch,
commit_message: state.commitMessage || getters.preBuiltCommitMessage,
actions: getCommitFiles(rootState.stagedFiles).map(f => ({
@@ -146,7 +153,7 @@ export const createCommitPayload = ({ branch, getters, newBranch, state, rootSta
encoding: f.base64 ? 'base64' : 'text',
last_commit_id: newBranch || f.deleted || f.prevPath ? undefined : f.lastCommitSha,
})),
- start_branch: newBranch ? rootState.currentBranchId : undefined,
+ start_sha: newBranch ? rootGetters.lastCommit.short_id : undefined,
});
export const createNewMergeRequestUrl = (projectUrl, source, target) =>
diff --git a/app/assets/javascripts/mr_popover/queries/merge_request.graphql b/app/assets/javascripts/mr_popover/queries/merge_request.graphql
index 0bb9bc03bc7..37d4bc88a69 100644
--- a/app/assets/javascripts/mr_popover/queries/merge_request.graphql
+++ b/app/assets/javascripts/mr_popover/queries/merge_request.graphql
@@ -1,4 +1,4 @@
-query mergeRequest($projectPath: ID!, $mergeRequestIID: ID!) {
+query mergeRequest($projectPath: ID!, $mergeRequestIID: String!) {
project(fullPath: $projectPath) {
mergeRequest(iid: $mergeRequestIID) {
createdAt
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
index abe5bdd2901..34cdb70ce14 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
@@ -49,6 +49,7 @@ export default {
required: false,
default: () => ({
sourceProjectId: '',
+ sourceProjectPath: '',
mergeRequestId: '',
appUrl: '',
}),
@@ -184,11 +185,6 @@ export default {
:link="deploymentExternalUrl"
:css-class="`deploy-link js-deploy-url inline ${slotProps.className}`"
/>
- <visual-review-app-link
- v-if="showVisualReviewApp"
- :link="deploymentExternalUrl"
- :app-metadata="visualReviewAppMeta"
- />
</template>
<template slot="result" slot-scope="slotProps">
@@ -213,12 +209,12 @@ export default {
:link="deploymentExternalUrl"
css-class="js-deploy-url js-deploy-url-feature-flag deploy-link btn btn-default btn-sm inline"
/>
- <visual-review-app-link
- v-if="showVisualReviewApp"
- :link="deploymentExternalUrl"
- :app-metadata="visualReviewAppMeta"
- />
</template>
+ <visual-review-app-link
+ v-if="showVisualReviewApp"
+ :link="deploymentExternalUrl"
+ :app-metadata="visualReviewAppMeta"
+ />
</template>
<span
v-if="deployment.stop_url"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue
index ba9a4d2a187..17ac8ada32d 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue
@@ -53,6 +53,7 @@ export default {
appUrl: this.mr.appUrl,
mergeRequestId: this.mr.iid,
sourceProjectId: this.mr.sourceProjectId,
+ sourceProjectPath: this.mr.sourceProjectFullPath,
};
},
pipeline() {
@@ -85,7 +86,7 @@ export default {
:class="deploymentClass"
:deployment="deployment"
:show-metrics="hasDeploymentMetrics"
- :show-visual-review-app="true"
+ :show-visual-review-app="showVisualReviewAppLink"
:visual-review-app-meta="visualReviewAppMeta"
/>
</div>
diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss
index 0a9c56f5625..3b62121eb0d 100644
--- a/app/assets/stylesheets/pages/settings.scss
+++ b/app/assets/stylesheets/pages/settings.scss
@@ -340,6 +340,11 @@
.deprecated-service {
cursor: default;
+
+ a {
+ font-weight: $gl-font-weight-bold;
+ color: $white-light;
+ }
}
.personal-access-tokens-never-expires-label {
diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb
index 80ee7c35906..ec8077d18e3 100644
--- a/app/controllers/clusters/clusters_controller.rb
+++ b/app/controllers/clusters/clusters_controller.rb
@@ -128,6 +128,7 @@ class Clusters::ClustersController < Clusters::BaseController
:enabled,
:name,
:environment_scope,
+ :managed,
:base_domain,
platform_kubernetes_attributes: [
:api_url,
@@ -140,6 +141,7 @@ class Clusters::ClustersController < Clusters::BaseController
params.require(:cluster).permit(
:enabled,
:environment_scope,
+ :managed,
:base_domain,
platform_kubernetes_attributes: [
:namespace
diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb
index 9cf25915e92..88a0690938a 100644
--- a/app/controllers/concerns/issuable_collections.rb
+++ b/app/controllers/concerns/issuable_collections.rb
@@ -104,6 +104,12 @@ module IssuableCollections
# Used by view to highlight active option
@sort = options[:sort]
+ # When a user looks for an exact iid, we do not filter by search but only by iid
+ if params[:search] =~ /^#(?<iid>\d+)\z/
+ options[:iids] = Regexp.last_match[:iid]
+ params[:search] = nil
+ end
+
if @project
options[:project_id] = @project.id
options[:attempt_project_search_optimizations] = true
diff --git a/app/helpers/services_helper.rb b/app/helpers/services_helper.rb
index d4b50b7ecfb..01ccf163b45 100644
--- a/app/helpers/services_helper.rb
+++ b/app/helpers/services_helper.rb
@@ -39,7 +39,7 @@ module ServicesHelper
end
def disable_fields_service?(service)
- !current_controller?("admin/services") && service.deprecated?
+ service.is_a?(KubernetesService) || (!current_controller?("admin/services") && service.deprecated?)
end
extend self
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index ccc877fb924..8c044c86c47 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -193,21 +193,40 @@ module Clusters
platform_kubernetes.kubeclient if kubernetes?
end
+ ##
+ # This is subtly different to #find_or_initialize_kubernetes_namespace_for_project
+ # below because it will ignore any namespaces that have not got a service account
+ # token. This provides a guarantee that any namespace selected here can be used
+ # for cluster operations - a namespace needs to have a service account configured
+ # before it it can be used.
+ #
+ # This is used for selecting a namespace to use when querying a cluster, or
+ # generating variables to pass to CI.
def kubernetes_namespace_for(project)
- find_or_initialize_kubernetes_namespace_for_project(project).namespace
+ find_or_initialize_kubernetes_namespace_for_project(
+ project, scope: kubernetes_namespaces.has_service_account_token
+ ).namespace
end
- def find_or_initialize_kubernetes_namespace_for_project(project)
+ ##
+ # This is subtly different to #kubernetes_namespace_for because it will include
+ # namespaces that have yet to receive a service account token. This allows
+ # the namespace configuration process to be repeatable - if a namespace has
+ # already been created without a token we don't need to create another
+ # record entirely, just set the token on the pre-existing namespace.
+ #
+ # This is used for configuring cluster namespaces.
+ def find_or_initialize_kubernetes_namespace_for_project(project, scope: kubernetes_namespaces)
attributes = { project: project }
attributes[:cluster_project] = cluster_project if project_type?
- kubernetes_namespaces.find_or_initialize_by(attributes).tap do |namespace|
+ scope.find_or_initialize_by(attributes).tap do |namespace|
namespace.set_defaults
end
end
def allow_user_defined_namespace?
- project_type?
+ project_type? || !managed?
end
def kube_ingress_domain
diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb
index 8e06156c73d..272861cacf0 100644
--- a/app/models/clusters/platforms/kubernetes.rb
+++ b/app/models/clusters/platforms/kubernetes.rb
@@ -80,9 +80,18 @@ module Clusters
.append(key: 'KUBE_CA_PEM_FILE', value: ca_pem, file: true)
end
- if kubernetes_namespace = cluster.kubernetes_namespaces.has_service_account_token.find_by(project: project)
+ if !cluster.managed?
+ project_namespace = namespace.presence || "#{project.path}-#{project.id}".downcase
+
+ variables
+ .append(key: 'KUBE_URL', value: api_url)
+ .append(key: 'KUBE_TOKEN', value: token, public: false, masked: true)
+ .append(key: 'KUBE_NAMESPACE', value: project_namespace)
+ .append(key: 'KUBECONFIG', value: kubeconfig(project_namespace), public: false, file: true)
+
+ elsif kubernetes_namespace = cluster.kubernetes_namespaces.has_service_account_token.find_by(project: project)
variables.concat(kubernetes_namespace.predefined_variables)
- elsif cluster.project_type? || !cluster.managed?
+ elsif cluster.project_type?
# As of 11.11 a user can create a cluster that they manage themselves,
# which replicates the existing project-level cluster behaviour.
# Once we have marked all project-level clusters that make use of this
diff --git a/app/models/project_services/deployment_service.rb b/app/models/project_services/deployment_service.rb
deleted file mode 100644
index 80aa2101509..00000000000
--- a/app/models/project_services/deployment_service.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-# Base class for deployment services
-#
-# These services integrate with a deployment solution like Kubernetes/OpenShift,
-# Mesosphere, etc, to provide additional features to environments.
-class DeploymentService < Service
- default_value_for :category, 'deployment'
-
- def self.supported_events
- %w()
- end
-
- def predefined_variables(project:)
- []
- end
-
- # Environments may have a number of terminals. Should return an array of
- # hashes describing them, e.g.:
- #
- # [{
- # :selectors => {"a" => "b", "foo" => "bar"},
- # :url => "wss://external.example.com/exec",
- # :headers => {"Authorization" => "Token xxx"},
- # :subprotocols => ["foo"],
- # :ca_pem => "----BEGIN CERTIFICATE...", # optional
- # :created_at => Time.now.utc
- # }]
- #
- # Selectors should be a set of values that uniquely identify a particular
- # terminal
- def terminals(environment)
- raise NotImplementedError
- end
-
- def can_test?
- false
- end
-end
diff --git a/app/models/project_services/kubernetes_service.rb b/app/models/project_services/kubernetes_service.rb
index aa6b4aa1d5e..edf7e886e77 100644
--- a/app/models/project_services/kubernetes_service.rb
+++ b/app/models/project_services/kubernetes_service.rb
@@ -5,10 +5,12 @@
# We'll move this class to Clusters::Platforms::Kubernetes, which contains exactly the same logic.
# After we've migrated data, we'll remove KubernetesService. This would happen in a few months.
# If you're modyfiyng this class, please note that you should update the same change in Clusters::Platforms::Kubernetes.
-class KubernetesService < DeploymentService
+class KubernetesService < Service
include Gitlab::Kubernetes
include ReactiveCaching
+ default_value_for :category, 'deployment'
+
self.reactive_cache_key = ->(service) { [service.class.model_name.singular, service.project_id] }
# Namespace defaults to the project path, but can be overridden in case that
@@ -32,7 +34,10 @@ class KubernetesService < DeploymentService
before_validation :enforce_namespace_to_lower_case
- validate :deprecation_validation, unless: :template?
+ attr_accessor :skip_deprecation_validation
+
+ validate :deprecation_validation, unless: :skip_deprecation_validation
+
validates :namespace,
allow_blank: true,
length: 1..63,
@@ -44,6 +49,14 @@ class KubernetesService < DeploymentService
after_save :clear_reactive_cache!
+ def self.supported_events
+ %w()
+ end
+
+ def can_test?
+ false
+ end
+
def initialize_properties
self.properties = {} if properties.nil?
end
@@ -56,11 +69,6 @@ class KubernetesService < DeploymentService
'Kubernetes / OpenShift integration'
end
- def help
- 'To enable terminal access to Kubernetes environments, label your ' \
- 'deployments with `app=$CI_ENVIRONMENT_SLUG`'
- end
-
def self.to_param
'kubernetes'
end
@@ -153,14 +161,25 @@ class KubernetesService < DeploymentService
end
def deprecated?
- !active
+ true
+ end
+
+ def editable?
+ false
end
def deprecation_message
- content = _("Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page") % {
- deprecated_message_content: deprecated_message_content,
- url: Gitlab::Routing.url_helpers.project_clusters_path(project)
- }
+ content = if project
+ _("Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page") % {
+ deprecated_message_content: deprecated_message_content,
+ url: Gitlab::Routing.url_helpers.project_clusters_path(project)
+ }
+ else
+ _("The instance-level Kubernetes service integration is deprecated. Your data has been migrated to an <a href=\"%{url}\"/>instance-level cluster</a>.") % {
+ url: Gitlab::Routing.url_helpers.admin_clusters_path
+ }
+ end
+
content.html_safe
end
@@ -243,10 +262,6 @@ class KubernetesService < DeploymentService
end
def deprecated_message_content
- if active?
- _("Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure")
- else
- _("Fields on this page are now uneditable, you can configure")
- end
+ _("Fields on this page are now uneditable, you can configure")
end
end
diff --git a/app/models/project_services/mock_deployment_service.rb b/app/models/project_services/mock_deployment_service.rb
index 7ab1687f8ba..1103cb11e73 100644
--- a/app/models/project_services/mock_deployment_service.rb
+++ b/app/models/project_services/mock_deployment_service.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
-class MockDeploymentService < DeploymentService
+class MockDeploymentService < Service
+ default_value_for :category, 'deployment'
+
def title
'Mock deployment'
end
@@ -17,4 +19,16 @@ class MockDeploymentService < DeploymentService
def terminals(environment)
[]
end
+
+ def self.supported_events
+ %w()
+ end
+
+ def predefined_variables(project:)
+ []
+ end
+
+ def can_test?
+ false
+ end
end
diff --git a/app/models/service.rb b/app/models/service.rb
index 16fbe6648cc..40033003f3b 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -120,7 +120,7 @@ class Service < ApplicationRecord
end
def self.event_names
- self.supported_events.map { |event| "#{event}_events" }
+ self.supported_events.map { |event| ServicesHelper.service_event_field_name(event) }
end
def event_field(event)
@@ -152,7 +152,7 @@ class Service < ApplicationRecord
end
def self.supported_events
- %w(push tag_push issue confidential_issue merge_request wiki_page)
+ %w(commit push tag_push issue confidential_issue merge_request wiki_page)
end
def execute(data)
diff --git a/app/views/admin/services/_deprecated_message.html.haml b/app/views/admin/services/_deprecated_message.html.haml
new file mode 100644
index 00000000000..fea9506a4bb
--- /dev/null
+++ b/app/views/admin/services/_deprecated_message.html.haml
@@ -0,0 +1,3 @@
+.flash-container.flash-container-page
+ .flash-alert.deprecated-service
+ %span= @service.deprecation_message
diff --git a/app/views/admin/services/_form.html.haml b/app/views/admin/services/_form.html.haml
index 1798b44bbb7..97373a3c350 100644
--- a/app/views/admin/services/_form.html.haml
+++ b/app/views/admin/services/_form.html.haml
@@ -6,5 +6,6 @@
= form_for :service, url: admin_application_settings_service_path, method: :put, html: { class: 'fieldset-form' } do |form|
= render 'shared/service_settings', form: form, subject: @service
- .footer-block.row-content-block
- = form.submit 'Save', class: 'btn btn-success'
+ - unless @service.is_a?(KubernetesService)
+ .footer-block.row-content-block
+ = form.submit 'Save', class: 'btn btn-success'
diff --git a/app/views/admin/services/edit.html.haml b/app/views/admin/services/edit.html.haml
index 512176649e6..79f5ab0d77d 100644
--- a/app/views/admin/services/edit.html.haml
+++ b/app/views/admin/services/edit.html.haml
@@ -1,4 +1,7 @@
- add_to_breadcrumbs "Service Templates", admin_application_settings_services_path
- breadcrumb_title @service.title
- page_title @service.title, "Service Templates"
+
+= render 'deprecated_message' if @service.deprecation_message
+
= render 'form'
diff --git a/app/views/clusters/clusters/gcp/_form.html.haml b/app/views/clusters/clusters/gcp/_form.html.haml
index 70e2eaeaf3b..4d3e3359ea0 100644
--- a/app/views/clusters/clusters/gcp/_form.html.haml
+++ b/app/views/clusters/clusters/gcp/_form.html.haml
@@ -65,15 +65,6 @@
%p.form-text.text-muted
= s_('ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}.').html_safe % { help_link_start_machine_type: help_link_start % { url: machine_type_link_url }, help_link_start_pricing: help_link_start % { url: pricing_link_url }, help_link_end: help_link_end }
- .form-group
- = provider_gcp_field.check_box :legacy_abac, { label: s_('ClusterIntegration|RBAC-enabled cluster'),
- label_class: 'label-bold' }, false, true
- .form-text.text-muted
- = s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
- = s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
- = link_to _('More information'), help_page_path('user/project/clusters/index.md',
- anchor: 'role-based-access-control-rbac-core-only'), target: '_blank'
-
.form-group
= field.check_box :managed, { label: s_('ClusterIntegration|GitLab-managed cluster'),
label_class: 'label-bold' }
diff --git a/app/views/clusters/platforms/kubernetes/_form.html.haml b/app/views/clusters/platforms/kubernetes/_form.html.haml
index c1727cf9079..f2e44462226 100644
--- a/app/views/clusters/platforms/kubernetes/_form.html.haml
+++ b/app/views/clusters/platforms/kubernetes/_form.html.haml
@@ -48,7 +48,7 @@
= s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
.form-group
- = field.check_box :managed, { disabled: true, label: s_('ClusterIntegration|GitLab-managed cluster'),
+ = field.check_box :managed, { label: s_('ClusterIntegration|GitLab-managed cluster'),
label_class: 'label-bold' }
.form-text.text-muted
= s_('ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster.')
diff --git a/app/views/projects/merge_requests/_mr_box.html.haml b/app/views/projects/merge_requests/_mr_box.html.haml
index 7f2c9dcacfd..4f09f47d795 100644
--- a/app/views/projects/merge_requests/_mr_box.html.haml
+++ b/app/views/projects/merge_requests/_mr_box.html.haml
@@ -1,10 +1,10 @@
.detail-page-description
- %h2.title
+ %h2.title.qa-title
= markdown_field(@merge_request, :title)
%div
- if @merge_request.description.present?
- .description{ class: can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : '' }
+ .description.qa-description{ class: can?(current_user, :update_merge_request, @merge_request) ? 'js-task-list-container' : '' }
.md
= markdown_field(@merge_request, :description)
%textarea.hidden.js-task-list-field
diff --git a/app/views/shared/projects/_search_form.html.haml b/app/views/shared/projects/_search_form.html.haml
index 7c7c0a363ac..4365e3f6877 100644
--- a/app/views/shared/projects/_search_form.html.haml
+++ b/app/views/shared/projects/_search_form.html.haml
@@ -1,7 +1,7 @@
- form_field_classes = local_assigns[:admin_view] || !Feature.enabled?(:project_list_filter_bar) ? 'input-short js-projects-list-filter' : ''
- placeholder = local_assigns[:search_form_placeholder] ? search_form_placeholder : 'Filter by name...'
-= form_tag filter_projects_path, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f|
+= form_tag filter_projects_path, method: :get, class: 'project-filter-form qa-project-filter-form', id: 'project-filter-form' do |f|
= search_field_tag :name, params[:name],
placeholder: placeholder,
class: "project-filter-form-field form-control #{form_field_classes}",
diff --git a/changelogs/unreleased/-30974-issue-search-by-number.yml b/changelogs/unreleased/-30974-issue-search-by-number.yml
new file mode 100644
index 00000000000..1e6642ec102
--- /dev/null
+++ b/changelogs/unreleased/-30974-issue-search-by-number.yml
@@ -0,0 +1,5 @@
+---
+title: "Search issuables by iids"
+merge_request: !28302
+author: Riccardo Padovani
+type: fixed
diff --git a/changelogs/unreleased/55362-refresh-blank-service-account-token.yml b/changelogs/unreleased/55362-refresh-blank-service-account-token.yml
new file mode 100644
index 00000000000..3189de97e8b
--- /dev/null
+++ b/changelogs/unreleased/55362-refresh-blank-service-account-token.yml
@@ -0,0 +1,5 @@
+---
+title: Refresh service_account_token for kubernetes_namespaces
+merge_request: 29657
+author:
+type: fixed
diff --git a/changelogs/unreleased/55902-disable-creation-of-non-rbac-kubernetes-clusters.yml b/changelogs/unreleased/55902-disable-creation-of-non-rbac-kubernetes-clusters.yml
new file mode 100644
index 00000000000..2af2d229c6c
--- /dev/null
+++ b/changelogs/unreleased/55902-disable-creation-of-non-rbac-kubernetes-clusters.yml
@@ -0,0 +1,5 @@
+---
+title: Remove support for creating non-RBAC kubernetes clusters
+merge_request: 29614
+author:
+type: removed
diff --git a/changelogs/unreleased/56737-commits-and-mr-events-on-jira-api.yml b/changelogs/unreleased/56737-commits-and-mr-events-on-jira-api.yml
new file mode 100644
index 00000000000..ee2ce8acaeb
--- /dev/null
+++ b/changelogs/unreleased/56737-commits-and-mr-events-on-jira-api.yml
@@ -0,0 +1,5 @@
+---
+title: Expose all current events properly on services API
+merge_request: 29736
+author: Zsolt Kovari
+type: fixed
diff --git a/changelogs/unreleased/59023-fix-web-ide-creating-branches-off-new-commits.yml b/changelogs/unreleased/59023-fix-web-ide-creating-branches-off-new-commits.yml
new file mode 100644
index 00000000000..f7e0ee333aa
--- /dev/null
+++ b/changelogs/unreleased/59023-fix-web-ide-creating-branches-off-new-commits.yml
@@ -0,0 +1,5 @@
+---
+title: Fix IDE commit using latest ref in branch and overriding contents
+merge_request: 29769
+author:
+type: fixed
diff --git a/changelogs/unreleased/60617-allow-switching-from-gitlab-managed-to-unmanaged-clusters.yml b/changelogs/unreleased/60617-allow-switching-from-gitlab-managed-to-unmanaged-clusters.yml
new file mode 100644
index 00000000000..1127dde4fcf
--- /dev/null
+++ b/changelogs/unreleased/60617-allow-switching-from-gitlab-managed-to-unmanaged-clusters.yml
@@ -0,0 +1,5 @@
+---
+title: Allow switching clusters between managed and unmanaged
+merge_request: 29322
+author:
+type: added
diff --git a/changelogs/unreleased/62685-add-index-invite-email-to-members.yml b/changelogs/unreleased/62685-add-index-invite-email-to-members.yml
new file mode 100644
index 00000000000..80bb05e1709
--- /dev/null
+++ b/changelogs/unreleased/62685-add-index-invite-email-to-members.yml
@@ -0,0 +1,5 @@
+---
+title: Add index on invite_email for members
+merge_request: 29768
+author:
+type: performance
diff --git a/changelogs/unreleased/63079-exclude-k8s-namespaces-with-no-service-account-token.yml b/changelogs/unreleased/63079-exclude-k8s-namespaces-with-no-service-account-token.yml
new file mode 100644
index 00000000000..9dc99c8a62f
--- /dev/null
+++ b/changelogs/unreleased/63079-exclude-k8s-namespaces-with-no-service-account-token.yml
@@ -0,0 +1,6 @@
+---
+title: Ensure a Kubernetes namespace is not used for deployments if there is no service
+ account token associated with it
+merge_request: 29643
+author:
+type: fixed
diff --git a/changelogs/unreleased/63261-the-graphql-query-for-the-mr-popover-failes-on-the-frontend.yml b/changelogs/unreleased/63261-the-graphql-query-for-the-mr-popover-failes-on-the-frontend.yml
new file mode 100644
index 00000000000..87d74e3f4b4
--- /dev/null
+++ b/changelogs/unreleased/63261-the-graphql-query-for-the-mr-popover-failes-on-the-frontend.yml
@@ -0,0 +1,6 @@
+---
+title: Make sure we are receiving the proper information on the MR Popover by updating
+ the IID in the graphql query
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/hashed-storage-enabled-default.yml b/changelogs/unreleased/hashed-storage-enabled-default.yml
new file mode 100644
index 00000000000..9a34505785c
--- /dev/null
+++ b/changelogs/unreleased/hashed-storage-enabled-default.yml
@@ -0,0 +1,5 @@
+---
+title: Hashed Storage is enabled by default on new installations
+merge_request: 29586
+author:
+type: changed
diff --git a/changelogs/unreleased/migrate_k8s_service_integration.yml b/changelogs/unreleased/migrate_k8s_service_integration.yml
new file mode 100644
index 00000000000..57f03e6bdab
--- /dev/null
+++ b/changelogs/unreleased/migrate_k8s_service_integration.yml
@@ -0,0 +1,5 @@
+---
+title: Migrate Kubernetes service integration templates to clusters
+merge_request: 28534
+author:
+type: added
diff --git a/changelogs/unreleased/readonly_k8s_integration.yml b/changelogs/unreleased/readonly_k8s_integration.yml
new file mode 100644
index 00000000000..718705e8750
--- /dev/null
+++ b/changelogs/unreleased/readonly_k8s_integration.yml
@@ -0,0 +1,5 @@
+---
+title: Make Kubernetes service templates readonly
+merge_request: 29044
+author:
+type: removed
diff --git a/changelogs/unreleased/visual-review-apps-fix-dropdown.yml b/changelogs/unreleased/visual-review-apps-fix-dropdown.yml
new file mode 100644
index 00000000000..ade68c26df9
--- /dev/null
+++ b/changelogs/unreleased/visual-review-apps-fix-dropdown.yml
@@ -0,0 +1,5 @@
+---
+title: Move Dropdown to Stick to MR View App Button
+merge_request: 29767
+author:
+type: fixed
diff --git a/config/application.rb b/config/application.rb
index c4831b1e638..c5ef6a2c60d 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -47,6 +47,19 @@ module Gitlab
config.generators.templates.push("#{config.root}/generator_templates")
+ ee_paths = config.eager_load_paths.each_with_object([]) do |path, memo|
+ ee_path = config.root.join('ee', Pathname.new(path).relative_path_from(config.root))
+ memo << ee_path.to_s if ee_path.exist?
+ end
+
+ # Eager load should load CE first
+ config.eager_load_paths.push(*ee_paths)
+ config.helpers_paths.push "#{config.root}/ee/app/helpers"
+
+ # Other than Ruby modules we load EE first
+ config.paths['lib/tasks'].unshift "#{config.root}/ee/lib/tasks"
+ config.paths['app/views'].unshift "#{config.root}/ee/app/views"
+
# Rake tasks ignore the eager loading settings, so we need to set the
# autoload paths explicitly
config.autoload_paths = config.eager_load_paths.dup
@@ -162,6 +175,23 @@ module Gitlab
config.assets.paths << "#{config.root}/node_modules/xterm/src/"
config.assets.precompile << "xterm.css"
+ %w[images javascripts stylesheets].each do |path|
+ config.assets.paths << "#{config.root}/ee/app/assets/#{path}"
+ config.assets.precompile << "jira_connect.js"
+ config.assets.precompile << "pages/jira_connect.css"
+ end
+
+ config.assets.paths << "#{config.root}/vendor/assets/javascripts/"
+ config.assets.precompile << "snowplow/sp.js"
+
+ # Compile non-JS/CSS assets in the ee/app/assets folder by default
+ # Mimic sprockets-rails default: https://github.com/rails/sprockets-rails/blob/v3.2.1/lib/sprockets/railtie.rb#L84-L87
+ LOOSE_EE_APP_ASSETS = lambda do |logical_path, filename|
+ filename.start_with?(config.root.join("ee/app/assets").to_s) &&
+ !['.js', '.css', ''].include?(File.extname(logical_path))
+ end
+ config.assets.precompile << LOOSE_EE_APP_ASSETS
+
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
diff --git a/db/migrate/20190527011309_add_required_template_name_to_application_settings.rb b/db/migrate/20190527011309_add_required_template_name_to_application_settings.rb
new file mode 100644
index 00000000000..6cbac0ed507
--- /dev/null
+++ b/db/migrate/20190527011309_add_required_template_name_to_application_settings.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddRequiredTemplateNameToApplicationSettings < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ def change
+ add_column :application_settings, :required_instance_ci_template, :string, null: true
+ end
+end
diff --git a/db/migrate/20190610142825_add_index_to_members_invite_email.rb b/db/migrate/20190610142825_add_index_to_members_invite_email.rb
new file mode 100644
index 00000000000..58157cc5313
--- /dev/null
+++ b/db/migrate/20190610142825_add_index_to_members_invite_email.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddIndexToMembersInviteEmail < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :members, [:invite_email]
+ end
+
+ def down
+ remove_concurrent_index :members, [:invite_email]
+ end
+end
diff --git a/db/migrate/20190613030606_enable_hashed_storage_by_default.rb b/db/migrate/20190613030606_enable_hashed_storage_by_default.rb
new file mode 100644
index 00000000000..8edefd1273e
--- /dev/null
+++ b/db/migrate/20190613030606_enable_hashed_storage_by_default.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class EnableHashedStorageByDefault < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ change_column_default :application_settings, :hashed_storage_enabled, true
+ end
+
+ def down
+ change_column_default :application_settings, :hashed_storage_enabled, false
+ end
+end
diff --git a/db/post_migrate/20190517153211_migrate_k8s_service_integration.rb b/db/post_migrate/20190517153211_migrate_k8s_service_integration.rb
new file mode 100644
index 00000000000..4bd04edb239
--- /dev/null
+++ b/db/post_migrate/20190517153211_migrate_k8s_service_integration.rb
@@ -0,0 +1,104 @@
+# frozen_string_literal: true
+
+class MigrateK8sServiceIntegration < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ class Cluster < ActiveRecord::Base
+ self.table_name = 'clusters'
+
+ has_one :platform_kubernetes, class_name: 'MigrateK8sServiceIntegration::PlatformsKubernetes'
+
+ accepts_nested_attributes_for :platform_kubernetes
+
+ enum cluster_type: {
+ instance_type: 1,
+ group_type: 2,
+ project_type: 3
+ }
+
+ enum platform_type: {
+ kubernetes: 1
+ }
+
+ enum provider_type: {
+ user: 0,
+ gcp: 1
+ }
+ end
+
+ class PlatformsKubernetes < ActiveRecord::Base
+ self.table_name = 'cluster_platforms_kubernetes'
+
+ belongs_to :cluster, class_name: 'MigrateK8sServiceIntegration::Cluster'
+
+ attr_encrypted :token,
+ mode: :per_attribute_iv,
+ key: Settings.attr_encrypted_db_key_base_truncated,
+ algorithm: 'aes-256-cbc'
+ end
+
+ class Service < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'services'
+ self.inheritance_column = :_type_disabled # Disable STI, otherwise KubernetesModel will be looked up
+
+ belongs_to :project, class_name: 'MigrateK8sServiceIntegration::Project', foreign_key: :project_id
+
+ scope :kubernetes_service_templates, -> do
+ where(category: 'deployment', type: 'KubernetesService', template: true)
+ end
+
+ def api_url
+ parsed_properties['api_url'].presence
+ end
+
+ def ca_pem
+ parsed_properties['ca_pem']
+ end
+
+ def namespace
+ parsed_properties['namespace'].presence
+ end
+
+ def token
+ parsed_properties['token'].presence
+ end
+
+ private
+
+ def parsed_properties
+ @parsed_properties ||= JSON.parse(self.properties)
+ end
+ end
+
+ def up
+ has_instance_cluster = Cluster.instance_type.where(enabled: true).exists?
+
+ MigrateK8sServiceIntegration::Service.kubernetes_service_templates.find_each do |service|
+ next unless service.api_url && service.token
+
+ MigrateK8sServiceIntegration::Cluster.create!(
+ enabled: !has_instance_cluster && service.active,
+ managed: false,
+ name: 'KubernetesService',
+ cluster_type: 'instance_type',
+ provider_type: 'user',
+ platform_type: 'kubernetes',
+ platform_kubernetes_attributes: {
+ api_url: service.api_url,
+ ca_cert: service.ca_pem,
+ namespace: service.namespace,
+ token: service.token
+ }
+ )
+ end
+ end
+
+ def down
+ # It is not possible to tell which instance-level clusters were created by
+ # this migration. The original data is intentionally left intact.
+ end
+end
diff --git a/db/post_migrate/20190611161642_add_index_to_events_and_audit_events_created_at_author_id.rb b/db/post_migrate/20190611161642_add_index_to_events_and_audit_events_created_at_author_id.rb
new file mode 100644
index 00000000000..342e83d6322
--- /dev/null
+++ b/db/post_migrate/20190611161642_add_index_to_events_and_audit_events_created_at_author_id.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddIndexToEventsAndAuditEventsCreatedAtAuthorId < ActiveRecord::Migration[5.1]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'analytics_index_%s_on_created_at_and_author_id'.freeze
+ EVENTS_INDEX_NAME = (INDEX_NAME % 'events').freeze
+ AUDIT_EVENTS_INDEX_NAME = (INDEX_NAME % 'audit_events').freeze
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :events, [:created_at, :author_id], name: EVENTS_INDEX_NAME
+ add_concurrent_index :audit_events, [:created_at, :author_id], name: AUDIT_EVENTS_INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :events, EVENTS_INDEX_NAME
+ remove_concurrent_index_by_name :audit_events, AUDIT_EVENTS_INDEX_NAME
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index a50ab02f718..20e0050ac61 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20190611161641) do
+ActiveRecord::Schema.define(version: 20190613030606) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -141,7 +141,7 @@ ActiveRecord::Schema.define(version: 20190611161641) do
t.boolean "help_page_hide_commercial_content", default: false
t.string "help_page_support_url"
t.integer "performance_bar_allowed_group_id"
- t.boolean "hashed_storage_enabled", default: false, null: false
+ t.boolean "hashed_storage_enabled", default: true, null: false
t.boolean "project_export_enabled", default: true, null: false
t.boolean "auto_devops_enabled", default: true, null: false
t.boolean "throttle_unauthenticated_enabled", default: false, null: false
@@ -194,6 +194,7 @@ ActiveRecord::Schema.define(version: 20190611161641) do
t.integer "elasticsearch_replicas", default: 1, null: false
t.text "encrypted_lets_encrypt_private_key"
t.text "encrypted_lets_encrypt_private_key_iv"
+ t.string "required_instance_ci_template"
t.boolean "dns_rebinding_protection_enabled", default: true, null: false
t.boolean "default_project_deletion_protection", default: false, null: false
t.boolean "lock_memberships_to_ldap", default: false, null: false
@@ -335,6 +336,7 @@ ActiveRecord::Schema.define(version: 20190611161641) do
t.text "details"
t.datetime "created_at"
t.datetime "updated_at"
+ t.index ["created_at", "author_id"], name: "analytics_index_audit_events_on_created_at_and_author_id", using: :btree
t.index ["entity_id", "entity_type"], name: "index_audit_events_on_entity_id_and_entity_type", using: :btree
end
@@ -1219,6 +1221,7 @@ ActiveRecord::Schema.define(version: 20190611161641) do
t.string "target_type"
t.index ["action"], name: "index_events_on_action", using: :btree
t.index ["author_id", "project_id"], name: "index_events_on_author_id_and_project_id", using: :btree
+ t.index ["created_at", "author_id"], name: "analytics_index_events_on_created_at_and_author_id", using: :btree
t.index ["project_id", "created_at"], name: "index_events_on_project_id_and_created_at", using: :btree
t.index ["project_id", "id"], name: "index_events_on_project_id_and_id", using: :btree
t.index ["target_type", "target_id"], name: "index_events_on_target_type_and_target_id", using: :btree
@@ -1848,6 +1851,7 @@ ActiveRecord::Schema.define(version: 20190611161641) do
t.boolean "ldap", default: false, null: false
t.boolean "override", default: false, null: false
t.index ["access_level"], name: "index_members_on_access_level", using: :btree
+ t.index ["invite_email"], name: "index_members_on_invite_email", using: :btree
t.index ["invite_token"], name: "index_members_on_invite_token", unique: true, using: :btree
t.index ["requested_at"], name: "index_members_on_requested_at", using: :btree
t.index ["source_id", "source_type"], name: "index_members_on_source_id_and_source_type", using: :btree
diff --git a/doc/administration/repository_storage_types.md b/doc/administration/repository_storage_types.md
index 38842693d73..834b41b3a2c 100644
--- a/doc/administration/repository_storage_types.md
+++ b/doc/administration/repository_storage_types.md
@@ -47,18 +47,12 @@ Any change in the URL will need to be reflected on disk (when groups / users or
projects are renamed). This can add a lot of load in big installations,
especially if using any type of network based filesystem.
-CAUTION: **Caution:**
-For Geo in particular: Geo does work with legacy storage, but in some
-edge cases due to race conditions it can lead to errors when a project is
-renamed multiple times in short succession, or a project is deleted and
-recreated under the same name very quickly. We expect these race events to be
-rare, and we have not observed a race condition side-effect happening yet.
-This pattern also exists in other objects stored in GitLab, like issue
-Attachments, GitLab Pages artifacts, Docker Containers for the integrated
-Registry, etc. Hashed storage is a requirement for Geo.
-
## Hashed Storage
+CAUTION: **Important:**
+Geo requires Hashed Storage since 12.0. If you haven't migrated yet,
+check the [migration instructions](#how-to-migrate-to-hashed-storage) ASAP.
+
Hashed Storage is the new storage behavior we rolled out with 10.0. Instead
of coupling project URL and the folder structure where the repository will be
stored on disk, we are coupling a hash, based on the project's ID. This makes
diff --git a/doc/api/graphql/index.md b/doc/api/graphql/index.md
index 88e657a5d2f..6c1cce620ca 100644
--- a/doc/api/graphql/index.md
+++ b/doc/api/graphql/index.md
@@ -46,7 +46,7 @@ curl --data "value=100" --header "PRIVATE-TOKEN: <your_access_token>" https://gi
A first iteration of a GraphQL API includes the following queries
1. `project` : Within a project it is also possible to fetch a `mergeRequest` by IID.
-1. `group` : Only basic group information is currently supported.
+1. `group` : Basic group information and epics **[ULTIMATE]** are currently supported.
1. `namespace` : Within a namespace it is also possible to fetch `projects`.
### Multiplex queries
diff --git a/doc/api/services.md b/doc/api/services.md
index 898cfad7254..f38f96f64ad 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -22,6 +22,7 @@ Parameters:
| --------- | ---- | -------- | ----------- |
| `api_key` | string | true | User API token. User must have access to task, all comments will be attributed to this user. |
| `restrict_to_branch` | string | false | Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches. |
+| `push_events` | boolean | false | Enable notifications for push events |
### Delete Asana service
@@ -57,6 +58,7 @@ Parameters:
| --------- | ---- | -------- | ----------- |
| `token` | string | true | The authentication token
| `subdomain` | string | false | The subdomain setting |
+| `push_events` | boolean | false | Enable notifications for push events |
### Delete Assembla service
@@ -96,6 +98,7 @@ Parameters:
| `build_key` | string | true | Bamboo build plan key like KEY |
| `username` | string | true | A user with API access, if applicable |
| `password` | string | true | Password of the user |
+| `push_events` | boolean | false | Enable notifications for push events |
### Delete Atlassian Bamboo CI service
@@ -134,6 +137,7 @@ Parameters:
| `project_url` | string | true | Project url |
| `description` | string | false | Description |
| `title` | string | false | Title |
+| `push_events` | boolean | false | Enable notifications for push events |
### Delete Bugzilla Service
@@ -170,6 +174,7 @@ Parameters:
| `token` | string | true | Buildkite project GitLab token |
| `project_url` | string | true | `https://buildkite.com/example/project` |
| `enable_ssl_verification` | boolean | false | Enable SSL verification |
+| `push_events` | boolean | false | Enable notifications for push events |
### Delete Buildkite service
@@ -206,6 +211,7 @@ Parameters:
| `token` | string | true | Campfire token |
| `subdomain` | string | false | Campfire subdomain |
| `room` | string | false | Campfire room |
+| `push_events` | boolean | false | Enable notifications for push events |
### Delete Campfire service
@@ -244,6 +250,7 @@ Parameters:
| `project_url` | string | true | Project url
| `description` | string | false | Description
| `title` | string | false | Title
+| `push_events` | boolean | false | Enable notifications for push events |
### Delete Custom Issue Tracker service
@@ -280,6 +287,10 @@ Parameters:
| `token` | string | true | Drone CI project specific token |
| `drone_url` | string | true | `http://drone.example.com` |
| `enable_ssl_verification` | boolean | false | Enable SSL verification |
+| `push_events` | boolean | false | Enable notifications for push events |
+| `merge_requests_events` | boolean | false | Enable notifications for merge request events |
+| `tag_push_events` | boolean | false | Enable notifications for tag push events |
+
### Delete Drone CI service
@@ -316,6 +327,8 @@ Parameters:
| `recipients` | string | true | Emails separated by whitespace |
| `disable_diffs` | boolean | false | Disable code diffs |
| `send_from_committer_email` | boolean | false | Send from committer |
+| `push_events` | boolean | false | Enable notifications for push events |
+| `tag_push_events` | boolean | false | Enable notifications for tag push events |
### Delete Emails on push service
@@ -384,6 +397,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `token` | string | true | Flowdock Git source token |
+| `push_events` | boolean | false | Enable notifications for push events |
### Delete Flowdock service
@@ -471,6 +485,14 @@ Parameters:
| `room` | string | false |Room name or ID |
| `api_version` | string | false | Leave blank for default (v2) |
| `server` | string | false | Leave blank for default. For example, `https://hipchat.example.com`. |
+| `push_events` | boolean | false | Enable notifications for push events |
+| `issues_events` | boolean | false | Enable notifications for issue events |
+| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events |
+| `merge_requests_events` | boolean | false | Enable notifications for merge request events |
+| `tag_push_events` | boolean | false | Enable notifications for tag push events |
+| `note_events` | boolean | false | Enable notifications for note events |
+| `confidental_note_events` | boolean | false | Enable notifications for confidential note events |
+| `pipeline_events` | boolean | false | Enable notifications for pipeline events |
### Delete HipChat service
@@ -511,6 +533,7 @@ Parameters:
| `server_host` | string | false | localhost |
| `server_port` | integer | false | 6659 |
| `colorize_messages` | boolean | false | Colorize messages |
+| `push_events` | boolean | false | Enable notifications for push events |
### Delete Irker (IRC gateway) service
@@ -562,6 +585,8 @@ Parameters:
| `password` | string | yes | The password of the user created to be used with GitLab/JIRA. |
| `active` | boolean | no | Activates or deactivates the service. Defaults to false (deactivated). |
| `jira_issue_transition_id` | string | no | The ID of a transition that moves issues to a closed state. You can find this number under the JIRA workflow administration (**Administration > Issues > Workflows**) by selecting **View** under **Operations** of the desired workflow of your project. The ID of each state can be found inside the parenthesis of each transition name under the **Transitions (id)** column ([see screenshot][trans]). By default, this ID is set to `2`. |
+| `commit_events` | boolean | false | Enable notifications for commit events |
+| `merge_requests_events` | boolean | false | Enable notifications for merge request events |
### Delete JIRA service
@@ -715,9 +740,14 @@ PUT /projects/:id/services/packagist
Parameters:
-- `username` (**required**)
-- `token` (**required**)
-- `server` (optional)
+| Parameter | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `username` | string | yes | The username of a Packagist account |
+| `token` | string | yes | API token to the Packagist server |
+| `server` | boolean | no | URL of the Packagist server. Leave blank for default: https://packagist.org |
+| `push_events` | boolean | false | Enable notifications for push events |
+| `merge_requests_events` | boolean | false | Enable notifications for merge request events |
+| `tag_push_events` | boolean | false | Enable notifications for tag push events |
### Delete Packagist service
@@ -755,6 +785,7 @@ Parameters:
| `add_pusher` | boolean | no | Add pusher to recipients list |
| `notify_only_broken_pipelines` | boolean | no | Notify only broken pipelines |
| `notify_only_default_branch` | boolean | no | Send notifications only for the default branch ([introduced in GitLab 12.0](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/28271)) |
+| `pipeline_events` | boolean | false | Enable notifications for pipeline events |
### Delete Pipeline-Emails service
@@ -790,6 +821,7 @@ Parameters:
| --------- | ---- | -------- | ----------- |
| `token` | string | true | The PivotalTracker token |
| `restrict_to_branch` | boolean | false | Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches. |
+| `push_events` | boolean | false | Enable notifications for push events |
### Delete PivotalTracker service
@@ -862,6 +894,7 @@ Parameters:
| `priority` | string | true | The priority |
| `device` | string | false | Leave blank for all active devices |
| `sound` | string | false | The sound of the notification |
+| `push_events` | boolean | false | Enable notifications for push events |
### Delete Pushover service
@@ -899,6 +932,7 @@ Parameters:
| `project_url` | string | true | Project url |
| `issues_url` | string | true | Issue url |
| `description` | string | false | Description |
+| `push_events` | boolean | false | Enable notifications for push events |
### Delete Redmine service
@@ -989,6 +1023,15 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `webhook` | string | true | The Microsoft Teams webhook. For example, `https://outlook.office.com/webhook/...` |
+| `push_events` | boolean | false | Enable notifications for push events |
+| `issues_events` | boolean | false | Enable notifications for issue events |
+| `confidential_issues_events` | boolean | false | Enable notifications for confidential issue events |
+| `merge_requests_events` | boolean | false | Enable notifications for merge request events |
+| `tag_push_events` | boolean | false | Enable notifications for tag push events |
+| `note_events` | boolean | false | Enable notifications for note events |
+| `confidental_note_events` | boolean | false | Enable notifications for confidential note events |
+| `pipeline_events` | boolean | false | Enable notifications for pipeline events |
+| `wiki_page_events` | boolean | false | Enable notifications for wiki page events |
### Delete Microsoft Teams service
@@ -1084,6 +1127,7 @@ Parameters:
| `build_type` | string | true | Build configuration ID |
| `username` | string | true | A user with permissions to trigger a manual build |
| `password` | string | true | The password of the user |
+| `push_events` | boolean | false | Enable notifications for push events |
### Delete JetBrains TeamCity CI service
@@ -1230,6 +1274,7 @@ Parameters:
| `issues_url` | string | true | Issue url |
| `project_url` | string | true | Project url |
| `description` | string | false | Description |
+| `push_events` | boolean | false | Enable notifications for push events |
### Delete YouTrack Service
diff --git a/doc/ci/merge_request_pipelines/index.md b/doc/ci/merge_request_pipelines/index.md
index d8c1cefc8df..5adb7ebd30d 100644
--- a/doc/ci/merge_request_pipelines/index.md
+++ b/doc/ci/merge_request_pipelines/index.md
@@ -124,7 +124,7 @@ otherwise pipelines for merged results won't run and your merge requests will be
## Merge Trains **[PREMIUM]**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9186) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.0.
-> This feature is disabled by default until we resolve issues with [contention handling](https://gitlab.com/gitlab-org/gitlab-ee/issues/11222), but [can be enabled manually](#enabling-merge-trains).
+> This feature is disabled by default, but [can be enabled manually](#enabling-merge-trains).
[Pipelines for merged results](#pipelines-for-merged-results-premium) introduces
running a build on the result of the merged code prior to merging, as a way to keep master green.
@@ -142,9 +142,8 @@ If the button is subsequently pressed in a different MR, instead of creating a n
it creates a new pipeline targeting the merge result of the previous MR plus the target branch.
Pipelines invalidated through failures are immediately canceled and requeued.
-CAUTION: **Warning:**
-At this moment, each merge train can generate a merge ref and run a pipeline **one at a time** due to a technical challenge.
-We have [an issue](https://gitlab.com/gitlab-org/gitlab-ee/issues/11222) to tackle this problem to make the pipelines for merged results run in parallel.
+CAUTION: **Caution:**
+At the moment, each merge train can generate a merge ref and run a pipeline **one at a time**. We plan to make the pipelines for merged results [run in parallel](https://gitlab.com/gitlab-org/gitlab-ee/issues/11222) in a future release.
### Enabling Merge Trains
@@ -186,11 +185,6 @@ button while the latest pipeline is running.
![Add to merge train when pipeline succeeds](img/merge_train_start_when_pipeline_succeeds.png)
-### Merge Train's limitations
-
-- At this moment, each merge train can generate a merge ref and run a pipeline **one at a time** due to a technical challenge.
- We have [an issue](https://gitlab.com/gitlab-org/gitlab-ee/issues/11222) to tackle this problem to make the pipelines for merged results run in parallel.
-
## Excluding certain jobs
The behavior of the `only: merge_requests` parameter is such that _only_ jobs with
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 4c170056a49..2759f1c5160 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -2620,6 +2620,24 @@ test:
- pwd
```
+### Nested paths
+
+The value of `GIT_CLONE_PATH` is expanded once and nesting variables
+within it is not supported.
+
+For example, you define both the variables below in your
+`.gitlab-ci.yml` file:
+
+```yml
+variables:
+ GOPATH: $CI_BUILDS_DIR/go
+ GIT_CLONE_PATH: $GOPATH/src/namespace/project
+```
+
+The value of `GIT_CLONE_PATH` is expanded once into
+`$CI_BUILDS_DIR/go/src/namespace/project`, and results in failure
+because `$CI_BUILDS_DIR` is not expanded.
+
## Special YAML features
It's possible to use special YAML features like anchors (`&`), aliases (`*`)
diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md
index 6064c417900..a2f38a2fcdf 100644
--- a/doc/integration/elasticsearch.md
+++ b/doc/integration/elasticsearch.md
@@ -275,19 +275,18 @@ You can also use the `gitlab:elastic:clear_index_status` Rake task to force the
indexer to "forget" all progress, so retrying the indexing process from the
start.
-To index all wikis:
+The `index_projects` command enqueues jobs to index all project and wiki
+repositories, and most database content. However, snippets still need to be
+indexed separately. To do so, run one of these commands:
```sh
# Omnibus installations
-sudo gitlab-rake gitlab:elastic:index_wikis
+sudo gitlab-rake gitlab:elastic:index_snippets
# Installations from source
-bundle exec rake gitlab:elastic:index_wikis RAILS_ENV=production
+bundle exec rake gitlab:elastic:index_snippets RAILS_ENV=production
```
-The wiki indexer also supports the `ID_FROM` and `ID_TO` parameters if you want
-to limit a project set.
-
Enable replication and refreshing again after indexing (only if you previously disabled it):
```bash
@@ -335,14 +334,11 @@ There are several rake tasks available to you via the command line:
- `sudo gitlab-rake gitlab:elastic:create_empty_index`
- `sudo gitlab-rake gitlab:elastic:clear_index_status`
- `sudo gitlab-rake gitlab:elastic:index_projects`
- - `sudo gitlab-rake gitlab:elastic:index_wikis`
- `sudo gitlab-rake gitlab:elastic:index_snippets`
- [sudo gitlab-rake gitlab:elastic:index_projects](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/tasks/gitlab/elastic.rake)
- This iterates over all projects and queues sidekiq jobs to index them in the background.
- [sudo gitlab-rake gitlab:elastic:index_projects_status](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/tasks/gitlab/elastic.rake)
- This determines the overall status of the indexing. It is done by counting the total number of indexed projects, dividing by a count of the total number of projects, then multiplying by 100.
-- [sudo gitlab-rake gitlab:elastic:index_wikis](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/tasks/gitlab/elastic.rake)
- - Iterates over every project, determines if said project contains wiki data, and then indexes the blobs (content) of said wiki data.
- [sudo gitlab-rake gitlab:elastic:create_empty_index](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/tasks/gitlab/elastic.rake)
- This generates an empty index on the Elasticsearch side.
- [sudo gitlab-rake gitlab:elastic:clear_index_status](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/ee/lib/tasks/gitlab/elastic.rake)
diff --git a/doc/user/group/clusters/index.md b/doc/user/group/clusters/index.md
index 3c5e820c1ca..26d764fa2cf 100644
--- a/doc/user/group/clusters/index.md
+++ b/doc/user/group/clusters/index.md
@@ -57,10 +57,6 @@ differentiate the new cluster from the rest.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22011) in GitLab 11.5.
> Became [optional](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/26565) in GitLab 11.11.
-NOTE: **Note:**
-Only available when creating clusters. Existing clusters not managed by GitLab
-cannot become GitLab-managed later.
-
You can choose to allow GitLab to manage your cluster for you. If your cluster is
managed by GitLab, resources for your projects will be automatically created. See the
[Access controls](../../project/clusters/index.md#access-controls) section for details on which resources will
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index dc21db603d6..a4d4fb91f71 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -71,7 +71,6 @@ new Kubernetes cluster to your project:
- **Number of nodes** - Enter the number of nodes you wish the cluster to have.
- **Machine type** - The [machine type](https://cloud.google.com/compute/docs/machine-types)
of the Virtual Machine instance that the cluster will be based on.
- - **RBAC-enabled cluster** - Leave this checked if using default GKE creation options, see the [RBAC section](#rbac-cluster-resources) for more information.
- **GitLab-managed cluster** - Leave this checked if you want GitLab to manage namespaces and service accounts for this cluster. See the [Managed clusters section](#gitlab-managed-clusters) for more information.
1. Finally, click the **Create Kubernetes cluster** button.
@@ -86,6 +85,9 @@ account](#access-controls). Starting from [GitLab
creation process will explicitly request that basic authentication and
client certificate is enabled.
+NOTE: **Note:**
+Starting from [GitLab 12.1](https://gitlab.com/gitlab-org/gitlab-ce/issues/55902), all GKE clusters created by GitLab are RBAC enabled. Take a look at the [RBAC section](#rbac-cluster-resources) for more information.
+
## Adding an existing Kubernetes cluster
To add an existing Kubernetes cluster to your project:
@@ -225,10 +227,6 @@ applications running on the cluster.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22011) in GitLab 11.5.
> Became [optional](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/26565) in GitLab 11.11.
-NOTE: **Note:**
-Only available when creating clusters. Existing clusters not managed by GitLab
-cannot become GitLab-managed later.
-
You can choose to allow GitLab to manage your cluster for you. If your cluster is
managed by GitLab, resources for your projects will be automatically created. See the
[Access controls](#access-controls) section for details on which resources will
diff --git a/doc/user/project/repository/reducing_the_repo_size_using_git.md b/doc/user/project/repository/reducing_the_repo_size_using_git.md
index 35ceb76dc0d..7765a3d7438 100644
--- a/doc/user/project/repository/reducing_the_repo_size_using_git.md
+++ b/doc/user/project/repository/reducing_the_repo_size_using_git.md
@@ -35,16 +35,16 @@ BFG Repo-Cleaner](#using-the-bfg-repo-cleaner). It's faster and simpler than
`git filter-branch`, and GitLab can use its account of what has changed to clean
up its own internal state, maximizing the space saved.
-> **Warning:**
-> Make sure to first make a copy of your repository since rewriting history will
-> purge the files and information you are about to delete. Also make sure to
-> inform any collaborators to not use `pull` after your changes, but use `rebase`.
+CAUTION: **Caution:**
+Make sure to first make a copy of your repository since rewriting history will
+purge the files and information you are about to delete. Also make sure to
+inform any collaborators to not use `pull` after your changes, but use `rebase`.
-> **Warning:**
-> This process is not suitable for removing sensitive data like password or keys
-> from your repository. Information about commits, including file content, is
-> cached in the database, and will remain visible even after they have been
-> removed from the repository.
+CAUTION: **Caution:**
+This process is not suitable for removing sensitive data like password or keys
+from your repository. Information about commits, including file content, is
+cached in the database, and will remain visible even after they have been
+removed from the repository.
## Using the BFG Repo-Cleaner
@@ -99,10 +99,11 @@ up its own internal state, maximizing the space saved.
`git gc` against the repository. You will receive an email once it has
completed.
+NOTE: **Note:**
This process will remove some copies of the rewritten commits from GitLab's
cache and database, but there are still numerous gaps in coverage - at present,
-some of the copies may persist indefinitely. [Clearing the instance cache](../../../administration/raketasks/maintenance.md#clear-redis-cache)
-may help to remove some of them, but it should not be depended on for security
+some of the copies may persist indefinitely. [Clearing the instance cache](../../../administration/raketasks/maintenance.md#clear-redis-cache)
+may help to remove some of them, but it should not be depended on for security
purposes!
## Using `git filter-branch`
diff --git a/doc/workflow/todos.md b/doc/workflow/todos.md
index 32907db4f46..3eac79427cf 100644
--- a/doc/workflow/todos.md
+++ b/doc/workflow/todos.md
@@ -34,6 +34,8 @@ A Todo appears in your Todos dashboard when:
- the author, or
- have set it to automatically merge once pipeline succeeds.
+Todo triggers are not affected by [GitLab Notification Email settings](notifications.md).
+
NOTE: **Note:**
When an user no longer has access to a resource related to a Todo like an issue, merge request, project or group the related Todos, for security reasons, gets deleted within the next hour. The delete is delayed to prevent data loss in case user got their access revoked by mistake.
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 8840accf675..25e9fdd5fce 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -997,7 +997,7 @@ module API
class ProjectService < Grape::Entity
expose :id, :title, :created_at, :updated_at, :active
- expose :push_events, :issues_events, :confidential_issues_events
+ expose :commit_events, :push_events, :issues_events, :confidential_issues_events
expose :merge_requests_events, :tag_push_events, :note_events
expose :confidential_note_events, :pipeline_events, :wiki_page_events
expose :job_events
diff --git a/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb b/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb
index dbdc59505ac..531c9ce4256 100644
--- a/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb
+++ b/lib/gitlab/ci/build/prerequisite/kubernetes_namespace.rb
@@ -9,7 +9,7 @@ module Gitlab
deployment_cluster.present? &&
deployment_cluster.managed? &&
!deployment_cluster.project_type? &&
- kubernetes_namespace.new_record?
+ (kubernetes_namespace.new_record? || kubernetes_namespace.service_account_token.blank?)
end
def complete!
diff --git a/lib/gitlab/ci/config.rb b/lib/gitlab/ci/config.rb
index f187e456993..a0275515906 100644
--- a/lib/gitlab/ci/config.rb
+++ b/lib/gitlab/ci/config.rb
@@ -8,6 +8,12 @@ module Gitlab
class Config
ConfigError = Class.new(StandardError)
+ RESCUE_ERRORS = [
+ Gitlab::Config::Loader::FormatError,
+ Extendable::ExtensionError,
+ External::Processor::IncludeError
+ ].freeze
+
def initialize(config, project: nil, sha: nil, user: nil)
@config = Config::Extendable
.new(build_config(config, project: project, sha: sha, user: user))
@@ -15,9 +21,7 @@ module Gitlab
@global = Entry::Global.new(@config)
@global.compose!
- rescue Gitlab::Config::Loader::FormatError,
- Extendable::ExtensionError,
- External::Processor::IncludeError => e
+ rescue *rescue_errors => e
raise Config::ConfigError, e.message
end
@@ -83,6 +87,11 @@ module Gitlab
user: user,
expandset: Set.new).perform
end
+
+ # Overriden in EE
+ def rescue_errors
+ RESCUE_ERRORS
+ end
end
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 186c4cb2dba..0cabaeabb9a 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -9999,6 +9999,9 @@ msgstr ""
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
+msgid "The instance-level Kubernetes service integration is deprecated. Your data has been migrated to an <a href=\"%{url}\"/>instance-level cluster</a>."
+msgstr ""
+
msgid "The invitation could not be accepted."
msgstr ""
@@ -11943,9 +11946,6 @@ msgstr ""
msgid "Your Groups"
msgstr ""
-msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
-msgstr ""
-
msgid "Your Primary Email will be used for avatar detection."
msgstr ""
diff --git a/qa/Rakefile b/qa/Rakefile
index 7ac018f7286..7ba8a6d68ba 100644
--- a/qa/Rakefile
+++ b/qa/Rakefile
@@ -13,8 +13,9 @@ task :delete_subgroups do
end
desc "Generate Performance Testdata"
-task :generate_perf_testdata do
- QA::Tools::GeneratePerfTestdata.new.run
+task :generate_perf_testdata, :type do |t, args|
+ args.with_defaults(type: :all)
+ QA::Tools::GeneratePerfTestdata.new.method(args[:type]).call
end
desc "Run artillery load tests"
diff --git a/qa/qa/page/dashboard/projects.rb b/qa/qa/page/dashboard/projects.rb
index 7ab8ee39f72..0c23d7cffbb 100644
--- a/qa/qa/page/dashboard/projects.rb
+++ b/qa/qa/page/dashboard/projects.rb
@@ -5,7 +5,7 @@ module QA
module Dashboard
class Projects < Page::Base
view 'app/views/shared/projects/_search_form.html.haml' do
- element :form_filter_by_name, /form_tag.+id: 'project-filter-form'/ # rubocop:disable QA/ElementWithPattern
+ element :project_filter_form, required: true
end
def go_to_project(name)
@@ -14,10 +14,14 @@ module QA
find_link(text: name).click
end
+ def self.path
+ '/'
+ end
+
private
def filter_by_name(name)
- page.within('form#project-filter-form') do
+ within_element(:project_filter_form) do
fill_in :name, with: name
end
end
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index 5aef868a805..6a415b56e50 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -111,6 +111,14 @@ module QA
end
end
+ def has_title?(title)
+ has_element?(:title, text: title)
+ end
+
+ def has_description?(description)
+ has_element?(:description, text: description)
+ end
+
def merge!
# The merge button is disabled on load
wait do
diff --git a/qa/qa/resource/label.rb b/qa/qa/resource/label.rb
index 5a681a5fe9f..3750725c440 100644
--- a/qa/qa/resource/label.rb
+++ b/qa/qa/resource/label.rb
@@ -46,7 +46,7 @@ module QA
end
def api_post_path
- "/projects/#{project}/labels"
+ "/projects/#{project.id}/labels"
end
def api_post_body
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index d706439a891..e8ea947581a 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -18,7 +18,11 @@ module QA
end
attribute :path_with_namespace do
- "#{group.sandbox.path}/#{group.path}/#{name}" if group
+ "#{sandbox_path}#{group.path}/#{name}" if group
+ end
+
+ def sandbox_path
+ group.respond_to?('sandbox') ? "#{group.sandbox.path}/" : ''
end
attribute :repository_ssh_location do
diff --git a/qa/qa/resource/project_milestone.rb b/qa/qa/resource/project_milestone.rb
index 8ace75f695a..70640eac095 100644
--- a/qa/qa/resource/project_milestone.rb
+++ b/qa/qa/resource/project_milestone.rb
@@ -31,6 +31,21 @@ module QA
milestone_new.click_milestone_create_button
end
end
+
+ def api_get_path
+ "/projects/#{project.id}/milestones/#{id}"
+ end
+
+ def api_post_path
+ "/projects/#{project.id}/milestones"
+ end
+
+ def api_post_body
+ {
+ description: @description,
+ title: @title
+ }
+ end
end
end
end
diff --git a/qa/qa/resource/sandbox.rb b/qa/qa/resource/sandbox.rb
index 942eea5cc40..e2b1c4c0831 100644
--- a/qa/qa/resource/sandbox.rb
+++ b/qa/qa/resource/sandbox.rb
@@ -44,6 +44,10 @@ module QA
"/groups/#{path}"
end
+ def api_members_path
+ "#{api_get_path}/members"
+ end
+
def api_post_path
'/groups'
end
diff --git a/qa/qa/runtime/address.rb b/qa/qa/runtime/address.rb
index 98d042fb43a..c622051bb6d 100644
--- a/qa/qa/runtime/address.rb
+++ b/qa/qa/runtime/address.rb
@@ -5,7 +5,7 @@ module QA
class Address
attr_reader :address
- def initialize(instance, page = nil)
+ def initialize(instance, page)
@instance = instance
@address = host + (page.is_a?(String) ? page : page&.path)
end
diff --git a/qa/qa/runtime/browser.rb b/qa/qa/runtime/browser.rb
index 3bf4b3bbbfb..ed0779b93cc 100644
--- a/qa/qa/runtime/browser.rb
+++ b/qa/qa/runtime/browser.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'rspec/core'
+require 'rspec/expectations'
require 'capybara/rspec'
require 'capybara-screenshot/rspec'
require 'selenium-webdriver'
@@ -27,13 +28,12 @@ module QA
# In case of an address that is a symbol we will try to guess address
# based on `Runtime::Scenario#something_address`.
#
- def visit(address, page = nil, &block)
- Browser::Session.new(address, page).perform(&block)
+ def visit(address, page_class, &block)
+ Browser::Session.new(address, page_class).perform(&block)
end
- def self.visit(address, page = nil, &block)
- new.visit(address, page, &block)
- page.validate_elements_present!
+ def self.visit(address, page_class, &block)
+ new.visit(address, page_class, &block)
end
def self.configure!
@@ -128,8 +128,11 @@ module QA
class Session
include Capybara::DSL
- def initialize(instance, page = nil)
- @session_address = Runtime::Address.new(instance, page)
+ attr_reader :page_class
+
+ def initialize(instance, page_class)
+ @session_address = Runtime::Address.new(instance, page_class)
+ @page_class = page_class
end
def url
@@ -139,6 +142,8 @@ module QA
def perform(&block)
visit(url)
+ page_class.validate_elements_present!
+
if QA::Runtime::Env.qa_cookies
browser = Capybara.current_session.driver.browser
QA::Runtime::Env.qa_cookies.each do |cookie|
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index 82510dfa03c..96f337dc081 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -10,13 +10,26 @@ module QA
# The environment variables used to indicate if the environment under test
# supports the given feature
SUPPORTED_FEATURES = {
- git_protocol_v2: 'QA_CAN_TEST_GIT_PROTOCOL_V2'
+ git_protocol_v2: 'QA_CAN_TEST_GIT_PROTOCOL_V2',
+ admin: 'QA_CAN_TEST_ADMIN_FEATURES'
}.freeze
def supported_features
SUPPORTED_FEATURES
end
+ def admin_password
+ ENV['GITLAB_ADMIN_PASSWORD']
+ end
+
+ def admin_username
+ ENV['GITLAB_ADMIN_USERNAME']
+ end
+
+ def admin_personal_access_token
+ ENV['GITLAB_QA_ADMIN_ACCESS_TOKEN']
+ end
+
def debug?
enabled?(ENV['QA_DEBUG'], default: false)
end
@@ -92,14 +105,6 @@ module QA
ENV['GITLAB_PASSWORD']
end
- def admin_username
- ENV['GITLAB_ADMIN_USERNAME']
- end
-
- def admin_password
- ENV['GITLAB_ADMIN_PASSWORD']
- end
-
def github_username
ENV['GITHUB_USERNAME']
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
index cd1c7545944..6969f123f95 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
@@ -1,74 +1,64 @@
# frozen_string_literal: true
module QA
- # Failure issue: https://gitlab.com/gitlab-org/quality/staging/issues/50
- context 'Create', :quarantine do
- describe 'Merge request creation' do
- it 'user creates a new merge request', :smoke do
+ context 'Create' do
+ describe 'Create a new merge request' do
+ before do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.act { sign_in_using_credentials }
+ Page::Main::Login.perform(&:sign_in_using_credentials)
- current_project = Resource::Project.fabricate! do |project|
- project.name = 'project-with-merge-request'
+ @project = Resource::Project.fabricate_via_api! do |project|
+ project.name = 'project'
end
- merge_request_title = 'This is a merge request'
- merge_request_description = 'Great feature'
+ @merge_request_title = 'One merge request to rule them all'
+ @merge_request_description = '... to find them, to bring them all, and in the darkness bind them'
+ end
- Resource::MergeRequest.fabricate! do |merge_request|
- merge_request.title = merge_request_title
- merge_request.description = merge_request_description
- merge_request.project = current_project
+ it 'creates a basic merge request', :smoke do
+ Resource::MergeRequest.fabricate_via_browser_ui! do |merge_request|
+ merge_request.project = @project
+ merge_request.title = @merge_request_title
+ merge_request.description = @merge_request_description
end
- expect(page).to have_content(merge_request_title)
- expect(page).to have_content(merge_request_description)
- expect(page).to have_content('Opened just now')
+ Page::MergeRequest::Show.perform do |merge_request|
+ expect(merge_request).to have_title(@merge_request_title)
+ expect(merge_request).to have_description(@merge_request_description)
+ end
end
- it 'user creates a new merge request with a milestone and label' do
+ it 'creates a merge request with a milestone and label' do
gitlab_account_username = "@#{Runtime::User.username}"
- Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.act { sign_in_using_credentials }
-
- current_project = Resource::Project.fabricate! do |project|
- project.name = 'project-with-merge-request-and-milestone'
- end
-
- current_milestone = Resource::ProjectMilestone.fabricate! do |milestone|
- milestone.title = 'unique-milestone'
- milestone.project = current_project
+ milestone = Resource::ProjectMilestone.fabricate_via_api! do |milestone|
+ milestone.project = @project
+ milestone.title = 'milestone'
end
- new_label = Resource::Label.fabricate_via_browser_ui! do |label|
- label.project = current_project
- label.title = 'qa-mr-test-label'
- label.description = 'Merge Request label'
+ label = Resource::Label.fabricate_via_api! do |label|
+ label.project = @project
+ label.title = 'label'
end
- merge_request_title = 'This is a merge request with a milestone and a label'
- merge_request_description = 'Great feature with milestone'
-
- Resource::MergeRequest.fabricate! do |merge_request|
- merge_request.title = merge_request_title
- merge_request.description = merge_request_description
- merge_request.project = current_project
- merge_request.milestone = current_milestone
+ Resource::MergeRequest.fabricate_via_browser_ui! do |merge_request|
+ merge_request.title = @merge_request_title
+ merge_request.description = @merge_request_description
+ merge_request.project = @project
+ merge_request.milestone = milestone
merge_request.assignee = 'me'
- merge_request.labels.push(new_label)
+ merge_request.labels.push(label)
end
Page::MergeRequest::Show.perform do |merge_request|
- expect(merge_request).to have_content(merge_request_title)
- expect(merge_request).to have_content(merge_request_description)
- expect(merge_request).to have_content('Opened just now')
+ expect(merge_request).to have_title(@merge_request_title)
+ expect(merge_request).to have_description(@merge_request_description)
expect(merge_request).to have_assignee(gitlab_account_username)
- expect(merge_request).to have_label(new_label.title)
+ expect(merge_request).to have_label(label.title)
end
Page::Issuable::Sidebar.perform do |sidebar|
- expect(sidebar).to have_milestone(current_milestone.title)
+ expect(sidebar).to have_milestone(milestone.title)
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb
index 5bfafdfa041..247cde38e52 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb
@@ -1,74 +1,57 @@
# frozen_string_literal: true
module QA
- # Failure issue: https://gitlab.com/gitlab-org/quality/staging/issues/37
- context 'Create', :quarantine do
+ context 'Create', :requires_admin do
describe 'push after setting the file size limit via admin/application_settings' do
- before(:all) do
- push = Resource::Repository::ProjectPush.fabricate! do |p|
- p.file_name = 'README.md'
- p.file_content = '# This is a test project'
- p.commit_message = 'Add README.md'
+ before(:context) do
+ @project = Resource::Project.fabricate_via_api! do |p|
+ p.name = 'project-test-push-limit'
+ p.initialize_with_readme = true
end
- @project = push.project
+ @api_client = Runtime::API::Client.new(:gitlab, personal_access_token: Runtime::Env.admin_personal_access_token)
end
- before do
- Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.perform(&:sign_in_using_credentials)
- end
-
- after(:all) do
+ after(:context) do
# need to set the default value after test
# default value for file size limit is empty
- Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.perform(&:sign_in_using_credentials)
-
- set_file_size_limit('')
-
- Page::Main::Menu.perform(&:sign_out)
+ set_file_size_limit(nil)
end
it 'push successful when the file size is under the limit' do
set_file_size_limit(5)
- expect(page).to have_content("Application settings saved successfully")
-
push = push_new_file('oversize_file_1.bin', wait_for_push: true)
expect(push.output).not_to have_content 'remote: fatal: pack exceeds maximum allowed size'
end
it 'push fails when the file size is above the limit' do
set_file_size_limit(1)
- expect(page).to have_content("Application settings saved successfully")
-
expect { push_new_file('oversize_file_2.bin', wait_for_push: false) }
.to raise_error(QA::Git::Repository::RepositoryCommandError, /remote: fatal: pack exceeds maximum allowed size/)
end
def set_file_size_limit(limit)
- Page::Main::Menu.perform(&:click_admin_area)
- Page::Admin::Menu.perform(&:go_to_general_settings)
+ request = Runtime::API::Request.new(@api_client, '/application/settings')
+ put request.url, receive_max_input_size: limit
- Page::Admin::Settings::General.perform do |setting|
- setting.expand_account_and_limit do |page|
- page.set_max_file_size(limit)
- page.save_settings
- end
- end
+ expect_status(200)
+ expect(json_body).to match(
+ a_hash_including(receive_max_input_size: limit)
+ )
end
def push_new_file(file_name, wait_for_push: true)
- @project.visit!
-
- Resource::Repository::ProjectPush.fabricate! do |p|
- p.project = @project
+ commit_message = 'Adding a new file'
+ output = Resource::Repository::Push.fabricate! do |p|
+ p.repository_http_uri = @project.repository_http_location.uri
p.file_name = file_name
p.file_content = SecureRandom.random_bytes(2000000)
- p.commit_message = 'Adding a new file'
- p.wait_for_push = wait_for_push
+ p.commit_message = commit_message
p.new_branch = false
end
+ @project.wait_for_push commit_message
+
+ output
end
end
end
diff --git a/qa/qa/tools/generate_perf_testdata.rb b/qa/qa/tools/generate_perf_testdata.rb
index de8cfa1aed9..b0477951967 100644
--- a/qa/qa/tools/generate_perf_testdata.rb
+++ b/qa/qa/tools/generate_perf_testdata.rb
@@ -19,26 +19,30 @@ module QA
raise ArgumentError, "Please provide GITLAB_QA_ACCESS_TOKEN" unless ENV['GITLAB_QA_ACCESS_TOKEN']
@api_client = Runtime::API::Client.new(ENV['GITLAB_ADDRESS'], personal_access_token: ENV['GITLAB_QA_ACCESS_TOKEN'])
- @group_name = "gitlab-qa-perf-sandbox-#{SecureRandom.hex(8)}"
- @project_name = "my-test-project-#{SecureRandom.hex(8)}"
+ @group_name = ENV['GROUP_NAME'] || "gitlab-qa-perf-sandbox-#{SecureRandom.hex(8)}"
+ @project_name = ENV['PROJECT_NAME'] || "my-test-project-#{SecureRandom.hex(8)}"
@visibility = "public"
@urls = { host: ENV['GITLAB_ADDRESS'] }
end
- def run
+ def all
STDOUT.puts 'Running...'
group_id = create_group
create_project(group_id)
- create_branch
- add_new_file
+
+ create_many_branches
+ create_many_new_files
+ create_mr_with_many_commits
+
methods_arr = [
- method(:create_issues),
- method(:create_labels),
- method(:create_todos),
- method(:create_merge_requests),
- method(:create_issue_with_500_discussions),
- method(:create_mr_with_large_files)
+ method(:create_many_issues),
+ method(:create_many_labels),
+ method(:create_many_todos),
+ method(:create_many_merge_requests),
+ method(:create_an_issue_with_many_discussions),
+ method(:create_an_mr_with_large_files_and_many_mr_discussions)
]
+
threads_arr = []
methods_arr.each do |m|
@@ -51,103 +55,102 @@ module QA
STDOUT.puts "\nDone"
end
- private
-
def create_group
- group_search_response = post Runtime::API::Request.new(@api_client, "/groups").url, "name=#{@group_name}&path=#{@group_name}&visibility=#{@visibility}"
+ group_search_response = create_a_group_api_req(@group_name, @visibility)
group = JSON.parse(group_search_response.body)
@urls[:group_page] = group["web_url"]
group["id"]
+ STDOUT.puts "Created a group: #{@urls[:group_page]}"
end
def create_project(group_id)
- create_project_response = post Runtime::API::Request.new(@api_client, "/projects").url, "name=#{@project_name}&namespace_id=#{group_id}&visibility=#{@visibility}"
+ create_project_response = create_a_project_api_req(@project_name, group_id, @visibility)
@urls[:project_page] = JSON.parse(create_project_response.body)["web_url"]
+ STDOUT.puts "Created a project: #{@urls[:project_page]}"
end
- def create_issues
+ def create_many_issues
30.times do |i|
- post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/issues").url, "title=issue#{i}&description=desc#{i}"
+ create_an_issue_api_req("#{@group_name}%2F#{@project_name}", "issue#{i}", "desc#{i}")
end
@urls[:issues_list_page] = @urls[:project_page] + "/issues"
- STDOUT.puts "Created Issues"
+ STDOUT.puts "Created many issues: #{@urls[:issues_list_page]}"
end
- def create_todos
+ def create_many_todos
30.times do |i|
- post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/issues/#{i + 1}/todo").url, nil
+ create_a_todo_api_req("#{@group_name}%2F#{@project_name}", "#{i + 1}")
end
@urls[:todos_page] = ENV['GITLAB_ADDRESS'] + "/dashboard/todos"
- STDOUT.puts "Created todos"
+ STDOUT.puts "Created many todos: #{@urls[:todos_page]}"
end
- def create_labels
+ def create_many_labels
30.times do |i|
- post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/labels").url,
- "name=label#{i}&color=#{Faker::Color.hex_color}"
+ create_a_label_api_req("#{@group_name}%2F#{@project_name}", "label#{i}", "#{Faker::Color.hex_color}")
end
@urls[:labels_page] = @urls[:project_page] + "/labels"
- STDOUT.puts "Created labels"
+ STDOUT.puts "Created many labels: #{@urls[:labels_page]}"
end
- def create_merge_requests
+ def create_many_merge_requests
30.times do |i|
- post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/merge_requests").url, "source_branch=branch#{i}&target_branch=master&title=MR#{i}"
+ create_a_merge_request_api_req("#{@group_name}%2F#{@project_name}", "branch#{i}", "master", "MR#{i}")
end
@urls[:mr_list_page] = @urls[:project_page] + "/merge_requests"
- STDOUT.puts "Created MRs"
+ STDOUT.puts "Created many MRs: #{@urls[:mr_list_page]}"
end
- def add_new_file
- post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/repository/files/hello.txt").url, "branch=master&commit_message=\"hello\"&content=\"my new content\""
+ def create_many_new_files
+ create_a_new_file_api_req("hello.txt", "master", "#{@group_name}%2F#{@project_name}", "hello", "my new content")
30.times do |i|
- post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/repository/files/hello#{i}.txt").url, "branch=branch#{i}&commit_message=\"hello\"&content=\"my new content\""
+ create_a_new_file_api_req("hello#{i}.txt", "branch#{i}", "#{@group_name}%2F#{@project_name}", "hello", "my new content")
end
- STDOUT.puts "Added Files"
+
+ @urls[:files_page] = @urls[:project_page] + "/tree/master"
+ STDOUT.puts "Added many new files: #{@urls[:files_page]}"
end
- def create_branch
+ def create_many_branches
30.times do |i|
- post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/repository/branches").url, "branch=branch#{i}&ref=master"
+ create_a_branch_api_req("branch#{i}", "#{@group_name}%2F#{@project_name}")
end
- STDOUT.puts "Created branches"
+ @urls[:branches_page] = @urls[:project_page] + "/-/branches"
+ STDOUT.puts "Created many branches: #{@urls[:branches_page]}"
end
- def create_issue_with_500_discussions
+ def create_an_issue_with_many_discussions
issue_id = 1
500.times do
- post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/issues/#{issue_id}/discussions").url, "body=\"Let us discuss\""
+ create_a_discussion_on_issue_api_req("#{@group_name}%2F#{@project_name}", issue_id, "Let us discuss")
end
- labels_list = (0..15).map {|i| "label#{i}"}.join(',')
+ labels_list = (0..15).map { |i| "label#{i}" }.join(',')
# Add description and labels
- put Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/issues/#{issue_id}").url, "description=#{Faker::Lorem.sentences(500).join(" ")}&labels=#{labels_list}"
+ update_an_issue_api_req("#{@group_name}%2F#{@project_name}", issue_id, "#{Faker::Lorem.sentences(500).join(" ")}", labels_list)
@urls[:large_issue] = @urls[:project_page] + "/issues/#{issue_id}"
- STDOUT.puts "Created Issue with 500 Discussions"
+ STDOUT.puts "Created an issue with many discussions: #{@urls[:large_issue]}"
end
- def create_mr_with_large_files
+ def create_an_mr_with_large_files_and_many_mr_discussions
content_arr = []
16.times do |i|
faker_line_arr = Faker::Lorem.sentences(1500)
content = faker_line_arr.join("\n\r")
- post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/repository/files/hello#{i}.txt").url,
- "branch=master&commit_message=\"Add hello#{i}.txt\"&content=#{content}"
+ create_a_new_file_api_req("hello#{i}.txt", "master", "#{@group_name}%2F#{@project_name}", "Add hello#{i}.txt", content)
content_arr[i] = faker_line_arr
end
- post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/repository/branches").url,
- "branch=performance&ref=master"
+ create_a_branch_api_req("performance", "#{@group_name}%2F#{@project_name}")
16.times do |i|
missed_line_array = content_arr[i].each_slice(2).map(&:first)
content = missed_line_array.join("\n\rIm new!:D \n\r ")
- put Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/repository/files/hello#{i}.txt").url,
- "branch=performance&commit_message=\"Update hello#{i}.txt\"&content=#{content}"
+
+ update_file_api_req("hello#{i}.txt", "performance", "#{@group_name}%2F#{@project_name}", "Update hello#{i}.txt", content)
end
- create_mr_response = post Runtime::API::Request.new(@api_client, """/projects/#{@group_name}%2F#{@project_name}/merge_requests""").url,
- "source_branch=performance&target_branch=master&title=Large_MR"
+ create_mr_response = create_a_merge_request_api_req("#{@group_name}%2F#{@project_name}", "performance", "master", "Large_MR")
iid = JSON.parse(create_mr_response.body)["iid"]
diff_refs = JSON.parse(create_mr_response.body)["diff_refs"]
@@ -161,8 +164,8 @@ module QA
if should_resolve
discussion_id = JSON.parse(create_diff_note_response.body)["id"]
- put Runtime::API::Request.new(@api_client, """/projects/#{@group_name}%2F#{@project_name}/merge_requests/#{iid}/discussions/#{discussion_id}""").url,
- "resolved=true"
+
+ update_a_discussion_on_issue_api_req("#{@group_name}%2F#{@project_name}", iid, discussion_id, "true")
end
should_resolve ^= true
@@ -171,23 +174,93 @@ module QA
# Add discussions to main tab
100.times do
- post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/merge_requests/#{iid}/discussions").url,
- "body=\"Let us discuss\""
+ create_a_discussion_on_mr_api_req("#{@group_name}%2F#{@project_name}", iid, "Let us discuss")
end
@urls[:large_mr] = JSON.parse(create_mr_response.body)["web_url"]
- STDOUT.puts "Created MR with 500 Discussions and 20 Very Large Files"
+ STDOUT.puts "Created an MR with many discussions and many very large Files: #{@urls[:large_mr]}"
end
def create_diff_note(iid, file_count, line_count, head_sha, start_sha, base_sha, line_type)
post Runtime::API::Request.new(@api_client, "/projects/#{@group_name}%2F#{@project_name}/merge_requests/#{iid}/discussions").url,
- """body=\"Let us discuss\"&
+ "" "body=\"Let us discuss\"&
position[position_type]=text&
position[new_path]=hello#{file_count}.txt&
position[old_path]=hello#{file_count}.txt&
position[#{line_type}]=#{line_count * 100}&
position[head_sha]=#{head_sha}&
position[start_sha]=#{start_sha}&
- position[base_sha]=#{base_sha}"""
+ position[base_sha]=#{base_sha}" ""
+ end
+
+ def create_mr_with_many_commits
+ project_path = "#{@group_name}%2F#{@project_name}"
+ branch_name = "branch_with_many_commits-#{SecureRandom.hex(8)}"
+ file_name = "file_for_many_commits.txt"
+ create_a_branch_api_req(branch_name, project_path)
+ create_a_new_file_api_req(file_name, branch_name, project_path, "Initial commit for new file", "Initial file content")
+ create_mr_response = create_a_merge_request_api_req(project_path, branch_name, "master", "MR with many commits-#{SecureRandom.hex(8)}")
+ @urls[:mr_with_many_commits] = JSON.parse(create_mr_response.body)["web_url"]
+ 100.times do |i|
+ update_file_api_req(file_name, branch_name, project_path, Faker::Lorem.sentences(5).join(" "), Faker::Lorem.sentences(500).join("\n"))
+ end
+ STDOUT.puts "Created an MR with many commits: #{@urls[:mr_with_many_commits]}"
+ end
+
+ private
+
+ # API Requests
+
+ def create_a_discussion_on_issue_api_req(project_path_or_id, issue_id, body)
+ post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/issues/#{issue_id}/discussions").url, "body=\"#{body}\""
+ end
+
+ def update_a_discussion_on_issue_api_req(project_path_or_id, mr_iid, discussion_id, resolved_status)
+ put Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/merge_requests/#{mr_iid}/discussions/#{discussion_id}").url, "resolved=#{resolved_status}"
+ end
+
+ def create_a_discussion_on_mr_api_req(project_path_or_id, mr_iid, body)
+ post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/merge_requests/#{mr_iid}/discussions").url,
+ "body=\"#{body}\""
+ end
+
+ def create_a_label_api_req(project_path_or_id, name, color)
+ post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/labels").url, "name=#{name}&color=#{color}"
+ end
+
+ def create_a_todo_api_req(project_path_or_id, issue_id)
+ post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/issues/#{issue_id}/todo").url, nil
+ end
+
+ def create_an_issue_api_req(project_path_or_id, title, description)
+ post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/issues").url, "title=#{title}&description=#{description}"
+ end
+
+ def update_an_issue_api_req(project_path_or_id, issue_id, description, labels_list)
+ put Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/issues/#{issue_id}").url, "description=#{description}&labels=#{labels_list}"
+ end
+
+ def create_a_project_api_req(project_name, group_id, visibility)
+ post Runtime::API::Request.new(@api_client, "/projects").url, "name=#{project_name}&namespace_id=#{group_id}&visibility=#{visibility}"
+ end
+
+ def create_a_group_api_req(group_name, visibility)
+ post Runtime::API::Request.new(@api_client, "/groups").url, "name=#{group_name}&path=#{group_name}&visibility=#{visibility}"
+ end
+
+ def create_a_branch_api_req(branch_name, project_path_or_id)
+ post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/repository/branches").url, "branch=#{branch_name}&ref=master"
+ end
+
+ def create_a_new_file_api_req(file_path, branch_name, project_path_or_id, commit_message, content)
+ post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/repository/files/#{file_path}").url, "branch=#{branch_name}&commit_message=\"#{commit_message}\"&content=\"#{content}\""
+ end
+
+ def create_a_merge_request_api_req(project_path_or_id, source_branch, target_branch, mr_title)
+ post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/merge_requests").url, "source_branch=#{source_branch}&target_branch=#{target_branch}&title=#{mr_title}"
+ end
+
+ def update_file_api_req(file_path, branch_name, project_path_or_id, commit_message, content)
+ put Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/repository/files/#{file_path}").url, "branch=#{branch_name}&commit_message=\"#{commit_message}\"&content=\"#{content}\""
end
end
end
diff --git a/qa/spec/runtime/env_spec.rb b/qa/spec/runtime/env_spec.rb
index 2560695ef2e..caf96a213e1 100644
--- a/qa/spec/runtime/env_spec.rb
+++ b/qa/spec/runtime/env_spec.rb
@@ -227,6 +227,12 @@ describe QA::Runtime::Env do
env_key: 'QA_CAN_TEST_GIT_PROTOCOL_V2',
default: true
+ it_behaves_like 'boolean method with parameter',
+ method: :can_test?,
+ param: :admin,
+ env_key: 'QA_CAN_TEST_ADMIN_FEATURES',
+ default: true
+
it 'raises ArgumentError if feature is unknown' do
expect { described_class.can_test? :foo }.to raise_error(ArgumentError, 'Unknown feature "foo"')
end
diff --git a/qa/spec/specs/runner_spec.rb b/qa/spec/specs/runner_spec.rb
index 5c86c102105..f94145d148e 100644
--- a/qa/spec/specs/runner_spec.rb
+++ b/qa/spec/specs/runner_spec.rb
@@ -1,16 +1,22 @@
# frozen_string_literal: true
+require 'active_support/core_ext/hash'
+
describe QA::Specs::Runner do
+ shared_examples 'excludes orchestrated' do
+ it 'excludes the orchestrated tag and includes default args' do
+ expect_rspec_runner_arguments(['--tag', '~orchestrated', *described_class::DEFAULT_TEST_PATH_ARGS])
+
+ subject.perform
+ end
+ end
+
context '#perform' do
before do
allow(QA::Runtime::Browser).to receive(:configure!)
end
- it 'excludes the orchestrated tag by default' do
- expect_rspec_runner_arguments(['--tag', '~orchestrated', *described_class::DEFAULT_TEST_PATH_ARGS])
-
- subject.perform
- end
+ it_behaves_like 'excludes orchestrated'
context 'when tty is set' do
subject { described_class.new.tap { |runner| runner.tty = true } }
@@ -67,8 +73,6 @@ describe QA::Specs::Runner do
allow(QA::Runtime::Env).to receive(:signup_disabled?).and_return(true)
end
- subject { described_class.new }
-
it 'includes default args and excludes the skip_signup_disabled tag' do
expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~skip_signup_disabled', *described_class::DEFAULT_TEST_PATH_ARGS])
@@ -76,18 +80,54 @@ describe QA::Specs::Runner do
end
end
- context 'when git protocol v2 is not supported' do
- before do
- allow(QA::Runtime::Env).to receive(:can_test?).with(:git_protocol_v2).and_return(false)
+ context 'testable features' do
+ shared_examples 'one supported feature' do |feature|
+ before do
+ QA::Runtime::Env.supported_features.each do |tag, _|
+ allow(QA::Runtime::Env).to receive(:can_test?).with(tag).and_return(false)
+ end
+
+ allow(QA::Runtime::Env).to receive(:can_test?).with(feature).and_return(true) unless feature.nil?
+ end
+
+ it 'includes default args and excludes all unsupported tags' do
+ expect_rspec_runner_arguments(['--tag', '~orchestrated', *excluded_feature_tags_except(feature), *described_class::DEFAULT_TEST_PATH_ARGS])
+
+ subject.perform
+ end
end
- subject { described_class.new }
+ context 'when only git protocol 2 is supported' do
+ it_behaves_like 'one supported feature', :git_protocol_v2
+ end
- it 'includes default args and excludes the requires_git_protocol_v2 tag' do
- expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~requires_git_protocol_v2', *described_class::DEFAULT_TEST_PATH_ARGS])
+ context 'when only admin features are supported' do
+ it_behaves_like 'one supported feature', :admin
+ end
- subject.perform
+ context 'when no features are supported' do
+ it_behaves_like 'one supported feature', nil
end
+
+ context 'when all features are supported' do
+ before do
+ QA::Runtime::Env.supported_features.each do |tag, _|
+ allow(QA::Runtime::Env).to receive(:can_test?).with(tag).and_return(true)
+ end
+ end
+
+ it_behaves_like 'excludes orchestrated'
+ end
+
+ context 'when features are not specified' do
+ it_behaves_like 'excludes orchestrated'
+ end
+ end
+
+ def excluded_feature_tags_except(tag)
+ QA::Runtime::Env.supported_features.except(tag).map do |tag, _|
+ ['--tag', "~requires_#{tag}"]
+ end.flatten
end
def expect_rspec_runner_arguments(arguments)
diff --git a/spec/controllers/admin/clusters_controller_spec.rb b/spec/controllers/admin/clusters_controller_spec.rb
index 7b77cb186a4..7709f525119 100644
--- a/spec/controllers/admin/clusters_controller_spec.rb
+++ b/spec/controllers/admin/clusters_controller_spec.rb
@@ -396,6 +396,7 @@ describe Admin::ClustersController do
cluster: {
enabled: false,
name: 'my-new-cluster-name',
+ managed: false,
base_domain: domain
}
}
@@ -409,6 +410,7 @@ describe Admin::ClustersController do
expect(flash[:notice]).to eq('Kubernetes cluster was successfully updated.')
expect(cluster.enabled).to be_falsey
expect(cluster.name).to eq('my-new-cluster-name')
+ expect(cluster).not_to be_managed
expect(cluster.domain).to eq('test-domain.com')
end
@@ -433,6 +435,7 @@ describe Admin::ClustersController do
cluster: {
enabled: false,
name: 'my-new-cluster-name',
+ managed: false,
domain: domain
}
}
@@ -445,6 +448,7 @@ describe Admin::ClustersController do
expect(response).to have_http_status(:no_content)
expect(cluster.enabled).to be_falsey
expect(cluster.name).to eq('my-new-cluster-name')
+ expect(cluster).not_to be_managed
end
end
diff --git a/spec/controllers/concerns/issuable_collections_spec.rb b/spec/controllers/concerns/issuable_collections_spec.rb
index fb2cd5ca955..f210537aad5 100644
--- a/spec/controllers/concerns/issuable_collections_spec.rb
+++ b/spec/controllers/concerns/issuable_collections_spec.rb
@@ -180,5 +180,16 @@ describe IssuableCollections do
is_expected.not_to include('invalid_param', 'invalid_array')
end
end
+
+ context 'search using an issue iid' do
+ let(:params) { { search: "#5" } }
+
+ it 'mutates the search into a filter by iid' do
+ is_expected.to include({
+ 'iids' => '5',
+ 'search' => nil
+ })
+ end
+ end
end
end
diff --git a/spec/controllers/groups/clusters_controller_spec.rb b/spec/controllers/groups/clusters_controller_spec.rb
index 7349cb7094c..2f64c7f3460 100644
--- a/spec/controllers/groups/clusters_controller_spec.rb
+++ b/spec/controllers/groups/clusters_controller_spec.rb
@@ -463,6 +463,7 @@ describe Groups::ClustersController do
cluster: {
enabled: false,
name: 'my-new-cluster-name',
+ managed: false,
base_domain: domain
}
}
@@ -476,6 +477,7 @@ describe Groups::ClustersController do
expect(flash[:notice]).to eq('Kubernetes cluster was successfully updated.')
expect(cluster.enabled).to be_falsey
expect(cluster.name).to eq('my-new-cluster-name')
+ expect(cluster).not_to be_managed
expect(cluster.domain).to eq('test-domain.com')
end
@@ -500,6 +502,7 @@ describe Groups::ClustersController do
cluster: {
enabled: false,
name: 'my-new-cluster-name',
+ managed: false,
domain: domain
}
}
@@ -512,6 +515,7 @@ describe Groups::ClustersController do
expect(response).to have_http_status(:no_content)
expect(cluster.enabled).to be_falsey
expect(cluster.name).to eq('my-new-cluster-name')
+ expect(cluster).not_to be_managed
end
end
diff --git a/spec/controllers/projects/branches_controller_spec.rb b/spec/controllers/projects/branches_controller_spec.rb
index c778b7888dc..cf201c9f735 100644
--- a/spec/controllers/projects/branches_controller_spec.rb
+++ b/spec/controllers/projects/branches_controller_spec.rb
@@ -123,7 +123,11 @@ describe Projects::BranchesController do
expect(response).to redirect_to project_tree_path(project, branch)
end
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
+ context 'when user configured kubernetes from CI/CD > Clusters' do
+ before do
+ create(:cluster, :provided_by_gcp, projects: [project])
+ end
+
it 'redirects to autodeploy setup page' do
result = { status: :success, branch: double(name: branch) }
@@ -143,22 +147,6 @@ describe Projects::BranchesController do
end
end
- context 'when user configured kubernetes from Integration > Kubernetes' do
- before do
- project.services << build(:kubernetes_service)
- end
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
- context 'when user configured kubernetes from CI/CD > Clusters' do
- before do
- create(:cluster, :provided_by_gcp, projects: [project])
- end
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
it 'redirects to autodeploy setup page' do
result = { status: :success, branch: double(name: branch) }
diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb
index 8d37bd82d21..fa49438287f 100644
--- a/spec/controllers/projects/clusters_controller_spec.rb
+++ b/spec/controllers/projects/clusters_controller_spec.rb
@@ -449,6 +449,7 @@ describe Projects::ClustersController do
cluster: {
enabled: false,
name: 'my-new-cluster-name',
+ managed: false,
platform_kubernetes_attributes: {
namespace: 'my-namespace'
}
@@ -464,6 +465,7 @@ describe Projects::ClustersController do
expect(flash[:notice]).to eq('Kubernetes cluster was successfully updated.')
expect(cluster.enabled).to be_falsey
expect(cluster.name).to eq('my-new-cluster-name')
+ expect(cluster).not_to be_managed
expect(cluster.platform_kubernetes.namespace).to eq('my-namespace')
end
@@ -475,6 +477,7 @@ describe Projects::ClustersController do
cluster: {
enabled: false,
name: 'my-new-cluster-name',
+ managed: false,
platform_kubernetes_attributes: {
namespace: 'my-namespace'
}
@@ -489,6 +492,7 @@ describe Projects::ClustersController do
expect(response).to have_http_status(:no_content)
expect(cluster.enabled).to be_falsey
expect(cluster.name).to eq('my-new-cluster-name')
+ expect(cluster).not_to be_managed
expect(cluster.platform_kubernetes.namespace).to eq('my-namespace')
end
end
diff --git a/spec/controllers/projects/services_controller_spec.rb b/spec/controllers/projects/services_controller_spec.rb
index 3608d175d50..5c7f8d95f82 100644
--- a/spec/controllers/projects/services_controller_spec.rb
+++ b/spec/controllers/projects/services_controller_spec.rb
@@ -141,20 +141,6 @@ describe Projects::ServicesController do
end
end
- context 'with a deprecated service' do
- let(:service) { create(:kubernetes_service, project: project) }
-
- before do
- put :update,
- params: { namespace_id: project.namespace, project_id: project, id: service.to_param, service: { namespace: 'updated_namespace' } }
- end
-
- it 'does not update the service' do
- service.reload
- expect(service.namespace).not_to eq('updated_namespace')
- end
- end
-
context 'when activating JIRA service from a template' do
let(:template_service) { create(:jira_service, project: project, template: true) }
@@ -168,20 +154,10 @@ describe Projects::ServicesController do
describe "GET #edit" do
before do
- get :edit, params: { namespace_id: project.namespace, project_id: project, id: service_id }
+ get :edit, params: { namespace_id: project.namespace, project_id: project, id: 'jira' }
end
context 'with approved services' do
- let(:service_id) { 'jira' }
-
- it 'renders edit page' do
- expect(response).to be_success
- end
- end
-
- context 'with a deprecated service' do
- let(:service_id) { 'kubernetes' }
-
it 'renders edit page' do
expect(response).to be_success
end
diff --git a/spec/factories/clusters/kubernetes_namespaces.rb b/spec/factories/clusters/kubernetes_namespaces.rb
index 3b50a57433f..042be7b4c4a 100644
--- a/spec/factories/clusters/kubernetes_namespaces.rb
+++ b/spec/factories/clusters/kubernetes_namespaces.rb
@@ -16,5 +16,9 @@ FactoryBot.define do
trait :with_token do
service_account_token { FFaker::Lorem.characters(10) }
end
+
+ trait :without_token do
+ service_account_token nil
+ end
end
end
diff --git a/spec/factories/services.rb b/spec/factories/services.rb
index 0d8c26a2ee9..763909f30bd 100644
--- a/spec/factories/services.rb
+++ b/spec/factories/services.rb
@@ -24,6 +24,8 @@ FactoryBot.define do
api_url: 'https://kubernetes.example.com',
token: 'a' * 40
})
+
+ skip_deprecation_validation true
end
factory :mock_deployment_service do
diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb
index 83e582c34f0..e4a3a1a8c92 100644
--- a/spec/features/projects/clusters/gcp_spec.rb
+++ b/spec/features/projects/clusters/gcp_spec.rb
@@ -79,10 +79,6 @@ describe 'Gcp Cluster', :js do
expect(page).to have_content('Something wrong!')
end
-
- it 'user sees RBAC is enabled by default' do
- expect(page).to have_checked_field('RBAC-enabled cluster')
- end
end
context 'when user filled form with invalid parameters' do
diff --git a/spec/features/projects/clusters/interchangeability_spec.rb b/spec/features/projects/clusters/interchangeability_spec.rb
deleted file mode 100644
index 0033e12b6b1..00000000000
--- a/spec/features/projects/clusters/interchangeability_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require 'spec_helper'
-
-describe 'Interchangeability between KubernetesService and Platform::Kubernetes' do
- EXCEPT_METHODS = %i[test title description help fields initialize_properties namespace namespace= api_url api_url= deprecated? deprecation_message].freeze
- EXCEPT_METHODS_GREP_V = %w[_touched? _changed? _was].freeze
-
- it 'Clusters::Platform::Kubernetes covers core interfaces in KubernetesService' do
- expected_interfaces = KubernetesService.instance_methods(false)
- expected_interfaces = expected_interfaces - EXCEPT_METHODS
- EXCEPT_METHODS_GREP_V.each do |g|
- expected_interfaces = expected_interfaces.grep_v(/#{Regexp.escape(g)}\z/)
- end
-
- expect(expected_interfaces - Clusters::Platforms::Kubernetes.instance_methods).to be_empty
- end
-end
diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb
index da4ef6428d4..fbaf12be64e 100644
--- a/spec/features/projects/environments/environment_spec.rb
+++ b/spec/features/projects/environments/environment_spec.rb
@@ -155,7 +155,10 @@ describe 'Environment' do
end
context 'with terminal' do
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
+ context 'when user configured kubernetes from CI/CD > Clusters' do
+ let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.project }
+
context 'for project maintainer' do
let(:role) { :maintainer }
@@ -191,19 +194,6 @@ describe 'Environment' do
end
end
end
-
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project, :test_repo) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
- context 'when user configured kubernetes from CI/CD > Clusters' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:project) { cluster.project }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
end
context 'when environment is available' do
diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb
index 7b7e45312d9..1b5d9083932 100644
--- a/spec/features/projects/environments/environments_spec.rb
+++ b/spec/features/projects/environments/environments_spec.rb
@@ -248,7 +248,10 @@ describe 'Environments page', :js do
end
context 'when kubernetes terminal is available' do
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
+ context 'when user configured kubernetes from CI/CD > Clusters' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, projects: [create(:project, :repository)]) }
+ let(:project) { cluster.project }
+
context 'for project maintainer' do
let(:role) { :maintainer }
@@ -265,19 +268,6 @@ describe 'Environments page', :js do
end
end
end
-
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project, :test_repo) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
- context 'when user configured kubernetes from CI/CD > Clusters' do
- let(:cluster) { create(:cluster, :provided_by_gcp, projects: [create(:project, :repository)]) }
- let(:project) { cluster.project }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
end
end
diff --git a/spec/finders/fork_projects_finder_spec.rb b/spec/finders/fork_projects_finder_spec.rb
index b3fdffc3331..98cff37205e 100644
--- a/spec/finders/fork_projects_finder_spec.rb
+++ b/spec/finders/fork_projects_finder_spec.rb
@@ -12,6 +12,8 @@ describe ForkProjectsFinder do
let(:private_fork_member) { create(:user) }
before do
+ stub_feature_flags(object_pools: { enabled: false, thing: source_project })
+
private_fork.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
private_fork.add_developer(private_fork_member)
diff --git a/spec/frontend/ide/services/index_spec.js b/spec/frontend/ide/services/index_spec.js
new file mode 100644
index 00000000000..499fa8fc012
--- /dev/null
+++ b/spec/frontend/ide/services/index_spec.js
@@ -0,0 +1,55 @@
+import services from '~/ide/services';
+import Api from '~/api';
+
+jest.mock('~/api');
+
+const TEST_PROJECT_ID = 'alice/wonderland';
+const TEST_BRANCH = 'master-patch-123';
+const TEST_COMMIT_SHA = '123456789';
+
+describe('IDE services', () => {
+ describe('commit', () => {
+ let payload;
+
+ beforeEach(() => {
+ payload = {
+ branch: TEST_BRANCH,
+ commit_message: 'Hello world',
+ actions: [],
+ start_sha: undefined,
+ };
+
+ Api.createBranch.mockReturnValue(Promise.resolve());
+ Api.commitMultiple.mockReturnValue(Promise.resolve());
+ });
+
+ describe.each`
+ startSha | shouldCreateBranch
+ ${undefined} | ${false}
+ ${TEST_COMMIT_SHA} | ${true}
+ `('when start_sha is $startSha', ({ startSha, shouldCreateBranch }) => {
+ beforeEach(() => {
+ payload.start_sha = startSha;
+
+ return services.commit(TEST_PROJECT_ID, payload);
+ });
+
+ if (shouldCreateBranch) {
+ it('should create branch', () => {
+ expect(Api.createBranch).toHaveBeenCalledWith(TEST_PROJECT_ID, {
+ ref: TEST_COMMIT_SHA,
+ branch: TEST_BRANCH,
+ });
+ });
+ } else {
+ it('should not create branch', () => {
+ expect(Api.createBranch).not.toHaveBeenCalled();
+ });
+ }
+
+ it('should commit', () => {
+ expect(Api.commitMultiple).toHaveBeenCalledWith(TEST_PROJECT_ID, payload);
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/ide/stores/modules/commit/actions_spec.js b/spec/javascripts/ide/stores/modules/commit/actions_spec.js
index 5f7272311c8..8a3c132972e 100644
--- a/spec/javascripts/ide/stores/modules/commit/actions_spec.js
+++ b/spec/javascripts/ide/stores/modules/commit/actions_spec.js
@@ -6,9 +6,11 @@ import eventHub from '~/ide/eventhub';
import consts from '~/ide/stores/modules/commit/constants';
import * as mutationTypes from '~/ide/stores/modules/commit/mutation_types';
import * as actions from '~/ide/stores/modules/commit/actions';
-import testAction from '../../../../helpers/vuex_action_helper';
import { commitActionTypes } from '~/ide/constants';
import { resetStore, file } from 'spec/ide/helpers';
+import testAction from '../../../../helpers/vuex_action_helper';
+
+const TEST_COMMIT_SHA = '123456789';
describe('IDE commit module actions', () => {
beforeEach(() => {
@@ -139,6 +141,9 @@ describe('IDE commit module actions', () => {
branches: {
master: {
workingReference: '',
+ commit: {
+ short_id: TEST_COMMIT_SHA,
+ },
},
},
};
@@ -239,6 +244,9 @@ describe('IDE commit module actions', () => {
branches: {
master: {
workingReference: '1',
+ commit: {
+ short_id: TEST_COMMIT_SHA,
+ },
},
},
};
@@ -247,7 +255,7 @@ describe('IDE commit module actions', () => {
...file('changed'),
type: 'blob',
active: true,
- lastCommitSha: '123456789',
+ lastCommitSha: TEST_COMMIT_SHA,
};
store.state.stagedFiles.push(f);
store.state.changedFiles = [
@@ -307,7 +315,7 @@ describe('IDE commit module actions', () => {
previous_path: undefined,
},
],
- start_branch: 'master',
+ start_sha: TEST_COMMIT_SHA,
});
done();
@@ -330,11 +338,11 @@ describe('IDE commit module actions', () => {
file_path: jasmine.anything(),
content: undefined,
encoding: jasmine.anything(),
- last_commit_id: '123456789',
+ last_commit_id: TEST_COMMIT_SHA,
previous_path: undefined,
},
],
- start_branch: undefined,
+ start_sha: undefined,
});
done();
diff --git a/spec/javascripts/ide/stores/utils_spec.js b/spec/javascripts/ide/stores/utils_spec.js
index debe1c4acee..e3bf6d40245 100644
--- a/spec/javascripts/ide/stores/utils_spec.js
+++ b/spec/javascripts/ide/stores/utils_spec.js
@@ -132,7 +132,7 @@ describe('Multi-file store utils', () => {
previous_path: undefined,
},
],
- start_branch: undefined,
+ start_sha: undefined,
});
});
@@ -187,7 +187,7 @@ describe('Multi-file store utils', () => {
previous_path: undefined,
},
],
- start_branch: undefined,
+ start_sha: undefined,
});
});
});
diff --git a/spec/lib/gitlab/ci/build/policy/kubernetes_spec.rb b/spec/lib/gitlab/ci/build/policy/kubernetes_spec.rb
index 4884d5f8ba4..4510b82ca9d 100644
--- a/spec/lib/gitlab/ci/build/policy/kubernetes_spec.rb
+++ b/spec/lib/gitlab/ci/build/policy/kubernetes_spec.rb
@@ -4,24 +4,14 @@ describe Gitlab::Ci::Build::Policy::Kubernetes do
let(:pipeline) { create(:ci_pipeline, project: project) }
context 'when kubernetes service is active' do
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
- it 'is satisfied by a kubernetes pipeline' do
- expect(described_class.new('active'))
- .to be_satisfied_by(pipeline)
- end
- end
-
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
context 'when user configured kubernetes from CI/CD > Clusters' do
let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:project) { cluster.project }
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
+ it 'is satisfied by a kubernetes pipeline' do
+ expect(described_class.new('active'))
+ .to be_satisfied_by(pipeline)
+ end
end
end
diff --git a/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb b/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
index 5387863bd07..5ac5122e800 100644
--- a/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
+++ b/spec/lib/gitlab/ci/build/prerequisite/kubernetes_namespace_spec.rb
@@ -35,9 +35,15 @@ describe Gitlab::Ci::Build::Prerequisite::KubernetesNamespace do
end
context 'and a namespace is already created for this project' do
- let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, cluster: cluster, project: build.project) }
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token, cluster: cluster, project: build.project) }
it { is_expected.to be_falsey }
+
+ context 'and the service_account_token is blank' do
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :without_token, cluster: cluster, project: build.project) }
+
+ it { is_expected.to be_truthy }
+ end
end
context 'and cluster is project type' do
diff --git a/spec/migrations/migrate_k8s_service_integration_spec.rb b/spec/migrations/migrate_k8s_service_integration_spec.rb
new file mode 100644
index 00000000000..4dd0c09632a
--- /dev/null
+++ b/spec/migrations/migrate_k8s_service_integration_spec.rb
@@ -0,0 +1,161 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20190517153211_migrate_k8s_service_integration.rb')
+
+describe MigrateK8sServiceIntegration, :migration do
+ context 'template service' do
+ context 'with namespace' do
+ let!(:service) do
+ MigrateK8sServiceIntegration::Service.create!(
+ active: true,
+ template: true,
+ category: 'deployment',
+ type: 'KubernetesService',
+ properties: "{\"namespace\":\"prod\",\"api_url\":\"https://sample.kubernetes.com\",\"ca_pem\":\"ca_pem-sample\",\"token\":\"token-sample\"}"
+ )
+ end
+
+ let(:cluster) { MigrateK8sServiceIntegration::Cluster.instance_type.last! }
+ let(:platform) { cluster.platform_kubernetes }
+
+ it 'migrates the KubernetesService template to Platform::Kubernetes' do
+ expect { migrate! }.to change { MigrateK8sServiceIntegration::Cluster.count }.by(1)
+
+ expect(cluster).to be_enabled
+ expect(cluster).to be_user
+ expect(cluster).not_to be_managed
+ expect(cluster.environment_scope).to eq('*')
+ expect(platform.api_url).to eq('https://sample.kubernetes.com')
+ expect(platform.ca_cert).to eq('ca_pem-sample')
+ expect(platform.namespace).to eq('prod')
+ expect(platform.token).to eq('token-sample')
+ end
+ end
+
+ context 'without namespace' do
+ let!(:service) do
+ MigrateK8sServiceIntegration::Service.create!(
+ active: true,
+ template: true,
+ category: 'deployment',
+ type: 'KubernetesService',
+ properties: "{\"namespace\":\"\",\"api_url\":\"https://sample.kubernetes.com\",\"ca_pem\":\"ca_pem-sample\",\"token\":\"token-sample\"}"
+ )
+ end
+
+ let(:cluster) { MigrateK8sServiceIntegration::Cluster.instance_type.last! }
+ let(:platform) { cluster.platform_kubernetes }
+
+ it 'migrates the KubernetesService template to Platform::Kubernetes' do
+ expect { migrate! }.to change { MigrateK8sServiceIntegration::Cluster.count }.by(1)
+
+ expect(cluster).to be_enabled
+ expect(cluster).to be_user
+ expect(cluster).not_to be_managed
+ expect(cluster.environment_scope).to eq('*')
+ expect(platform.api_url).to eq('https://sample.kubernetes.com')
+ expect(platform.ca_cert).to eq('ca_pem-sample')
+ expect(platform.namespace).to be_nil
+ expect(platform.token).to eq('token-sample')
+ end
+ end
+
+ context 'with nullified parameters' do
+ let!(:service) do
+ MigrateK8sServiceIntegration::Service.create!(
+ active: true,
+ template: true,
+ category: 'deployment',
+ type: 'KubernetesService',
+ properties: "{}"
+ )
+ end
+
+ it 'does not migrate the KubernetesService' do
+ expect { migrate! }.not_to change { MigrateK8sServiceIntegration::Cluster.count }
+ end
+ end
+
+ context 'when disabled' do
+ let!(:service) do
+ MigrateK8sServiceIntegration::Service.create!(
+ active: false,
+ template: true,
+ category: 'deployment',
+ type: 'KubernetesService',
+ properties: "{\"namespace\":\"prod\",\"api_url\":\"https://sample.kubernetes.com\",\"ca_pem\":\"ca_pem-sample\",\"token\":\"token-sample\"}"
+ )
+ end
+
+ let(:cluster) { MigrateK8sServiceIntegration::Cluster.instance_type.last! }
+ let(:platform) { cluster.platform_kubernetes }
+
+ it 'migrates the KubernetesService template to Platform::Kubernetes' do
+ expect { migrate! }.to change { MigrateK8sServiceIntegration::Cluster.count }.by(1)
+
+ expect(cluster).not_to be_enabled
+ expect(cluster).to be_user
+ expect(cluster).not_to be_managed
+ expect(cluster.environment_scope).to eq('*')
+ expect(platform.api_url).to eq('https://sample.kubernetes.com')
+ expect(platform.ca_cert).to eq('ca_pem-sample')
+ expect(platform.namespace).to eq('prod')
+ expect(platform.token).to eq('token-sample')
+ end
+ end
+
+ context 'when an instance cluster already exists' do
+ let!(:service) do
+ MigrateK8sServiceIntegration::Service.create!(
+ active: true,
+ template: true,
+ category: 'deployment',
+ type: 'KubernetesService',
+ properties: "{\"namespace\":\"prod\",\"api_url\":\"https://sample.kubernetes.com\",\"ca_pem\":\"ca_pem-sample\",\"token\":\"token-sample\"}"
+ )
+ end
+
+ let!(:existing_cluster) do
+ MigrateK8sServiceIntegration::Cluster.create!(
+ name: 'test-cluster',
+ cluster_type: :instance_type,
+ managed: true,
+ provider_type: :user,
+ platform_type: :kubernetes
+ )
+ end
+ let(:new_cluster) { MigrateK8sServiceIntegration::Cluster.instance_type.last! }
+ let(:platform) { new_cluster.platform_kubernetes }
+
+ it 'migrates the KubernetesService template to disabled Platform::Kubernetes' do
+ expect { migrate! }.to change { MigrateK8sServiceIntegration::Cluster.count }.by(1)
+
+ expect(new_cluster).not_to be_enabled
+ expect(new_cluster).to be_user
+ expect(new_cluster).not_to be_managed
+ expect(new_cluster.environment_scope).to eq('*')
+ expect(platform.api_url).to eq('https://sample.kubernetes.com')
+ expect(platform.ca_cert).to eq('ca_pem-sample')
+ expect(platform.namespace).to eq('prod')
+ expect(platform.token).to eq('token-sample')
+ end
+ end
+ end
+
+ context 'non-template service' do
+ let!(:service) do
+ MigrateK8sServiceIntegration::Service.create!(
+ active: true,
+ template: false,
+ category: 'deployment',
+ type: 'KubernetesService',
+ properties: "{\"namespace\":\"prod\",\"api_url\":\"https://sample.kubernetes.com\",\"ca_pem\":\"ca_pem-sample\",\"token\":\"token-sample\"}"
+ )
+ end
+
+ it 'does not migrate the KubernetesService' do
+ expect { migrate! }.not_to change { MigrateK8sServiceIntegration::Cluster.count }
+ end
+ end
+end
diff --git a/spec/models/ci/pipeline_schedule_spec.rb b/spec/models/ci/pipeline_schedule_spec.rb
index 227870eb27f..c4d8ad5317a 100644
--- a/spec/models/ci/pipeline_schedule_spec.rb
+++ b/spec/models/ci/pipeline_schedule_spec.rb
@@ -128,8 +128,10 @@ describe Ci::PipelineSchedule do
context 'when pipeline schedule runs every minute' do
let(:pipeline_schedule) { create(:ci_pipeline_schedule, :every_minute) }
- it "updates next_run_at to the sidekiq worker's execution time", :quarantine do
- expect(pipeline_schedule.next_run_at).to eq(cron_worker_next_run_at)
+ it "updates next_run_at to the sidekiq worker's execution time" do
+ Timecop.freeze do
+ expect(pipeline_schedule.next_run_at).to eq(cron_worker_next_run_at)
+ end
end
end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index c4e54be673f..6ebc6337d50 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -962,7 +962,11 @@ describe Ci::Pipeline, :mailer do
end
context 'when kubernetes is active' do
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
+ context 'when user configured kubernetes from CI/CD > Clusters' do
+ let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.project }
+ let(:pipeline) { build(:ci_pipeline, project: project, config: config) }
+
it 'returns seeds for kubernetes dependent job' do
seeds = pipeline.stage_seeds
@@ -971,21 +975,6 @@ describe Ci::Pipeline, :mailer do
expect(seeds.dig(1, 0, :name)).to eq 'production'
end
end
-
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project) }
- let(:pipeline) { build(:ci_pipeline, project: project, config: config) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
- context 'when user configured kubernetes from CI/CD > Clusters' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:project) { cluster.project }
- let(:pipeline) { build(:ci_pipeline, project: project, config: config) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
end
context 'when kubernetes is not active' do
@@ -1679,23 +1668,13 @@ describe Ci::Pipeline, :mailer do
describe '#has_kubernetes_active?' do
context 'when kubernetes is active' do
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
- it 'returns true' do
- expect(pipeline).to have_kubernetes_active
- end
- end
-
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
context 'when user configured kubernetes from CI/CD > Clusters' do
let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:project) { cluster.project }
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
+ it 'returns true' do
+ expect(pipeline).to have_kubernetes_active
+ end
end
end
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index f206bb41f45..52661178d76 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -514,19 +514,43 @@ describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
subject { cluster.allow_user_defined_namespace? }
context 'project type cluster' do
- it { is_expected.to be_truthy }
+ context 'gitlab managed' do
+ it { is_expected.to be_truthy }
+ end
+
+ context 'not managed' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, managed: false) }
+
+ it { is_expected.to be_truthy }
+ end
end
context 'group type cluster' do
- let(:cluster) { create(:cluster, :provided_by_gcp, :group) }
+ context 'gitlab managed' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :group) }
- it { is_expected.to be_falsey }
+ it { is_expected.to be_falsey }
+ end
+
+ context 'not managed' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :group, managed: false) }
+
+ it { is_expected.to be_truthy }
+ end
end
context 'instance type cluster' do
- let(:cluster) { create(:cluster, :provided_by_gcp, :instance) }
+ context 'gitlab managed' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :instance) }
- it { is_expected.to be_falsey }
+ it { is_expected.to be_falsey }
+ end
+
+ context 'not managed' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :instance, managed: false) }
+
+ it { is_expected.to be_truthy }
+ end
end
end
@@ -555,6 +579,63 @@ describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
end
end
+ describe '#find_or_initialize_kubernetes_namespace_for_project' do
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.projects.first }
+
+ subject { cluster.find_or_initialize_kubernetes_namespace_for_project(project) }
+
+ context 'kubernetes namespace exists' do
+ context 'with no service account token' do
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, project: project, cluster: cluster) }
+
+ it { is_expected.to eq kubernetes_namespace }
+ end
+
+ context 'with a service account token' do
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token, project: project, cluster: cluster) }
+
+ it { is_expected.to eq kubernetes_namespace }
+ end
+ end
+
+ context 'kubernetes namespace does not exist' do
+ it 'initializes a new namespace and sets default values' do
+ expect(subject).to be_new_record
+ expect(subject.project).to eq project
+ expect(subject.cluster).to eq cluster
+ expect(subject.namespace).to be_present
+ expect(subject.service_account_name).to be_present
+ end
+ end
+
+ context 'a custom scope is provided' do
+ let(:scope) { cluster.kubernetes_namespaces.has_service_account_token }
+
+ subject { cluster.find_or_initialize_kubernetes_namespace_for_project(project, scope: scope) }
+
+ context 'kubernetes namespace exists' do
+ context 'with no service account token' do
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, project: project, cluster: cluster) }
+
+ it 'initializes a new namespace and sets default values' do
+ expect(subject).to be_new_record
+ expect(subject.project).to eq project
+ expect(subject.cluster).to eq cluster
+ expect(subject.namespace).to be_present
+ expect(subject.service_account_name).to be_present
+ end
+ end
+
+ context 'with a service account token' do
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token, project: project, cluster: cluster) }
+
+ it { is_expected.to eq kubernetes_namespace }
+ end
+ end
+ end
+ end
+
describe '#predefined_variables' do
subject { cluster.predefined_variables }
diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb
index c485850c16e..1fb3a8de808 100644
--- a/spec/models/clusters/platforms/kubernetes_spec.rb
+++ b/spec/models/clusters/platforms/kubernetes_spec.rb
@@ -223,19 +223,33 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
let(:namespace) { 'namespace-123' }
it { is_expected.to eq(namespace) }
+
+ context 'kubernetes namespace is present but has no service account token' do
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, cluster: cluster) }
+
+ it { is_expected.to eq(namespace) }
+ end
end
context 'with no namespace assigned' do
let(:namespace) { nil }
context 'when kubernetes namespace is present' do
- let(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, cluster: cluster) }
+ let(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token, cluster: cluster) }
before do
kubernetes_namespace
end
it { is_expected.to eq(kubernetes_namespace.namespace) }
+
+ context 'kubernetes namespace has no service account token' do
+ before do
+ kubernetes_namespace.update!(namespace: 'old-namespace', service_account_token: nil)
+ end
+
+ it { is_expected.to eq("#{project.path}-#{project.id}") }
+ end
end
context 'when kubernetes namespace is not present' do
@@ -284,6 +298,46 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
{ key: 'KUBE_TOKEN', value: kubernetes_namespace.service_account_token, public: false, masked: true }
)
end
+
+ context 'the cluster has been set to unmanaged after the namespace was created' do
+ before do
+ cluster.update!(managed: false)
+ end
+
+ it_behaves_like 'setting variables'
+
+ it 'sets KUBE_TOKEN from the platform' do
+ expect(subject).to include(
+ { key: 'KUBE_TOKEN', value: kubernetes.token, public: false, masked: true }
+ )
+ end
+
+ context 'the platform has a custom namespace set' do
+ before do
+ kubernetes.update!(namespace: 'custom-namespace')
+ end
+
+ it 'sets KUBE_NAMESPACE from the platform' do
+ expect(subject).to include(
+ { key: 'KUBE_NAMESPACE', value: kubernetes.namespace, public: true, masked: false }
+ )
+ end
+ end
+
+ context 'there is no namespace specified on the platform' do
+ let(:project) { cluster.project }
+
+ before do
+ kubernetes.update!(namespace: nil)
+ end
+
+ it 'sets KUBE_NAMESPACE to a default for the project' do
+ expect(subject).to include(
+ { key: 'KUBE_NAMESPACE', value: "#{project.path}-#{project.id}", public: true, masked: false }
+ )
+ end
+ end
+ end
end
context 'namespace is provided' do
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index 7233d2454c6..379dda1f5c4 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -515,29 +515,19 @@ describe Environment do
context 'when the environment is available' do
context 'with a deployment service' do
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
- context 'and a deployment' do
+ context 'when user configured kubernetes from CI/CD > Clusters' do
+ let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.project }
+
+ context 'with deployment' do
let!(:deployment) { create(:deployment, :success, environment: environment) }
it { is_expected.to be_truthy }
end
- context 'but no deployments' do
+ context 'without deployments' do
it { is_expected.to be_falsy }
end
end
-
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
- context 'when user configured kubernetes from CI/CD > Clusters' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:project) { cluster.project }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
end
context 'without a deployment service' do
@@ -546,8 +536,6 @@ describe Environment do
end
context 'when the environment is unavailable' do
- let(:project) { create(:kubernetes_project) }
-
before do
environment.stop
end
@@ -590,7 +578,10 @@ describe Environment do
allow(environment).to receive(:has_terminals?).and_return(true)
end
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
+ context 'when user configured kubernetes from CI/CD > Clusters' do
+ let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.project }
+
it 'returns the terminals from the deployment service' do
expect(environment.deployment_platform)
.to receive(:terminals).with(environment)
@@ -599,19 +590,6 @@ describe Environment do
is_expected.to eq(:fake_terminals)
end
end
-
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
- context 'when user configured kubernetes from CI/CD > Clusters' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:project) { cluster.project }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
end
context 'when the environment does not have terminals' do
diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb
index 2fce120381b..34ee1eafd5c 100644
--- a/spec/models/project_services/kubernetes_service_spec.rb
+++ b/spec/models/project_services/kubernetes_service_spec.rb
@@ -17,6 +17,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
context 'when service is active' do
before do
subject.active = true
+ subject.skip_deprecation_validation = true
end
it { is_expected.not_to validate_presence_of(:namespace) }
@@ -67,6 +68,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
before do
kubernetes_service.update_attribute(:active, false)
+ kubernetes_service.skip_deprecation_validation = false
kubernetes_service.properties['namespace'] = "foo"
end
@@ -80,19 +82,11 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
end
end
- context 'with a non-deprecated service' do
- let(:kubernetes_service) { create(:kubernetes_service) }
-
- it 'updates attributes' do
- kubernetes_service.properties['namespace'] = 'foo'
- expect(kubernetes_service.save).to be_truthy
- end
- end
-
context 'with an active and deprecated service' do
let(:kubernetes_service) { create(:kubernetes_service) }
before do
+ kubernetes_service.skip_deprecation_validation = false
kubernetes_service.active = false
kubernetes_service.properties['namespace'] = 'foo'
kubernetes_service.save
@@ -110,19 +104,6 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
expect(kubernetes_service.properties['namespace']).to eq("foo")
end
end
-
- context 'with a template service' do
- let(:kubernetes_service) { create(:kubernetes_service, template: true, active: false) }
-
- before do
- kubernetes_service.properties['namespace'] = 'foo'
- end
-
- it 'updates attributes' do
- expect(kubernetes_service.save).to be_truthy
- expect(kubernetes_service.properties['namespace']).to eq('foo')
- end
- end
end
describe '#initialize_properties' do
@@ -393,17 +374,8 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
describe "#deprecated?" do
let(:kubernetes_service) { create(:kubernetes_service) }
- context 'with an active kubernetes service' do
- it 'returns false' do
- expect(kubernetes_service.deprecated?).to be_falsy
- end
- end
-
- context 'with a inactive kubernetes service' do
- it 'returns true' do
- kubernetes_service.update_attribute(:active, false)
- expect(kubernetes_service.deprecated?).to be_truthy
- end
+ it 'returns true' do
+ expect(kubernetes_service.deprecated?).to be_truthy
end
end
@@ -414,12 +386,6 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
expect(kubernetes_service.deprecation_message).to match(/Kubernetes service integration has been deprecated/)
end
- context 'if the services is active' do
- it 'returns a message' do
- expect(kubernetes_service.deprecation_message).to match(/Your Kubernetes cluster information on this page is still editable/)
- end
- end
-
context 'if the service is not active' do
it 'returns a message' do
kubernetes_service.update_attribute(:active, false)
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index e6d5e8fc320..20b98b5eb85 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -2652,7 +2652,10 @@ describe Project do
end
context 'when project has a deployment service' do
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
+ context 'when user configured kubernetes from CI/CD > Clusters and KubernetesNamespace migration has not been executed' do
+ let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.project }
+
it 'returns variables from this service' do
expect(project.deployment_variables).to include(
{ key: 'KUBE_TOKEN', value: project.deployment_platform.token, public: false, masked: true }
@@ -2660,19 +2663,6 @@ describe Project do
end
end
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
- context 'when user configured kubernetes from CI/CD > Clusters and KubernetesNamespace migration has not been executed' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:project) { cluster.project }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
context 'when user configured kubernetes from CI/CD > Clusters and KubernetesNamespace migration has been executed' do
let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token) }
let!(:cluster) { kubernetes_namespace.cluster }
@@ -3478,6 +3468,7 @@ describe Project do
before do
allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
+ stub_application_setting(hashed_storage_enabled: false)
end
describe '#base_dir' do
@@ -3584,10 +3575,6 @@ describe Project do
let(:hashed_prefix) { File.join('@hashed', hash[0..1], hash[2..3]) }
let(:hashed_path) { File.join(hashed_prefix, hash) }
- before do
- stub_application_setting(hashed_storage_enabled: true)
- end
-
describe '#legacy_storage?' do
it 'returns false' do
expect(project.legacy_storage?).to be_falsey
@@ -4729,10 +4716,6 @@ describe Project do
subject { project.object_pool_params }
- before do
- stub_application_setting(hashed_storage_enabled: true)
- end
-
context 'when the objects cannot be pooled' do
let(:project) { create(:project, :repository, :private) }
@@ -4778,10 +4761,6 @@ describe Project do
context 'when objects are poolable' do
let(:project) { create(:project, :repository, :public) }
- before do
- stub_application_setting(hashed_storage_enabled: true)
- end
-
it { is_expected.to be_git_objects_poolable }
end
end
diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb
index c9439b0846d..d442c73c118 100644
--- a/spec/models/service_spec.rb
+++ b/spec/models/service_spec.rb
@@ -82,7 +82,7 @@ describe Service do
context 'when template is invalid' do
it 'sets service template to inactive when template is invalid' do
project = create(:project)
- template = KubernetesService.new(template: true, active: true)
+ template = build(:prometheus_service, template: true, active: true, properties: {})
template.save(validate: false)
service = described_class.build_from_template(project.id, template)
@@ -309,10 +309,10 @@ describe Service do
end
describe '.find_by_template' do
- let!(:kubernetes_service) { create(:kubernetes_service, template: true) }
+ let!(:service) { create(:service, template: true) }
it 'returns service template' do
- expect(KubernetesService.find_by_template).to eq(kubernetes_service)
+ expect(described_class.find_by_template).to eq(service)
end
end
diff --git a/spec/requests/api/services_spec.rb b/spec/requests/api/services_spec.rb
index e260aa21e25..3f79e332b90 100644
--- a/spec/requests/api/services_spec.rb
+++ b/spec/requests/api/services_spec.rb
@@ -10,7 +10,10 @@ describe API::Services do
end
Service.available_services_names.each do |service|
- describe "PUT /projects/:id/services/#{service.dasherize}" do
+ # TODO: Remove below `if: (service != "kubernetes")` in the next release
+ # KubernetesService was deprecated and it can't be updated. Right now it's
+ # only readable. It should be completely removed in the next iteration.
+ describe "PUT /projects/:id/services/#{service.dasherize}", if: (service != "kubernetes") do
include_context service
it "updates #{service} settings" do
@@ -19,13 +22,22 @@ describe API::Services do
expect(response).to have_gitlab_http_status(200)
current_service = project.services.first
- event = current_service.event_names.empty? ? "foo" : current_service.event_names.first
- state = current_service[event] || false
+ events = current_service.event_names.empty? ? ["foo"].freeze : current_service.event_names
+ query_strings = []
+ events.each do |event|
+ query_strings << "#{event}=#{!current_service[event]}"
+ end
+ query_strings = query_strings.join('&')
- put api("/projects/#{project.id}/services/#{dashed_service}?#{event}=#{!state}", user), params: service_attrs
+ put api("/projects/#{project.id}/services/#{dashed_service}?#{query_strings}", user), params: service_attrs
expect(response).to have_gitlab_http_status(200)
- expect(project.services.first[event]).not_to eq(state) unless event == "foo"
+ events.each do |event|
+ next if event == "foo"
+
+ expect(project.services.first[event]).not_to eq(current_service[event]),
+ "expected #{!current_service[event]} for event #{event} for service #{current_service.title}, got #{current_service[event]}"
+ end
end
it "returns if required fields missing" do
@@ -50,7 +62,10 @@ describe API::Services do
end
end
- describe "DELETE /projects/:id/services/#{service.dasherize}" do
+ # TODO: Remove below `if: (service != "kubernetes")` in the next release
+ # KubernetesService was deprecated and it can't be updated. Right now it's
+ # only readable. It should be completely removed in the next iteration.
+ describe "DELETE /projects/:id/services/#{service.dasherize}", if: (service != "kubernetes") do
include_context service
before do
diff --git a/spec/serializers/environment_entity_spec.rb b/spec/serializers/environment_entity_spec.rb
index c2312734042..906449f470b 100644
--- a/spec/serializers/environment_entity_spec.rb
+++ b/spec/serializers/environment_entity_spec.rb
@@ -59,15 +59,5 @@ describe EnvironmentEntity do
expect(subject[:cluster_type]).to eq('project_type')
end
end
-
- context 'when deployment platform is a Kubernetes Service' do
- before do
- create(:kubernetes_service, project: project)
- end
-
- it 'does not include cluster_type' do
- expect(subject).not_to include(:cluster_type)
- end
- end
end
end
diff --git a/spec/services/projects/after_rename_service_spec.rb b/spec/services/projects/after_rename_service_spec.rb
index b8055a285f2..8585d495ffb 100644
--- a/spec/services/projects/after_rename_service_spec.rb
+++ b/spec/services/projects/after_rename_service_spec.rb
@@ -23,6 +23,7 @@ describe Projects::AfterRenameService do
allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
stub_feature_flags(skip_hashed_storage_upgrade: false)
+ stub_application_setting(hashed_storage_enabled: false)
end
it 'renames a repository' do
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index a4c48991807..b0b74407812 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -228,6 +228,7 @@ describe Projects::CreateService, '#execute' do
context 'with legacy storage' do
before do
+ stub_application_setting(hashed_storage_enabled: false)
gitlab_shell.create_repository(repository_storage, "#{user.namespace.full_path}/existing", 'group/project')
end
@@ -259,7 +260,6 @@ describe Projects::CreateService, '#execute' do
let(:hashed_path) { '@hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b' }
before do
- stub_application_setting(hashed_storage_enabled: true)
allow(Digest::SHA2).to receive(:hexdigest) { hash }
end
diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb
index 6afc91d5e95..0c109e26a6a 100644
--- a/spec/services/projects/fork_service_spec.rb
+++ b/spec/services/projects/fork_service_spec.rb
@@ -116,11 +116,12 @@ describe Projects::ForkService do
end
end
- context 'repository already exists' do
+ context 'repository in legacy storage already exists' do
let(:repository_storage) { 'default' }
let(:repository_storage_path) { Gitlab.config.repositories.storages[repository_storage].legacy_disk_path }
before do
+ stub_application_setting(hashed_storage_enabled: false)
gitlab_shell.create_repository(repository_storage, "#{@to_user.namespace.full_path}/#{@from_project.path}", "#{@to_user.namespace.full_path}/#{@from_project.path}")
end
diff --git a/spec/support/prometheus/additional_metrics_shared_examples.rb b/spec/support/prometheus/additional_metrics_shared_examples.rb
index 8044b061ca5..de21e808932 100644
--- a/spec/support/prometheus/additional_metrics_shared_examples.rb
+++ b/spec/support/prometheus/additional_metrics_shared_examples.rb
@@ -44,7 +44,9 @@ RSpec.shared_examples 'additional metrics query' do
end
describe 'project has Kubernetes service' do
- shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
+ context 'when user configured kubernetes from CI/CD > Clusters' do
+ let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:project) { cluster.project }
let(:environment) { create(:environment, slug: 'environment-slug', project: project) }
let(:kube_namespace) { project.deployment_platform.kubernetes_namespace_for(project) }
@@ -56,19 +58,6 @@ RSpec.shared_examples 'additional metrics query' do
subject.query(*query_params)
end
end
-
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project) }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
-
- context 'when user configured kubernetes from CI/CD > Clusters' do
- let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
- let(:project) { cluster.project }
-
- it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
- end
end
describe 'project without Kubernetes service' do
diff --git a/spec/support/shared_contexts/services_shared_context.rb b/spec/support/shared_contexts/services_shared_context.rb
index 089f1798cd2..0c3a24d206f 100644
--- a/spec/support/shared_contexts/services_shared_context.rb
+++ b/spec/support/shared_contexts/services_shared_context.rb
@@ -37,8 +37,7 @@ Service.available_services_names.each do |service|
def initialize_service(service)
service_item = project.find_or_initialize_service(service)
service_item.properties = service_attrs
- service_item.active = true if service == "kubernetes"
- service_item.save
+ service_item.save!
service_item
end
end
diff --git a/spec/workers/reactive_caching_worker_spec.rb b/spec/workers/reactive_caching_worker_spec.rb
index 2395e6ec947..b8ca6063ccd 100644
--- a/spec/workers/reactive_caching_worker_spec.rb
+++ b/spec/workers/reactive_caching_worker_spec.rb
@@ -6,16 +6,6 @@ describe ReactiveCachingWorker do
let(:service) { project.deployment_platform }
describe '#perform' do
- context 'when user configured kubernetes from Integration > Kubernetes' do
- let(:project) { create(:kubernetes_project) }
-
- it 'calls #exclusively_update_reactive_cache!' do
- expect_any_instance_of(KubernetesService).to receive(:exclusively_update_reactive_cache!)
-
- described_class.new.perform("KubernetesService", service.id)
- end
- end
-
context 'when user configured kubernetes from CI/CD > Clusters' do
let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:project) { cluster.project }