summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/issue_templates/Coding style proposal.md (renamed from .gitlab/issue_templates/Add style proposal.md)0
-rw-r--r--.rubocop_todo.yml5
-rw-r--r--app/assets/javascripts/clusters/clusters_bundle.js28
-rw-r--r--app/assets/javascripts/clusters/components/application_row.vue59
-rw-r--r--app/assets/javascripts/clusters/constants.js3
-rw-r--r--app/assets/stylesheets/framework/buttons.scss4
-rw-r--r--app/assets/stylesheets/framework/variables.scss4
-rw-r--r--app/assets/stylesheets/pages/groups.scss108
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss4
-rw-r--r--app/assets/stylesheets/pages/projects.scss153
-rw-r--r--app/controllers/import/bitbucket_server_controller.rb7
-rw-r--r--app/controllers/notification_settings_controller.rb7
-rw-r--r--app/controllers/projects/pipelines_controller.rb6
-rw-r--r--app/helpers/import_helper.rb4
-rw-r--r--app/helpers/release_blog_post_helper.rb7
-rw-r--r--app/models/identity.rb2
-rw-r--r--app/models/internal_id.rb17
-rw-r--r--app/models/project.rb15
-rw-r--r--app/models/project_services/bamboo_service.rb32
-rw-r--r--app/serializers/cluster_application_entity.rb1
-rw-r--r--app/views/clusters/clusters/_form.html.haml (renamed from app/views/clusters/clusters/_integration_form.html.haml)0
-rw-r--r--app/views/clusters/clusters/gcp/_show.html.haml50
-rw-r--r--app/views/clusters/clusters/show.html.haml7
-rw-r--r--app/views/clusters/clusters/user/_show.html.haml39
-rw-r--r--app/views/clusters/platforms/kubernetes/_form.html.haml58
-rw-r--r--app/views/groups/_home_panel.html.haml71
-rw-r--r--app/views/groups/show.html.haml95
-rw-r--r--app/views/ide/_show.html.haml2
-rw-r--r--app/views/import/bitbucket_server/status.html.haml2
-rw-r--r--app/views/layouts/header/_help_dropdown.html.haml4
-rw-r--r--app/views/projects/_home_panel.html.haml24
-rw-r--r--app/views/projects/deploy_keys/_index.html.haml2
-rw-r--r--app/views/projects/milestones/_form.html.haml18
-rw-r--r--app/views/projects/milestones/edit.html.haml10
-rw-r--r--app/views/projects/milestones/index.html.haml8
-rw-r--r--app/views/projects/milestones/new.html.haml10
-rw-r--r--app/views/projects/milestones/show.html.haml28
-rw-r--r--app/views/shared/members/_access_request_buttons.html.haml20
-rw-r--r--app/views/shared/notifications/_button.html.haml2
-rw-r--r--app/views/shared/notifications/_new_button.html.haml (renamed from app/views/projects/buttons/_notifications.html.haml)8
-rw-r--r--changelogs/unreleased/24680-support-bamboo-api-polymorphism.yml5
-rw-r--r--changelogs/unreleased/25341-add-what-s-new-menu-item-in-top-navigation.yml5
-rw-r--r--changelogs/unreleased/53104-redesign-group-overview-ui-mvc.yml5
-rw-r--r--changelogs/unreleased/55820-adds-common-name-chart-value.yml5
-rw-r--r--changelogs/unreleased/56379-pipeline-stages-job-action-button-icon-is-not-aligned.yml5
-rw-r--r--changelogs/unreleased/56398-fix-cluster-installation-loading-state.yml5
-rw-r--r--changelogs/unreleased/ab-54270-github-iid.yml5
-rw-r--r--changelogs/unreleased/adrianmoisey-GITLAB_PAGES_PREDEFINED_VARIABLES.yml5
-rw-r--r--changelogs/unreleased/an-opentracing-render-tracing.yml5
-rw-r--r--changelogs/unreleased/cluster_status_for_ugprading.yml5
-rw-r--r--changelogs/unreleased/gt-externalize-app-views-projects-milestones.yml5
-rw-r--r--changelogs/unreleased/sh-disable-nil-user-id-identity-validation.yml5
-rw-r--r--changelogs/unreleased/sh-issue-53419-fix.yml5
-rw-r--r--config/initializers/tracing.rb1
-rw-r--r--db/post_migrate/20190102152410_delete_inconsistent_internal_id_records2.rb43
-rw-r--r--doc/administration/index.md2
-rw-r--r--doc/api/project_clusters.md1
-rw-r--r--doc/api/repositories.md2
-rw-r--r--doc/ci/caching/index.md12
-rw-r--r--doc/ci/docker/using_kaniko.md2
-rw-r--r--doc/ci/environments.md2
-rw-r--r--doc/ci/examples/artifactory_and_gitlab/index.md2
-rw-r--r--doc/ci/examples/container_scanning.md4
-rw-r--r--doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md2
-rw-r--r--doc/ci/examples/test-and-deploy-python-application-to-heroku.md2
-rw-r--r--doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md2
-rw-r--r--doc/ci/triggers/README.md2
-rw-r--r--doc/ci/variables/README.md71
-rw-r--r--doc/ci/variables/img/variables.pngbin34838 -> 0 bytes
-rw-r--r--doc/ci/yaml/README.md8
-rw-r--r--doc/install/installation.md130
-rw-r--r--doc/topics/autodevops/index.md4
-rw-r--r--doc/topics/autodevops/quick_start_guide.md4
-rw-r--r--doc/user/permissions.md7
-rw-r--r--doc/user/project/integrations/prometheus.md4
-rw-r--r--doc/user/project/integrations/prometheus_library/index.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/kubernetes.md2
-rw-r--r--doc/user/project/merge_requests/index.md12
-rw-r--r--doc/user/project/new_ci_build_permissions_model.md2
-rw-r--r--lib/gitlab.rb48
-rw-r--r--lib/gitlab/ci/ansi2html.rb18
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml6
-rw-r--r--lib/gitlab/ci/trace/stream.rb2
-rw-r--r--lib/gitlab/github_import/bulk_importing.rb4
-rw-r--r--lib/gitlab/github_import/importer/issue_importer.rb6
-rw-r--r--lib/gitlab/github_import/importer/milestones_importer.rb12
-rw-r--r--lib/gitlab/import/merge_request_helpers.rb4
-rw-r--r--lib/gitlab/metrics/influx_db.rb4
-rw-r--r--lib/gitlab/release_blog_post.rb40
-rw-r--r--lib/gitlab/tracing/rails/action_view_subscriber.rb75
-rw-r--r--lib/gitlab/tracing/rails/active_record_subscriber.rb27
-rw-r--r--lib/gitlab/tracing/rails/rails_common.rb24
-rw-r--r--lib/gitlab/version_info.rb8
-rw-r--r--locale/gitlab.pot36
-rw-r--r--qa/Gemfile.lock2
-rw-r--r--qa/Rakefile6
-rw-r--r--qa/qa/page/group/show.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/user_views_raw_diff_patch_requests_spec.rb5
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb3
-rw-r--r--qa/qa/support/api.rb18
-rw-r--r--qa/qa/tools/delete_subgroups.rb66
-rw-r--r--qa/spec/page/logging_spec.rb2
-rw-r--r--qa/spec/support/stub_env.rb2
-rwxr-xr-xscripts/trigger-build1
-rw-r--r--spec/controllers/import/bitbucket_server_controller_spec.rb22
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb2
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb2
-rw-r--r--spec/controllers/projects/snippets_controller_spec.rb2
-rw-r--r--spec/features/dashboard/datetime_on_tooltips_spec.rb4
-rw-r--r--spec/features/dashboard/help_spec.rb8
-rw-r--r--spec/features/groups/group_settings_spec.rb8
-rw-r--r--spec/features/groups_spec.rb8
-rw-r--r--spec/features/issues/filtered_search/dropdown_assignee_spec.rb2
-rw-r--r--spec/features/issues/filtered_search/dropdown_author_spec.rb2
-rw-r--r--spec/features/issues/filtered_search/dropdown_emoji_spec.rb2
-rw-r--r--spec/features/issues/filtered_search/dropdown_milestone_spec.rb2
-rw-r--r--spec/features/projects/deploy_keys_spec.rb2
-rw-r--r--spec/features/projects/files/undo_template_spec.rb2
-rw-r--r--spec/features/projects/jobs_spec.rb8
-rw-r--r--spec/features/projects/settings/repository_settings_spec.rb10
-rw-r--r--spec/features/projects/snippets/user_comments_on_snippet_spec.rb2
-rw-r--r--spec/features/projects_spec.rb16
-rw-r--r--spec/fixtures/api/schemas/cluster_status.json1
-rw-r--r--spec/helpers/import_helper_spec.rb4
-rw-r--r--spec/helpers/submodule_helper_spec.rb2
-rw-r--r--spec/javascripts/clusters/clusters_bundle_spec.js57
-rw-r--r--spec/javascripts/clusters/components/application_row_spec.js49
-rw-r--r--spec/javascripts/notes/components/noteable_discussion_spec.js142
-rw-r--r--spec/lib/gitlab/data_builder/pipeline_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/bulk_importing_spec.rb12
-rw-r--r--spec/lib/gitlab/github_import/importer/issue_importer_spec.rb22
-rw-r--r--spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb14
-rw-r--r--spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb10
-rw-r--r--spec/lib/gitlab/release_blog_post_spec.rb97
-rw-r--r--spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb2
-rw-r--r--spec/lib/gitlab/tracing/rails/action_view_subscriber_spec.rb147
-rw-r--r--spec/lib/gitlab/tracing/rails/active_record_subscriber_spec.rb8
-rw-r--r--spec/lib/gitlab_spec.rb76
-rw-r--r--spec/models/ci/build_spec.rb2
-rw-r--r--spec/models/identity_spec.rb34
-rw-r--r--spec/models/internal_id_spec.rb23
-rw-r--r--spec/models/project_services/bamboo_service_spec.rb26
-rw-r--r--spec/models/project_spec.rb1
-rw-r--r--spec/serializers/cluster_application_entity_spec.rb6
-rw-r--r--spec/services/resource_events/merge_into_notes_service_spec.rb4
-rw-r--r--spec/spec_helper.rb5
-rw-r--r--spec/support/helpers/kubernetes_helpers.rb2
-rw-r--r--spec/support/helpers/rake_helpers.rb2
-rw-r--r--spec/support/helpers/stub_env.rb2
-rw-r--r--spec/views/projects/_home_panel.html.haml_spec.rb2
150 files changed, 1390 insertions, 1203 deletions
diff --git a/.gitlab/issue_templates/Add style proposal.md b/.gitlab/issue_templates/Coding style proposal.md
index 1a3be44bea0..1a3be44bea0 100644
--- a/.gitlab/issue_templates/Add style proposal.md
+++ b/.gitlab/issue_templates/Coding style proposal.md
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 91810d84c50..c42d11a860e 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -437,11 +437,6 @@ Style/LineEndConcatenation:
- 'spec/lib/gitlab/gfm/reference_rewriter_spec.rb'
- 'spec/lib/gitlab/incoming_email_spec.rb'
-# Offense count: 39
-# Cop supports --auto-correct.
-Style/MethodCallWithoutArgsParentheses:
- Enabled: false
-
# Offense count: 18
Style/MethodMissing:
Enabled: false
diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js
index b1f992c03ff..fc4779632f9 100644
--- a/app/assets/javascripts/clusters/clusters_bundle.js
+++ b/app/assets/javascripts/clusters/clusters_bundle.js
@@ -6,7 +6,7 @@ import Flash from '../flash';
import Poll from '../lib/utils/poll';
import initSettingsPanels from '../settings_panels';
import eventHub from './event_hub';
-import { APPLICATION_STATUS, REQUEST_LOADING, REQUEST_SUCCESS, REQUEST_FAILURE } from './constants';
+import { APPLICATION_STATUS, REQUEST_SUBMITTED, REQUEST_FAILURE } from './constants';
import ClustersService from './services/clusters_service';
import ClustersStore from './stores/clusters_store';
import Applications from './components/applications.vue';
@@ -231,22 +231,18 @@ export default class Clusters {
installApplication(data) {
const appId = data.id;
- this.store.updateAppProperty(appId, 'requestStatus', REQUEST_LOADING);
+ this.store.updateAppProperty(appId, 'requestStatus', REQUEST_SUBMITTED);
this.store.updateAppProperty(appId, 'requestReason', null);
-
- this.service
- .installApplication(appId, data.params)
- .then(() => {
- this.store.updateAppProperty(appId, 'requestStatus', REQUEST_SUCCESS);
- })
- .catch(() => {
- this.store.updateAppProperty(appId, 'requestStatus', REQUEST_FAILURE);
- this.store.updateAppProperty(
- appId,
- 'requestReason',
- s__('ClusterIntegration|Request to begin installing failed'),
- );
- });
+ this.store.updateAppProperty(appId, 'statusReason', null);
+
+ this.service.installApplication(appId, data.params).catch(() => {
+ this.store.updateAppProperty(appId, 'requestStatus', REQUEST_FAILURE);
+ this.store.updateAppProperty(
+ appId,
+ 'requestReason',
+ s__('ClusterIntegration|Request to begin installing failed'),
+ );
+ });
}
destroy() {
diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue
index d4354dcfebd..3c3ce1dec56 100644
--- a/app/assets/javascripts/clusters/components/application_row.vue
+++ b/app/assets/javascripts/clusters/components/application_row.vue
@@ -4,12 +4,7 @@ import { s__, sprintf } from '../../locale';
import eventHub from '../event_hub';
import identicon from '../../vue_shared/components/identicon.vue';
import loadingButton from '../../vue_shared/components/loading_button.vue';
-import {
- APPLICATION_STATUS,
- REQUEST_LOADING,
- REQUEST_SUCCESS,
- REQUEST_FAILURE,
-} from '../constants';
+import { APPLICATION_STATUS, REQUEST_SUBMITTED, REQUEST_FAILURE } from '../constants';
export default {
components: {
@@ -72,6 +67,13 @@ export default {
isKnownStatus() {
return Object.values(APPLICATION_STATUS).includes(this.status);
},
+ isInstalling() {
+ return (
+ this.status === APPLICATION_STATUS.SCHEDULED ||
+ this.status === APPLICATION_STATUS.INSTALLING ||
+ (this.requestStatus === REQUEST_SUBMITTED && !this.statusReason && !this.isInstalled)
+ );
+ },
isInstalled() {
return (
this.status === APPLICATION_STATUS.INSTALLED ||
@@ -79,6 +81,18 @@ export default {
this.status === APPLICATION_STATUS.UPDATING
);
},
+ canInstall() {
+ if (this.isInstalling) {
+ return false;
+ }
+
+ return (
+ this.status === APPLICATION_STATUS.NOT_INSTALLABLE ||
+ this.status === APPLICATION_STATUS.INSTALLABLE ||
+ this.status === APPLICATION_STATUS.ERROR ||
+ this.isUnknownStatus
+ );
+ },
hasLogo() {
return !!this.logoUrl;
},
@@ -90,12 +104,7 @@ export default {
return `js-cluster-application-row-${this.id}`;
},
installButtonLoading() {
- return (
- !this.status ||
- this.status === APPLICATION_STATUS.SCHEDULED ||
- this.status === APPLICATION_STATUS.INSTALLING ||
- this.requestStatus === REQUEST_LOADING
- );
+ return !this.status || this.status === APPLICATION_STATUS.SCHEDULED || this.isInstalling;
},
installButtonDisabled() {
// Avoid the potential for the real-time data to say APPLICATION_STATUS.INSTALLABLE but
@@ -104,30 +113,17 @@ export default {
return (
((this.status !== APPLICATION_STATUS.INSTALLABLE &&
this.status !== APPLICATION_STATUS.ERROR) ||
- this.requestStatus === REQUEST_LOADING ||
- this.requestStatus === REQUEST_SUCCESS) &&
+ this.isInstalling) &&
this.isKnownStatus
);
},
installButtonLabel() {
let label;
- if (
- this.status === APPLICATION_STATUS.NOT_INSTALLABLE ||
- this.status === APPLICATION_STATUS.INSTALLABLE ||
- this.status === APPLICATION_STATUS.ERROR ||
- this.isUnknownStatus
- ) {
+ if (this.canInstall) {
label = s__('ClusterIntegration|Install');
- } else if (
- this.status === APPLICATION_STATUS.SCHEDULED ||
- this.status === APPLICATION_STATUS.INSTALLING
- ) {
+ } else if (this.isInstalling) {
label = s__('ClusterIntegration|Installing');
- } else if (
- this.status === APPLICATION_STATUS.INSTALLED ||
- this.status === APPLICATION_STATUS.UPDATED ||
- this.status === APPLICATION_STATUS.UPDATING
- ) {
+ } else if (this.isInstalled) {
label = s__('ClusterIntegration|Installed');
}
@@ -140,7 +136,10 @@ export default {
return s__('ClusterIntegration|Manage');
},
hasError() {
- return this.status === APPLICATION_STATUS.ERROR || this.requestStatus === REQUEST_FAILURE;
+ return (
+ !this.isInstalling &&
+ (this.status === APPLICATION_STATUS.ERROR || this.requestStatus === REQUEST_FAILURE)
+ );
},
generalErrorDescription() {
return sprintf(s__('ClusterIntegration|Something went wrong while installing %{title}'), {
diff --git a/app/assets/javascripts/clusters/constants.js b/app/assets/javascripts/clusters/constants.js
index e31afadf186..360511e8882 100644
--- a/app/assets/javascripts/clusters/constants.js
+++ b/app/assets/javascripts/clusters/constants.js
@@ -18,8 +18,7 @@ export const APPLICATION_STATUS = {
};
// These are only used client-side
-export const REQUEST_LOADING = 'request-loading';
-export const REQUEST_SUCCESS = 'request-success';
+export const REQUEST_SUBMITTED = 'request-submitted';
export const REQUEST_FAILURE = 'request-failure';
export const INGRESS = 'ingress';
export const JUPYTER = 'jupyter';
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index 5d2cbdde8dc..d164cc56e44 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -42,6 +42,10 @@
color: $text;
border-color: $border;
+ &.btn-border-color {
+ border-color: $border-color;
+ }
+
> .icon {
color: $text;
}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index e886a54dc99..9eae9a831fa 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -278,8 +278,8 @@ $performance-bar-height: 35px;
$flash-height: 52px;
$context-header-height: 60px;
$breadcrumb-min-height: 48px;
-$project-title-row-height: 64px;
-$project-avatar-mobile-size: 24px;
+$home-panel-title-row-height: 64px;
+$home-panel-avatar-mobile-size: 24px;
$gl-line-height: 16px;
$gl-line-height-24: 24px;
$gl-line-height-14: 14px;
diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss
index ebbb5beed81..8ade995525a 100644
--- a/app/assets/stylesheets/pages/groups.scss
+++ b/app/assets/stylesheets/pages/groups.scss
@@ -29,9 +29,7 @@
}
}
-.group-nav-container .group-search,
.group-nav-container .nav-controls {
- display: flex;
align-items: flex-start;
padding: $gl-padding-top 0 0;
@@ -44,6 +42,52 @@
margin-top: 0;
}
+ @include media-breakpoint-down(sm) {
+ .dropdown,
+ .dropdown .dropdown-toggle,
+ .btn-success {
+ display: block;
+ }
+
+ .group-filter-form,
+ .dropdown {
+ margin-bottom: 10px;
+ margin-right: 0;
+ }
+
+ &,
+ .group-filter-form,
+ .group-filter-form-field,
+ .dropdown,
+ .dropdown .dropdown-toggle,
+ .btn-success {
+ width: 100%;
+ }
+
+ .dropdown .dropdown-toggle .fa-chevron-down {
+ position: absolute;
+ top: 11px;
+ right: 8px;
+ }
+ }
+}
+
+.home-panel-buttons {
+ .home-panel-action-button {
+ vertical-align: top;
+ }
+
+
+ .notification-dropdown {
+ .dropdown-menu {
+ @extend .dropdown-menu-right;
+ }
+
+ .icon {
+ fill: $gl-text-color-secondary;
+ }
+ }
+
.new-project-subgroup {
.dropdown-primary {
min-width: 115px;
@@ -99,61 +143,29 @@
font-weight: $gl-font-weight-bold;
}
}
- }
- }
-
- @include media-breakpoint-down(sm) {
- &,
- .dropdown,
- .dropdown .dropdown-toggle,
- .btn-success {
- display: block;
- }
- .group-filter-form,
- .dropdown {
- margin-bottom: 10px;
- margin-right: 0;
- }
-
- .group-filter-form,
- .dropdown .dropdown-toggle,
- .btn-success {
- width: 100%;
- }
-
- .dropdown .dropdown-toggle .fa-chevron-down {
- position: absolute;
- top: 11px;
- right: 8px;
- }
-
- .new-project-subgroup {
- display: flex;
- align-items: flex-start;
+ @include media-breakpoint-down(sm) {
+ display: flex;
+ align-items: flex-start;
- .dropdown-primary {
- flex: 1;
- }
+ .dropdown-primary {
+ flex: 1;
+ }
- .dropdown-toggle {
- width: auto;
- }
+ .dropdown-toggle {
+ width: auto;
+ }
- .dropdown-menu {
- width: 100%;
- max-width: inherit;
- min-width: inherit;
+ .dropdown-menu {
+ width: 100%;
+ max-width: inherit;
+ min-width: inherit;
+ }
}
}
}
}
-.group-nav-container .group-search {
- padding: $gl-padding 0;
- border-bottom: 1px solid $border-color;
-}
-
.groups-listing {
.group-list-tree .group-row:first-child {
border-top: 0;
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index a28921592ec..e676d48c1f4 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -861,7 +861,7 @@ button.mini-pipeline-graph-dropdown-toggle {
height: $ci-action-dropdown-svg-size;
fill: $gl-text-color-secondary;
position: relative;
- top: 0;
+ top: 1px;
vertical-align: initial;
}
}
@@ -869,7 +869,7 @@ button.mini-pipeline-graph-dropdown-toggle {
// SVGs in the commit widget and mr widget
a.ci-action-icon-container.ci-action-icon-wrapper svg {
- top: 2px;
+ top: 4px;
}
.scrollable-menu {
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 505f6e036e3..2342c284a5e 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -140,73 +140,19 @@
}
}
-.project-home-panel,
-.group-home-panel {
- padding-top: 24px;
- padding-bottom: 24px;
-
- .group-avatar {
- float: none;
- margin: 0 auto;
-
- &.identicon {
- border-radius: 50%;
- }
- }
-
- .group-title {
- margin-top: 10px;
- margin-bottom: 10px;
- font-size: 24px;
- font-weight: $gl-font-weight-normal;
- line-height: 1;
- word-wrap: break-word;
-
- .fa {
- margin-left: 2px;
- font-size: 12px;
- vertical-align: middle;
- }
- }
-
- .group-home-desc {
- margin-left: auto;
- margin-right: auto;
- margin-bottom: 0;
- max-width: 700px;
-
- > p {
- margin-bottom: 0;
- }
- }
-
- .notifications-btn {
- .fa-bell,
- .fa-spinner {
- margin-right: 6px;
- }
-
- .fa-angle-down {
- margin-left: 6px;
- }
- }
-}
-
+.group-home-panel,
.project-home-panel {
padding-top: $gl-padding;
padding-bottom: $gl-padding;
- .project-avatar {
- width: $project-title-row-height;
- height: $project-title-row-height;
+ .home-panel-avatar {
+ width: $home-panel-title-row-height;
+ height: $home-panel-title-row-height;
flex-shrink: 0;
- flex-basis: $project-title-row-height;
- margin: 0 $gl-padding 0 0;
+ flex-basis: $home-panel-title-row-height;
}
- .project-title {
- margin-top: 8px;
- margin-bottom: 5px;
+ .home-panel-title {
font-size: 20px;
line-height: $gl-line-height-24;
font-weight: bold;
@@ -215,11 +161,7 @@
font-size: $gl-font-size-large;
}
- .project-visibility {
- color: $gl-text-color-secondary;
- }
-
- .project-topic-list {
+ .home-panel-topic-list {
font-size: $gl-font-size;
font-weight: $gl-font-weight-normal;
@@ -231,12 +173,12 @@
}
}
- .project-title-row {
+ .home-panel-title-row {
@include media-breakpoint-down(sm) {
- .project-avatar {
- width: $project-avatar-mobile-size;
- height: $project-avatar-mobile-size;
- flex-basis: $project-avatar-mobile-size;
+ .home-panel-avatar {
+ width: $home-panel-avatar-mobile-size;
+ height: $home-panel-avatar-mobile-size;
+ flex-basis: $home-panel-avatar-mobile-size;
.avatar {
font-size: 20px;
@@ -244,28 +186,26 @@
}
}
- .project-title {
+ .home-panel-title {
margin-top: 4px;
margin-bottom: 2px;
font-size: $gl-font-size;
line-height: $gl-font-size-large;
}
- .project-topic-list,
- .project-metadata {
+ .home-panel-topic-list,
+ .home-panel-metadata {
font-size: $gl-font-size-small;
}
}
}
- .project-metadata {
+ .home-panel-metadata {
font-weight: normal;
font-size: 14px;
line-height: $gl-btn-line-height;
- color: $gl-text-color-secondary;
-
- .project-license {
+ .home-panel-license {
.btn {
line-height: 0;
border-width: 0;
@@ -273,13 +213,13 @@
}
.access-request-link,
- .project-topic-list {
+ .home-panel-topic-list {
padding-left: $gl-padding-8;
border-left: 1px solid $gl-text-color-secondary;
}
}
- .project-description {
+ .home-panel-description {
@include media-breakpoint-up(md) {
font-size: $gl-font-size-large;
}
@@ -292,12 +232,11 @@
}
}
-.nav > .project-repo-buttons {
+.nav > .project-buttons {
margin-top: 0;
}
-.project-repo-buttons,
-.group-buttons {
+.project-repo-buttons {
.btn {
&:last-child {
margin-left: 0;
@@ -318,8 +257,30 @@
margin-left: 0;
}
}
+
+ .notifications-icon {
+ top: 1px;
+ margin-right: 0;
+ }
}
+ .icon {
+ top: 0;
+ }
+
+ .count-badge,
+ .btn-xs {
+ height: 24px;
+ }
+
+ .dropdown-toggle,
+ .clone-dropdown-btn {
+ .fa {
+ color: unset;
+ }
+ }
+
+ .home-panel-action-button,
.project-action-button {
margin: $gl-padding $gl-padding-8 0 0;
vertical-align: top;
@@ -385,31 +346,6 @@
}
}
-.project-repo-buttons {
- .icon {
- top: 0;
- }
-
- .count-badge,
- .btn-xs {
- height: 24px;
- }
-
- .dropdown-toggle,
- .clone-dropdown-btn {
- .fa {
- color: unset;
- }
- }
-
- .btn {
- .notifications-icon {
- top: 1px;
- margin-right: 0;
- }
- }
-}
-
.split-one {
display: inline-table;
margin-right: 12px;
@@ -772,9 +708,6 @@
.project-stats,
.project-buttons {
- font-size: 0;
- text-align: center;
-
.scrolling-tabs-container {
.scrolling-tabs {
margin-top: $gl-padding-8;
diff --git a/app/controllers/import/bitbucket_server_controller.rb b/app/controllers/import/bitbucket_server_controller.rb
index 87338488eba..f333e43b892 100644
--- a/app/controllers/import/bitbucket_server_controller.rb
+++ b/app/controllers/import/bitbucket_server_controller.rb
@@ -13,7 +13,10 @@ class Import::BitbucketServerController < Import::BaseController
# Repository names are limited to 128 characters. They must start with a
# letter or number and may contain spaces, hyphens, underscores, and periods.
# (https://community.atlassian.com/t5/Answers-Developer-Questions/stash-repository-names/qaq-p/499054)
- VALID_BITBUCKET_CHARS = /\A[\w\-_\.\s]+\z/
+ #
+ # Bitbucket Server starts personal project names with a tilde.
+ VALID_BITBUCKET_PROJECT_CHARS = /\A~?[\w\-\.\s]+\z/
+ VALID_BITBUCKET_CHARS = /\A[\w\-\.\s]+\z/
def new
end
@@ -91,7 +94,7 @@ class Import::BitbucketServerController < Import::BaseController
return render_validation_error('Missing project key') unless @project_key.present? && @repo_slug.present?
return render_validation_error('Missing repository slug') unless @repo_slug.present?
- return render_validation_error('Invalid project key') unless @project_key =~ VALID_BITBUCKET_CHARS
+ return render_validation_error('Invalid project key') unless @project_key =~ VALID_BITBUCKET_PROJECT_CHARS
return render_validation_error('Invalid repository slug') unless @repo_slug =~ VALID_BITBUCKET_CHARS
end
diff --git a/app/controllers/notification_settings_controller.rb b/app/controllers/notification_settings_controller.rb
index 384f308269a..43c4f4d220e 100644
--- a/app/controllers/notification_settings_controller.rb
+++ b/app/controllers/notification_settings_controller.rb
@@ -17,7 +17,8 @@ class NotificationSettingsController < ApplicationController
@saved = @notification_setting.update(notification_setting_params_for(@notification_setting.source))
if params[:hide_label].present?
- render_response("projects/buttons/_notifications")
+ btn_class = params[:project_id].present? ? 'btn-xs' : ''
+ render_response("shared/notifications/_new_button", btn_class)
else
render_response
end
@@ -41,9 +42,9 @@ class NotificationSettingsController < ApplicationController
can?(current_user, ability_name, resource)
end
- def render_response(response_template = "shared/notifications/_button")
+ def render_response(response_template = "shared/notifications/_button", btn_class = nil)
render json: {
- html: view_to_html_string(response_template, notification_setting: @notification_setting),
+ html: view_to_html_string(response_template, notification_setting: @notification_setting, btn_class: btn_class),
saved: @saved
}
end
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 67827b1d3bb..e6d029c356b 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -69,7 +69,7 @@ class Projects::PipelinesController < Projects::ApplicationController
render json: PipelineSerializer
.new(project: @project, current_user: @current_user)
- .represent(@pipeline, grouped: true)
+ .represent(@pipeline, show_represent_params)
end
end
end
@@ -157,6 +157,10 @@ class Projects::PipelinesController < Projects::ApplicationController
end
end
+ def show_represent_params
+ { grouped: true }
+ end
+
def create_params
params.require(:pipeline).permit(:ref, variables_attributes: %i[key secret_value])
end
diff --git a/app/helpers/import_helper.rb b/app/helpers/import_helper.rb
index 49171df1433..d3befd87ccc 100644
--- a/app/helpers/import_helper.rb
+++ b/app/helpers/import_helper.rb
@@ -8,7 +8,9 @@ module ImportHelper
end
def sanitize_project_name(name)
- name.gsub(/[^\w\-]/, '-')
+ # For personal projects in Bitbucket in the form ~username, we can
+ # just drop that leading tilde.
+ name.gsub(/\A~+/, '').gsub(/[^\w\-]/, '-')
end
def import_project_target(owner, name)
diff --git a/app/helpers/release_blog_post_helper.rb b/app/helpers/release_blog_post_helper.rb
deleted file mode 100644
index 31b5b7edc39..00000000000
--- a/app/helpers/release_blog_post_helper.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-
-module ReleaseBlogPostHelper
- def blog_post_url
- Gitlab::ReleaseBlogPost.instance.blog_post_url
- end
-end
diff --git a/app/models/identity.rb b/app/models/identity.rb
index d63dd432426..acdde4f296b 100644
--- a/app/models/identity.rb
+++ b/app/models/identity.rb
@@ -8,7 +8,7 @@ class Identity < ActiveRecord::Base
validates :provider, presence: true
validates :extern_uid, allow_blank: true, uniqueness: { scope: UniquenessScopes.scopes, case_sensitive: false }
- validates :user_id, uniqueness: { scope: UniquenessScopes.scopes }
+ validates :user, uniqueness: { scope: UniquenessScopes.scopes }
before_save :ensure_normalized_extern_uid, if: :extern_uid_changed?
after_destroy :clear_user_synced_attributes, if: :user_synced_attributes_metadata_from_provider?
diff --git a/app/models/internal_id.rb b/app/models/internal_id.rb
index e7168d49db9..e75c6eb2331 100644
--- a/app/models/internal_id.rb
+++ b/app/models/internal_id.rb
@@ -66,6 +66,17 @@ class InternalId < ActiveRecord::Base
InternalIdGenerator.new(subject, scope, usage, init).generate
end
+ # Flushing records is generally safe in a sense that those
+ # records are going to be re-created when needed.
+ #
+ # A filter condition has to be provided to not accidentally flush
+ # records for all projects.
+ def flush_records!(filter)
+ raise ArgumentError, "filter cannot be empty" if filter.blank?
+
+ where(filter).delete_all
+ end
+
def available?
@available_flag ||= ActiveRecord::Migrator.current_version >= REQUIRED_SCHEMA_VERSION # rubocop:disable Gitlab/PredicateMemoization
end
@@ -111,7 +122,7 @@ class InternalId < ActiveRecord::Base
# Generates next internal id and returns it
def generate
- InternalId.transaction do
+ subject.transaction do
# Create a record in internal_ids if one does not yet exist
# and increment its last value
#
@@ -125,7 +136,7 @@ class InternalId < ActiveRecord::Base
#
# Note this will acquire a ROW SHARE lock on the InternalId record
def track_greatest(new_value)
- InternalId.transaction do
+ subject.transaction do
(lookup || create_record).track_greatest_and_save!(new_value)
end
end
@@ -148,7 +159,7 @@ class InternalId < ActiveRecord::Base
# violation. We can safely roll-back the nested transaction and perform
# a lookup instead to retrieve the record.
def create_record
- InternalId.transaction(requires_new: true) do
+ subject.transaction(requires_new: true) do
InternalId.create!(
**scope,
usage: usage_value,
diff --git a/app/models/project.rb b/app/models/project.rb
index 15465d9b356..da77479fe1f 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -1585,6 +1585,13 @@ class Project < ActiveRecord::Base
def after_import
repository.after_import
wiki.repository.after_import
+
+ # The import assigns iid values on its own, e.g. by re-using GitHub ids.
+ # Flush existing InternalId records for this project for consistency reasons.
+ # Those records are going to be recreated with the next normal creation
+ # of a model instance (e.g. an Issue).
+ InternalId.flush_records!(project: self)
+
import_state.finish
import_state.remove_jid
update_project_counter_caches
@@ -1689,11 +1696,19 @@ class Project < ActiveRecord::Base
.append(key: 'CI_PROJECT_NAMESPACE', value: namespace.full_path)
.append(key: 'CI_PROJECT_URL', value: web_url)
.append(key: 'CI_PROJECT_VISIBILITY', value: visibility)
+ .concat(pages_variables)
.concat(container_registry_variables)
.concat(auto_devops_variables)
.concat(api_variables)
end
+ def pages_variables
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ variables.append(key: 'CI_PAGES_DOMAIN', value: Gitlab.config.pages.host)
+ variables.append(key: 'CI_PAGES_URL', value: pages_url)
+ end
+ end
+
def api_variables
Gitlab::Ci::Variables::Collection.new.tap do |variables|
variables.append(key: 'CI_API_V4_URL', value: API::Helpers::Version.new('v4').root_url)
diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb
index a252052200a..71f5607dbdb 100644
--- a/app/models/project_services/bamboo_service.rb
+++ b/app/models/project_services/bamboo_service.rb
@@ -80,19 +80,27 @@ class BambooService < CiService
private
- def get_build_result_index
- # When Bamboo returns multiple results for a given changeset, arbitrarily assume the most relevant result to be the last one.
- -1
+ def get_build_result(response)
+ return if response.code != 200
+
+ # May be nil if no result, a single result hash, or an array if multiple results for a given changeset.
+ result = response.dig('results', 'results', 'result')
+
+ # In case of multiple results, arbitrarily assume the last one is the most relevant.
+ return result.last if result.is_a?(Array)
+
+ result
end
def read_build_page(response)
+ result = get_build_result(response)
key =
- if response.code != 200 || response.dig('results', 'results', 'size') == '0'
+ if result.blank?
# If actual build link can't be determined, send user to build summary page.
build_key
else
# If actual build link is available, go to build result page.
- response.dig('results', 'results', 'result', get_build_result_index, 'planResultKey', 'key')
+ result.dig('planResultKey', 'key')
end
build_url("browse/#{key}")
@@ -101,11 +109,15 @@ class BambooService < CiService
def read_commit_status(response)
return :error unless response.code == 200 || response.code == 404
- status = if response.code == 404 || response.dig('results', 'results', 'size') == '0'
- 'Pending'
- else
- response.dig('results', 'results', 'result', get_build_result_index, 'buildState')
- end
+ result = get_build_result(response)
+ status =
+ if result.blank?
+ 'Pending'
+ else
+ result.dig('buildState')
+ end
+
+ return :error unless status.present?
if status.include?('Success')
'success'
diff --git a/app/serializers/cluster_application_entity.rb b/app/serializers/cluster_application_entity.rb
index 7b1a0be75ca..62b23a889c8 100644
--- a/app/serializers/cluster_application_entity.rb
+++ b/app/serializers/cluster_application_entity.rb
@@ -4,6 +4,7 @@ class ClusterApplicationEntity < Grape::Entity
expose :name
expose :status_name, as: :status
expose :status_reason
+ expose :version
expose :external_ip, if: -> (e, _) { e.respond_to?(:external_ip) }
expose :hostname, if: -> (e, _) { e.respond_to?(:hostname) }
expose :email, if: -> (e, _) { e.respond_to?(:email) }
diff --git a/app/views/clusters/clusters/_integration_form.html.haml b/app/views/clusters/clusters/_form.html.haml
index 4c47e11927e..4c47e11927e 100644
--- a/app/views/clusters/clusters/_integration_form.html.haml
+++ b/app/views/clusters/clusters/_form.html.haml
diff --git a/app/views/clusters/clusters/gcp/_show.html.haml b/app/views/clusters/clusters/gcp/_show.html.haml
deleted file mode 100644
index e9f05eaf453..00000000000
--- a/app/views/clusters/clusters/gcp/_show.html.haml
+++ /dev/null
@@ -1,50 +0,0 @@
-.form-group
- %label.append-bottom-10{ for: 'cluster-name' }
- = s_('ClusterIntegration|Kubernetes cluster name')
- .input-group
- %input.form-control.cluster-name.js-select-on-focus{ value: @cluster.name, readonly: true }
- %span.input-group-append
- = clipboard_button(text: @cluster.name, title: s_('ClusterIntegration|Copy Kubernetes cluster name'), class: 'input-group-text btn-default')
-
-= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster do |field|
- = form_errors(@cluster)
-
- = field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field|
- .form-group
- = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL')
- .input-group
- = platform_kubernetes_field.text_field :api_url, class: 'form-control js-select-on-focus', placeholder: s_('ClusterIntegration|API URL'), readonly: true
- %span.input-group-append
- = clipboard_button(text: @cluster.platform_kubernetes.api_url, title: s_('ClusterIntegration|Copy API URL'), class: 'input-group-text btn-default')
-
- .form-group
- = platform_kubernetes_field.label :ca_cert, s_('ClusterIntegration|CA Certificate')
- .input-group
- = platform_kubernetes_field.text_area :ca_cert, class: 'form-control js-select-on-focus', placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)'), readonly: true
- %span.input-group-append.clipboard-addon
- = clipboard_button(text: @cluster.platform_kubernetes.ca_cert, title: s_('ClusterIntegration|Copy CA Certificate'), class: 'input-group-text btn-blank')
-
- .form-group
- = platform_kubernetes_field.label :token, s_('ClusterIntegration|Token')
- .input-group
- = platform_kubernetes_field.text_field :token, class: 'form-control js-cluster-token js-select-on-focus', type: 'password', placeholder: s_('ClusterIntegration|Token'), readonly: true
- %span.input-group-append
- %button.btn.btn-default.input-group-text.js-show-cluster-token{ type: 'button' }
- = s_('ClusterIntegration|Show')
- = clipboard_button(text: @cluster.platform_kubernetes.token, title: s_('ClusterIntegration|Copy Token'), class: 'btn-default')
-
- - if @cluster.allow_user_defined_namespace?
- .form-group
- = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)')
- = platform_kubernetes_field.text_field :namespace, class: 'form-control', placeholder: s_('ClusterIntegration|Project namespace')
-
- .form-group
- .form-check
- = platform_kubernetes_field.check_box :authorization_type, { class: 'form-check-input', disabled: true }, 'rbac', 'abac'
- = platform_kubernetes_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster'), class: 'form-check-label label-bold'
- .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.')
-
- .form-group
- = field.submit s_('ClusterIntegration|Save changes'), class: 'btn btn-success'
diff --git a/app/views/clusters/clusters/show.html.haml b/app/views/clusters/clusters/show.html.haml
index 863a9a2f704..1ef76ef801e 100644
--- a/app/views/clusters/clusters/show.html.haml
+++ b/app/views/clusters/clusters/show.html.haml
@@ -31,7 +31,7 @@
%section#cluster-integration
%h4= @cluster.name
= render 'banner'
- = render 'integration_form'
+ = render 'form'
.cluster-applications-table#js-cluster-applications
@@ -42,10 +42,7 @@
= expanded ? _('Collapse') : _('Expand')
%p= s_('ClusterIntegration|See and edit the details for your Kubernetes cluster')
.settings-content
- - if @cluster.managed?
- = render 'clusters/clusters/gcp/show'
- - else
- = render 'clusters/clusters/user/show'
+ = render 'clusters/platforms/kubernetes/form', cluster: @cluster, platform: @cluster.platform_kubernetes, update_cluster_url_path: clusterable.cluster_path(@cluster)
%section.settings.no-animate#js-cluster-advanced-settings{ class: ('expanded' if expanded) }
.settings-header
diff --git a/app/views/clusters/clusters/user/_show.html.haml b/app/views/clusters/clusters/user/_show.html.haml
deleted file mode 100644
index cac8e72edd3..00000000000
--- a/app/views/clusters/clusters/user/_show.html.haml
+++ /dev/null
@@ -1,39 +0,0 @@
-= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster do |field|
- = form_errors(@cluster)
- .form-group
- = field.label :name, s_('ClusterIntegration|Kubernetes cluster name'), class: 'label-bold'
- = field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Kubernetes cluster name')
-
- = field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field|
- .form-group
- = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL'), class: 'label-bold'
- = platform_kubernetes_field.text_field :api_url, class: 'form-control', placeholder: s_('ClusterIntegration|API URL')
-
- .form-group
- = platform_kubernetes_field.label :ca_cert, s_('ClusterIntegration|CA Certificate'), class: 'label-bold'
- = platform_kubernetes_field.text_area :ca_cert, class: 'form-control', placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)')
-
- .form-group
- = platform_kubernetes_field.label :token, s_('ClusterIntegration|Token'), class: 'label-bold'
- .input-group
- = platform_kubernetes_field.text_field :token, class: 'form-control js-cluster-token', type: 'password', placeholder: s_('ClusterIntegration|Token'), autocomplete: 'off'
- %span.input-group-append.clipboard-addon
- .input-group-text
- %button.js-show-cluster-token.btn-blank{ type: 'button' }
- = s_('ClusterIntegration|Show')
-
- - if @cluster.allow_user_defined_namespace?
- .form-group
- = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)'), class: 'label-bold'
- = platform_kubernetes_field.text_field :namespace, class: 'form-control', placeholder: s_('ClusterIntegration|Project namespace')
-
- .form-group
- .form-check
- = platform_kubernetes_field.check_box :authorization_type, { class: 'form-check-input', disabled: true }, 'rbac', 'abac'
- = platform_kubernetes_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster'), class: 'form-check-label label-bold'
- .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.')
-
- .form-group
- = field.submit s_('ClusterIntegration|Save changes'), class: 'btn btn-success'
diff --git a/app/views/clusters/platforms/kubernetes/_form.html.haml b/app/views/clusters/platforms/kubernetes/_form.html.haml
new file mode 100644
index 00000000000..4a452b83112
--- /dev/null
+++ b/app/views/clusters/platforms/kubernetes/_form.html.haml
@@ -0,0 +1,58 @@
+= form_for cluster, url: update_cluster_url_path, as: :cluster do |field|
+ = form_errors(cluster)
+
+ .form-group
+ - if cluster.managed?
+ %label.append-bottom-10{ for: 'cluster-name' }
+ = s_('ClusterIntegration|Kubernetes cluster name')
+ .input-group
+ %input.form-control.cluster-name.js-select-on-focus{ value: cluster.name, readonly: true }
+ %span.input-group-append
+ = clipboard_button(text: cluster.name, title: s_('ClusterIntegration|Copy Kubernetes cluster name'), class: 'input-group-text btn-default')
+ - else
+ = field.label :name, s_('ClusterIntegration|Kubernetes cluster name'), class: 'label-bold'
+ .input-group
+ = field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Kubernetes cluster name')
+
+ = field.fields_for :platform_kubernetes, platform do |platform_field|
+ .form-group
+ = platform_field.label :api_url, s_('ClusterIntegration|API URL')
+ .input-group
+ = platform_field.text_field :api_url, class: 'form-control js-select-on-focus', placeholder: s_('ClusterIntegration|API URL'), readonly: cluster.managed?
+ - if cluster.managed?
+ %span.input-group-append
+ = clipboard_button(text: platform.api_url, title: s_('ClusterIntegration|Copy API URL'), class: 'input-group-text btn-default')
+
+ .form-group
+ = platform_field.label :ca_cert, s_('ClusterIntegration|CA Certificate')
+ .input-group
+ = platform_field.text_area :ca_cert, class: 'form-control js-select-on-focus', placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)'), readonly: cluster.managed?
+ - if cluster.managed?
+ %span.input-group-append.clipboard-addon
+ = clipboard_button(text: platform.ca_cert, title: s_('ClusterIntegration|Copy CA Certificate'), class: 'input-group-text btn-blank')
+
+ .form-group
+ = platform_field.label :token, s_('ClusterIntegration|Token')
+ .input-group
+ = platform_field.text_field :token, class: 'form-control js-cluster-token js-select-on-focus', type: 'password', placeholder: s_('ClusterIntegration|Token'), readonly: cluster.managed?
+ %span.input-group-append
+ %button.btn.btn-default.input-group-text.js-show-cluster-token{ type: 'button' }
+ = s_('ClusterIntegration|Show')
+ - if cluster.managed?
+ = clipboard_button(text: platform.token, title: s_('ClusterIntegration|Copy Token'), class: 'btn-default')
+
+ - if cluster.allow_user_defined_namespace?
+ .form-group
+ = platform_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)')
+ = platform_field.text_field :namespace, class: 'form-control', placeholder: s_('ClusterIntegration|Project namespace')
+
+ .form-group
+ .form-check
+ = platform_field.check_box :authorization_type, { class: 'form-check-input', disabled: true }, 'rbac', 'abac'
+ = platform_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster'), class: 'form-check-label label-bold'
+ .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.')
+
+ .form-group
+ = field.submit s_('ClusterIntegration|Save changes'), class: 'btn btn-success'
diff --git a/app/views/groups/_home_panel.html.haml b/app/views/groups/_home_panel.html.haml
index 88e401081f4..3a8d95f44d1 100644
--- a/app/views/groups/_home_panel.html.haml
+++ b/app/views/groups/_home_panel.html.haml
@@ -1,17 +1,58 @@
-.group-home-panel.text-center.border-bottom
- %div{ class: container_class }
- .avatar-container.s70.group-avatar
- = group_icon(@group, class: "avatar s70 avatar-tile")
- %h1.group-title
- = @group.name
- %span.visibility-icon.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) }
- = visibility_level_icon(@group.visibility_level, fw: false)
+- can_create_subgroups = can?(current_user, :create_subgroup, @group)
- - if @group.description.present?
- .group-home-desc
- = markdown_field(@group, :description)
+.group-home-panel
+ .row.mb-3
+ .home-panel-title-row.col-md-12.col-lg-6.d-flex
+ .avatar-container.home-panel-avatar.append-right-default.float-none
+ = group_icon(@group, class: 'avatar avatar-tile s64', width: 64, height: 64)
+ .d-flex.flex-column.flex-wrap.align-items-baseline
+ .d-inline-flex.align-items-baseline
+ %h1.home-panel-title.prepend-top-8.append-bottom-5
+ = @group.name
+ %span.visibility-icon.text-secondary.prepend-left-4.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) }
+ = visibility_level_icon(@group.visibility_level, fw: false, options: {class: 'icon'})
+ .home-panel-metadata.d-flex.align-items-center.text-secondary
+ %span
+ = _("Group")
+ - if current_user
+ %span.access-request-links.prepend-left-8
+ = render 'shared/members/access_request_links', source: @group
- - if current_user
- .group-buttons.d-none.d-sm-block
- = render 'shared/members/access_request_buttons', source: @group
- = render 'shared/notifications/button', notification_setting: @notification_setting
+ .home-panel-buttons.col-md-12.col-lg-6.d-inline-flex.flex-wrap.justify-content-lg-end
+ - if current_user
+ .group-buttons
+ = render 'shared/notifications/new_button', notification_setting: @notification_setting, btn_class: 'btn'
+ - if can? current_user, :create_projects, @group
+ - new_project_label = _("New project")
+ - new_subgroup_label = _("New subgroup")
+ - if can_create_subgroups
+ .btn-group.new-project-subgroup.droplab-dropdown.home-panel-action-button.prepend-top-default.js-new-project-subgroup.qa-new-project-or-subgroup-dropdown{ data: { project_path: new_project_path(namespace_id: @group.id), subgroup_path: new_group_path(parent_id: @group.id) } }
+ %input.btn.btn-success.dropdown-primary.js-new-group-child.qa-new-in-group-button{ type: "button", value: new_project_label, data: { action: "new-project" } }
+ %button.btn.btn-success.dropdown-toggle.js-dropdown-toggle.qa-new-project-or-subgroup-dropdown-toggle{ type: "button", data: { "dropdown-trigger" => "#new-project-or-subgroup-dropdown", 'display' => 'static' } }
+ = sprite_icon("arrow-down", css_class: "icon dropdown-btn-icon")
+ %ul#new-project-or-subgroup-dropdown.dropdown-menu.dropdown-menu-right{ data: { dropdown: true } }
+ %li.droplab-item-selected.qa-new-project-option{ role: "button", data: { value: "new-project", text: new_project_label } }
+ .menu-item
+ .icon-container
+ = icon("check", class: "list-item-checkmark")
+ .description
+ %strong= new_project_label
+ %span= s_("GroupsTree|Create a project in this group.")
+ %li.divider.droplap-item-ignore
+ %li.qa-new-subgroup-option{ role: "button", data: { value: "new-subgroup", text: new_subgroup_label } }
+ .menu-item
+ .icon-container
+ = icon("check", class: "list-item-checkmark")
+ .description
+ %strong= new_subgroup_label
+ %span= s_("GroupsTree|Create a subgroup in this group.")
+ - else
+ = link_to new_project_label, new_project_path(namespace_id: @group.id), class: "btn btn-success"
+
+ - if @group.description.present?
+ .group-home-desc.mt-1
+ .home-panel-description
+ .home-panel-description-markdown.read-more-container
+ = markdown_field(@group, :description)
+ %button.btn.btn-blank.btn-link.js-read-more-trigger.d-lg-none{ type: "button" }
+ = _("Read more")
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index cc294f6a931..77fe88dacb7 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -1,66 +1,41 @@
- @no_container = true
- breadcrumb_title _("Details")
-- can_create_subgroups = can?(current_user, :create_subgroup, @group)
+- @content_class = "limit-container-width" unless fluid_layout
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: "#{@group.name} activity")
-= render 'groups/home_panel'
-
-.groups-listing{ class: container_class, data: { endpoints: { default: group_children_path(@group, format: :json), shared: group_shared_projects_path(@group, format: :json) } } }
- .top-area.group-nav-container
- .group-search
- = render "shared/groups/search_form"
- - if can? current_user, :create_projects, @group
- - new_project_label = _("New project")
- - new_subgroup_label = _("New subgroup")
- - if can_create_subgroups
- .btn-group.new-project-subgroup.droplab-dropdown.js-new-project-subgroup.qa-new-project-or-subgroup-dropdown{ data: { project_path: new_project_path(namespace_id: @group.id), subgroup_path: new_group_path(parent_id: @group.id) } }
- %input.btn.btn-success.dropdown-primary.js-new-group-child.qa-new-in-group-button{ type: "button", value: new_project_label, data: { action: "new-project" } }
- %button.btn.btn-success.dropdown-toggle.js-dropdown-toggle.qa-new-project-or-subgroup-dropdown-toggle{ type: "button", data: { "dropdown-trigger" => "#new-project-or-subgroup-dropdown", 'display' => 'static' } }
- = icon("caret-down", class: "dropdown-btn-icon")
- %ul#new-project-or-subgroup-dropdown.dropdown-menu.dropdown-menu-right{ data: { dropdown: true } }
- %li.droplab-item-selected.qa-new-project-option{ role: "button", data: { value: "new-project", text: new_project_label } }
- .menu-item
- .icon-container
- = icon("check", class: "list-item-checkmark")
- .description
- %strong= new_project_label
- %span= s_("GroupsTree|Create a project in this group.")
- %li.divider.droplap-item-ignore
- %li.qa-new-subgroup-option{ role: "button", data: { value: "new-subgroup", text: new_subgroup_label } }
- .menu-item
- .icon-container
- = icon("check", class: "list-item-checkmark")
- .description
- %strong= new_subgroup_label
- %span= s_("GroupsTree|Create a subgroup in this group.")
- - else
- = link_to new_project_label, new_project_path(namespace_id: @group.id), class: "btn btn-success"
-
- .scrolling-tabs-container.inner-page-scroll-tabs
- .fade-left= icon('angle-left')
- .fade-right= icon('angle-right')
- %ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs
- %li.js-subgroups_and_projects-tab
- = link_to group_path, data: { target: 'div#subgroups_and_projects', action: 'subgroups_and_projects', toggle: 'tab'} do
- = _("Subgroups and projects")
- %li.js-shared-tab
- = link_to group_shared_path, data: { target: 'div#shared', action: 'shared', toggle: 'tab'} do
- = _("Shared projects")
- %li.js-archived-tab
- = link_to group_archived_path, data: { target: 'div#archived', action: 'archived', toggle: 'tab'} do
- = _("Archived projects")
-
- .nav-controls
- = render "shared/groups/dropdown", options_hash: subgroups_sort_options_hash
-
- .tab-content
- #subgroups_and_projects.tab-pane
- = render "subgroups_and_projects", group: @group
-
- #shared.tab-pane
- = render "shared_projects", group: @group
-
- #archived.tab-pane
- = render "archived_projects", group: @group
+%div{ class: [container_class, ("limit-container-width" unless fluid_layout)] }
+ = render 'groups/home_panel'
+
+ .groups-listing{ data: { endpoints: { default: group_children_path(@group, format: :json), shared: group_shared_projects_path(@group, format: :json) } } }
+ .top-area.group-nav-container
+ .scrolling-tabs-container.inner-page-scroll-tabs
+ .fade-left= icon('angle-left')
+ .fade-right= icon('angle-right')
+ %ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs
+ %li.js-subgroups_and_projects-tab
+ = link_to group_path, data: { target: 'div#subgroups_and_projects', action: 'subgroups_and_projects', toggle: 'tab'} do
+ = _("Subgroups and projects")
+ %li.js-shared-tab
+ = link_to group_shared_path, data: { target: 'div#shared', action: 'shared', toggle: 'tab'} do
+ = _("Shared projects")
+ %li.js-archived-tab
+ = link_to group_archived_path, data: { target: 'div#archived', action: 'archived', toggle: 'tab'} do
+ = _("Archived projects")
+
+ .nav-controls.d-block.d-md-flex
+ .group-search
+ = render "shared/groups/search_form"
+
+ = render "shared/groups/dropdown", options_hash: subgroups_sort_options_hash
+
+ .tab-content
+ #subgroups_and_projects.tab-pane
+ = render "subgroups_and_projects", group: @group
+
+ #shared.tab-pane
+ = render "shared_projects", group: @group
+
+ #archived.tab-pane
+ = render "archived_projects", group: @group
diff --git a/app/views/ide/_show.html.haml b/app/views/ide/_show.html.haml
index b24d6e27536..057225d021f 100644
--- a/app/views/ide/_show.html.haml
+++ b/app/views/ide/_show.html.haml
@@ -4,7 +4,7 @@
- content_for :page_specific_javascripts do
= stylesheet_link_tag 'page_bundles/ide'
-#ide.ide-loading{ data: ide_data() }
+#ide.ide-loading{ data: ide_data }
.text-center
= icon('spinner spin 2x')
%h2.clgray= _('Loading the GitLab IDE...')
diff --git a/app/views/import/bitbucket_server/status.html.haml b/app/views/import/bitbucket_server/status.html.haml
index ef69197e453..9280f12e187 100644
--- a/app/views/import/bitbucket_server/status.html.haml
+++ b/app/views/import/bitbucket_server/status.html.haml
@@ -56,7 +56,7 @@
.project-path.input-group-prepend
- if current_user.can_select_namespace?
- selected = params[:namespace_id] || :extra_group
- - opts = current_user.can_create_group? ? { extra_group: Group.new(name: repo.project_key, path: repo.project_key) } : {}
+ - opts = current_user.can_create_group? ? { extra_group: Group.new(name: sanitize_project_name(repo.project_key), path: sanitize_project_name(repo.project_key)) } : {}
= select_tag :namespace_id, namespaces_options(selected, opts.merge({ display_path: true })), { class: 'input-group-text select2 js-select-namespace', tabindex: 1 }
- else
= text_field_tag :path, current_user.namespace_path, class: "input-group-text input-large form-control", tabindex: 1, disabled: true
diff --git a/app/views/layouts/header/_help_dropdown.html.haml b/app/views/layouts/header/_help_dropdown.html.haml
index 513902890af..cd9128c452b 100644
--- a/app/views/layouts/header/_help_dropdown.html.haml
+++ b/app/views/layouts/header/_help_dropdown.html.haml
@@ -1,12 +1,8 @@
-- show_blog_link = current_user_menu?(:help) && blog_post_url.present?
%ul
- if current_user_menu?(:help)
%li
= link_to _("Help"), help_path
%li.divider
- - if show_blog_link
- %li
- = link_to _("What's new?"), blog_post_url
%li
= link_to _("Submit feedback"), "https://about.gitlab.com/submit-feedback"
- if current_user_menu?(:help) || current_user_menu?(:settings) || current_user_menu?(:profile)
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index 65537cf56de..7694217eb28 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -1,17 +1,17 @@
- empty_repo = @project.empty_repo?
- show_auto_devops_callout = show_auto_devops_callout?(@project)
.project-home-panel{ class: ("empty-project" if empty_repo) }
- .project-header.row.append-bottom-8
- .project-title-row.col-md-12.col-lg-6.d-flex
- .avatar-container.project-avatar.float-none
+ .row.append-bottom-8
+ .home-panel-title-row.col-md-12.col-lg-6.d-flex
+ .avatar-container.home-panel-avatar.append-right-default.float-none
= project_icon(@project, alt: @project.name, class: 'avatar avatar-tile s64', width: 64, height: 64)
.d-flex.flex-column.flex-wrap.align-items-baseline
.d-inline-flex.align-items-baseline
- %h1.project-title.qa-project-name
+ %h1.home-panel-title.prepend-top-8.append-bottom-5.qa-project-name
= @project.name
- %span.project-visibility.prepend-left-8.d-inline-flex.align-items-baseline.visibility-icon.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@project) }
+ %span.visibility-icon.text-secondary.prepend-left-4.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@project) }
= visibility_level_icon(@project.visibility_level, fw: false, options: {class: 'icon'})
- .project-metadata.d-flex.align-items-center
+ .home-panel-metadata.d-flex.align-items-center.text-secondary
- if can?(current_user, :read_project, @project)
%span.text-secondary
= s_('ProjectPage|Project ID: %{project_id}') % { project_id: @project.id }
@@ -19,7 +19,7 @@
%span.access-request-links.prepend-left-8
= render 'shared/members/access_request_links', source: @project
- if @project.tag_list.present?
- %span.project-topic-list.d-inline-flex.prepend-left-8.has-tooltip{ data: { container: 'body' }, title: @project.has_extra_topics? ? @project.tag_list.join(', ') : nil }
+ %span.home-panel-topic-list.d-inline-flex.prepend-left-8.has-tooltip{ data: { container: 'body' }, title: @project.has_extra_topics? ? @project.tag_list.join(', ') : nil }
= sprite_icon('tag', size: 16, css_class: 'icon append-right-4')
= @project.topics_to_show
- if @project.has_extra_topics?
@@ -29,7 +29,7 @@
.project-repo-buttons.col-md-12.col-lg-6.d-inline-flex.flex-wrap.justify-content-lg-end
- if current_user
.d-inline-flex
- = render 'projects/buttons/notifications', notification_setting: @notification_setting, btn_class: 'btn-xs'
+ = render 'shared/notifications/new_button', notification_setting: @notification_setting, btn_class: 'btn-xs'
.count-buttons.d-inline-flex
= render 'projects/buttons/star'
@@ -44,13 +44,13 @@
- if can?(current_user, :download_code, @project)
%nav.project-stats
- .nav-links.quick-links.mt-3
+ .nav-links.quick-links
= render 'stat_anchor_list', anchors: @project.statistics_anchors(show_auto_devops_callout: show_auto_devops_callout)
- .project-home-desc.mt-1
+ .home-panel-home-desc.mt-1
- if @project.description.present?
- .project-description
- .project-description-markdown.read-more-container
+ .home-panel-description
+ .home-panel-description-markdown.read-more-container
= markdown_field(@project, :description)
%button.btn.btn-blank.btn-link.js-read-more-trigger.d-lg-none{ type: "button" }
= _("Read more")
diff --git a/app/views/projects/deploy_keys/_index.html.haml b/app/views/projects/deploy_keys/_index.html.haml
index 062aa423bde..24d665761cc 100644
--- a/app/views/projects/deploy_keys/_index.html.haml
+++ b/app/views/projects/deploy_keys/_index.html.haml
@@ -3,7 +3,7 @@
.settings-header
%h4
Deploy Keys
- %button.btn.js-settings-toggle.qa-expand-deploy-keys{ type: 'button' }
+ %button.btn.js-settings-toggle{ type: 'button' }
= expanded ? 'Collapse' : 'Expand'
%p
Deploy keys allow read-only or read-write (if enabled) access to your repository. Deploy keys can be used for CI, staging or production servers. You can create a deploy key or add an existing one.
diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml
index 56c043b2b3d..4779b5c434e 100644
--- a/app/views/projects/milestones/_form.html.haml
+++ b/app/views/projects/milestones/_form.html.haml
@@ -5,23 +5,23 @@
.row
.col-md-6
.form-group.row
- = f.label :title, "Title", class: "col-form-label col-sm-2"
+ = f.label :title, _('Title'), class: 'col-form-label col-sm-2'
.col-sm-10
- = f.text_field :title, maxlength: 255, class: "qa-milestone-title form-control", required: true, autofocus: true
+ = f.text_field :title, maxlength: 255, class: 'qa-milestone-title form-control', required: true, autofocus: true
.form-group.row.milestone-description
- = f.label :description, "Description", class: "col-form-label col-sm-2"
+ = f.label :description, _('Description'), class: 'col-form-label col-sm-2'
.col-sm-10
= render layout: 'projects/md_preview', locals: { url: preview_markdown_path(@project) } do
- = render 'projects/zen', f: f, attr: :description, classes: 'qa-milestone-description note-textarea', placeholder: 'Write milestone description...'
+ = render 'projects/zen', f: f, attr: :description, classes: 'qa-milestone-description note-textarea', placeholder: _('Write milestone description...')
= render 'shared/notes/hints'
.clearfix
.error-alert
- = render "shared/milestones/form_dates", f: f
+ = render 'shared/milestones/form_dates', f: f
.form-actions
- if @milestone.new_record?
- = f.submit 'Create milestone', class: "btn-success btn qa-milestone-create-button"
- = link_to "Cancel", project_milestones_path(@project), class: "btn btn-cancel"
+ = f.submit _('Create milestone'), class: 'btn-create btn qa-milestone-create-button'
+ = link_to _('Cancel'), project_milestones_path(@project), class: 'btn btn-cancel'
- else
- = f.submit 'Save changes', class: "btn-success btn"
- = link_to "Cancel", project_milestone_path(@project, @milestone), class: "btn btn-cancel"
+ = f.submit _('Save changes'), class: 'btn-success btn'
+ = link_to _('Cancel'), project_milestone_path(@project, @milestone), class: 'btn btn-cancel'
diff --git a/app/views/projects/milestones/edit.html.haml b/app/views/projects/milestones/edit.html.haml
index 4006a468792..aa564e00af9 100644
--- a/app/views/projects/milestones/edit.html.haml
+++ b/app/views/projects/milestones/edit.html.haml
@@ -1,14 +1,14 @@
- @no_container = true
-- breadcrumb_title "Edit"
-- add_to_breadcrumbs "Milestones", project_milestones_path(@project)
-- page_title "Edit", @milestone.title, "Milestones"
+- breadcrumb_title _('Edit')
+- add_to_breadcrumbs _('Milestones'), project_milestones_path(@project)
+- page_title _('Edit'), @milestone.title, _('Milestones')
%div{ class: container_class }
%h3.page-title
- Edit Milestone
+ = _('Edit Milestone')
%hr
- = render "form"
+ = render 'form'
diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml
index ba853ef0708..a3414c16d73 100644
--- a/app/views/projects/milestones/index.html.haml
+++ b/app/views/projects/milestones/index.html.haml
@@ -1,5 +1,5 @@
- @no_container = true
-- page_title 'Milestones'
+- page_title _('Milestones')
%div{ class: container_class }
.top-area
@@ -9,8 +9,8 @@
= render 'shared/milestones/search_form'
= render 'shared/milestones_sort_dropdown'
- if can?(current_user, :admin_milestone, @project)
- = link_to new_project_milestone_path(@project), class: "btn btn-success qa-new-project-milestone", title: 'New milestone' do
- New milestone
+ = link_to new_project_milestone_path(@project), class: 'btn btn-success qa-new-project-milestone', title: _('New milestone') do
+ = _('New milestone')
.milestones
#delete-milestone-modal
@@ -21,6 +21,6 @@
- if @milestones.blank?
%li
- .nothing-here-block No milestones to show
+ .nothing-here-block= _('No milestones to show')
= paginate @milestones, theme: 'gitlab'
diff --git a/app/views/projects/milestones/new.html.haml b/app/views/projects/milestones/new.html.haml
index 01cc951e8c2..79207fd70b5 100644
--- a/app/views/projects/milestones/new.html.haml
+++ b/app/views/projects/milestones/new.html.haml
@@ -1,12 +1,12 @@
- @no_container = true
-- add_to_breadcrumbs "Milestones", project_milestones_path(@project)
-- breadcrumb_title "New"
-- page_title "New Milestone"
+- add_to_breadcrumbs _('Milestones'), project_milestones_path(@project)
+- breadcrumb_title _('New')
+- page_title _('New Milestone')
%div{ class: container_class }
%h3.page-title
- New Milestone
+ = _('New Milestone')
%hr
- = render "form"
+ = render 'form'
diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml
index 5859de61d71..0542b349e44 100644
--- a/app/views/projects/milestones/show.html.haml
+++ b/app/views/projects/milestones/show.html.haml
@@ -1,30 +1,30 @@
- @no_container = true
-- add_to_breadcrumbs "Milestones", project_milestones_path(@project)
+- add_to_breadcrumbs _('Milestones'), project_milestones_path(@project)
- breadcrumb_title @milestone.title
-- page_title @milestone.title, "Milestones"
+- page_title @milestone.title, _('Milestones')
- page_description @milestone.description
%div{ class: container_class }
.detail-page-header.milestone-page-header
.status-box{ class: status_box_class(@milestone) }
- if @milestone.closed?
- Closed
+ = _('Closed')
- elsif @milestone.expired?
- Past due
+ = _('Past due')
- elsif @milestone.upcoming?
- Upcoming
+ = _('Upcoming')
- else
- Open
+ = _('Open')
.header-text-content
%span.identifier
%strong
- Milestone
+ = _('Milestone')
- if @milestone.due_date || @milestone.start_date
= milestone_date_range(@milestone)
.milestone-buttons
- if can?(current_user, :admin_milestone, @project)
- = link_to edit_project_milestone_path(@project, @milestone), class: "btn btn-grouped btn-nr" do
- Edit
+ = link_to edit_project_milestone_path(@project, @milestone), class: 'btn btn-grouped btn-nr' do
+ = _('Edit')
- if @project.group
%button.js-promote-project-milestone-button.btn.btn-grouped{ data: { toggle: 'modal',
@@ -39,13 +39,13 @@
#promote-milestone-modal
- if @milestone.active?
- = link_to 'Close milestone', project_milestone_path(@project, @milestone, milestone: {state_event: :close }), method: :put, class: "btn btn-close btn-nr btn-grouped"
+ = link_to _('Close milestone'), project_milestone_path(@project, @milestone, milestone: {state_event: :close }), method: :put, class: 'btn btn-close btn-nr btn-grouped'
- else
- = link_to 'Reopen milestone', project_milestone_path(@project, @milestone, milestone: {state_event: :activate }), method: :put, class: "btn btn-reopen btn-nr btn-grouped"
+ = link_to _('Reopen milestone'), project_milestone_path(@project, @milestone, milestone: {state_event: :activate }), method: :put, class: 'btn btn-reopen btn-nr btn-grouped'
= render 'shared/milestones/delete_button'
- %a.btn.btn-default.btn-grouped.float-right.d-block.d-sm-none.js-sidebar-toggle{ href: "#" }
+ %a.btn.btn-default.btn-grouped.float-right.d-block.d-sm-none.js-sidebar-toggle{ href: '#' }
= icon('angle-double-left')
.detail-page-description.milestone-detail
@@ -62,10 +62,10 @@
- if can?(current_user, :read_issue, @project) && @milestone.total_items_count(current_user).zero?
.alert.alert-success.prepend-top-default
- %span Assign some issues to this milestone.
+ %span= _('Assign some issues to this milestone.')
- elsif @milestone.complete?(current_user) && @milestone.active?
.alert.alert-success.prepend-top-default
- %span All issues for this milestone are closed. You may close this milestone now.
+ %span= _('All issues for this milestone are closed. You may close this milestone now.')
= render 'deprecation_message'
= render 'shared/milestones/tabs', milestone: @milestone
diff --git a/app/views/shared/members/_access_request_buttons.html.haml b/app/views/shared/members/_access_request_buttons.html.haml
deleted file mode 100644
index ebae58f28ba..00000000000
--- a/app/views/shared/members/_access_request_buttons.html.haml
+++ /dev/null
@@ -1,20 +0,0 @@
-- model_name = source.model_name.to_s.downcase
-
-- if can?(current_user, :"destroy_#{model_name}_member", source.members.find_by(user_id: current_user.id)) # rubocop: disable CodeReuse/ActiveRecord
- .project-action-button.inline
- - link_text = source.is_a?(Group) ? _('Leave group') : _('Leave project')
- = link_to link_text, polymorphic_path([:leave, source, :members]),
- method: :delete,
- data: { confirm: leave_confirmation_message(source) },
- class: 'btn'
-- elsif requester = source.requesters.find_by(user_id: current_user.id) # rubocop: disable CodeReuse/ActiveRecord
- .project-action-button.inline
- = link_to _('Withdraw Access Request'), polymorphic_path([:leave, source, :members]),
- method: :delete,
- data: { confirm: remove_member_message(requester) },
- class: 'btn'
-- elsif source.request_access_enabled && can?(current_user, :request_access, source)
- .project-action-button.inline
- = link_to _('Request Access'), polymorphic_path([:request_access, source, :members]),
- method: :post,
- class: 'btn'
diff --git a/app/views/shared/notifications/_button.html.haml b/app/views/shared/notifications/_button.html.haml
index 30860988bbb..2ece7b7f701 100644
--- a/app/views/shared/notifications/_button.html.haml
+++ b/app/views/shared/notifications/_button.html.haml
@@ -1,7 +1,7 @@
- btn_class = local_assigns.fetch(:btn_class, nil)
- if notification_setting
- .js-notification-dropdown.notification-dropdown.project-action-button.dropdown.inline
+ .js-notification-dropdown.notification-dropdown.home-panel-action-button.dropdown.inline
= form_for notification_setting, remote: true, html: { class: "inline notification-form" } do |f|
= hidden_setting_source_input(notification_setting)
= f.hidden_field :level, class: "notification_setting_level"
diff --git a/app/views/projects/buttons/_notifications.html.haml b/app/views/shared/notifications/_new_button.html.haml
index a8b728527c8..6d26dbebbc8 100644
--- a/app/views/projects/buttons/_notifications.html.haml
+++ b/app/views/shared/notifications/_new_button.html.haml
@@ -1,7 +1,7 @@
-- btn_class = local_assigns.fetch(:btn_class, "btn-xs")
+- btn_class = local_assigns.fetch(:btn_class, nil)
- if notification_setting
- .js-notification-dropdown.notification-dropdown.project-action-button.dropdown.inline
+ .js-notification-dropdown.notification-dropdown.home-panel-action-button.prepend-top-default.append-right-8.dropdown.inline
= form_for notification_setting, remote: true, html: { class: "inline notification-form no-label" } do |f|
= hidden_setting_source_input(notification_setting)
= hidden_field_tag "hide_label", true
@@ -9,14 +9,14 @@
.js-notification-toggle-btns
%div{ class: ("btn-group" if notification_setting.custom?) }
- if notification_setting.custom?
- %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, class: "#{btn_class}", "aria-label" => _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, data: { container: "body", toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } }
+ %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, class: "#{btn_class}", "aria-label" => _("Notification setting - %{notification_title}") % { notification_title: notification_title(notification_setting.level) }, data: { container: "body", placement: 'top', toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } }
= sprite_icon("notifications", css_class: "icon notifications-icon js-notifications-icon")
%span.js-notification-loading.fa.hidden
%button.btn.dropdown-toggle{ data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" }, class: "#{btn_class}" }
= sprite_icon("arrow-down", css_class: "icon mr-0")
.sr-only Toggle dropdown
- else
- %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: "Notification setting - #{notification_title(notification_setting.level)}", class: "#{btn_class}", "aria-label" => "Notification setting: #{notification_title(notification_setting.level)}", data: { container: "body", toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
+ %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: "Notification setting - #{notification_title(notification_setting.level)}", class: "#{btn_class}", "aria-label" => "Notification setting: #{notification_title(notification_setting.level)}", data: { container: "body", placement: 'top', toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
= sprite_icon("notifications", css_class: "icon notifications-icon js-notifications-icon")
%span.js-notification-loading.fa.hidden
= sprite_icon("arrow-down", css_class: "icon")
diff --git a/changelogs/unreleased/24680-support-bamboo-api-polymorphism.yml b/changelogs/unreleased/24680-support-bamboo-api-polymorphism.yml
new file mode 100644
index 00000000000..5117195cd0c
--- /dev/null
+++ b/changelogs/unreleased/24680-support-bamboo-api-polymorphism.yml
@@ -0,0 +1,5 @@
+---
+title: "Support bamboo api polymorphism"
+merge_request: 24680
+author: Alex Lossent
+type: fixed \ No newline at end of file
diff --git a/changelogs/unreleased/25341-add-what-s-new-menu-item-in-top-navigation.yml b/changelogs/unreleased/25341-add-what-s-new-menu-item-in-top-navigation.yml
deleted file mode 100644
index da1777827cb..00000000000
--- a/changelogs/unreleased/25341-add-what-s-new-menu-item-in-top-navigation.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Resolve Add What's new menu item in top navigation
-merge_request: 23186
-author:
-type: added
diff --git a/changelogs/unreleased/53104-redesign-group-overview-ui-mvc.yml b/changelogs/unreleased/53104-redesign-group-overview-ui-mvc.yml
new file mode 100644
index 00000000000..cb810b7ac7f
--- /dev/null
+++ b/changelogs/unreleased/53104-redesign-group-overview-ui-mvc.yml
@@ -0,0 +1,5 @@
+---
+title: Refresh group overview to match project overview
+merge_request: 23866
+author:
+type: changed
diff --git a/changelogs/unreleased/55820-adds-common-name-chart-value.yml b/changelogs/unreleased/55820-adds-common-name-chart-value.yml
new file mode 100644
index 00000000000..1871abbfc6b
--- /dev/null
+++ b/changelogs/unreleased/55820-adds-common-name-chart-value.yml
@@ -0,0 +1,5 @@
+---
+title: Ensure Cert Manager works with Auto DevOps URLs greater than 64 bytes
+merge_request: 24683
+author:
+type: fixed
diff --git a/changelogs/unreleased/56379-pipeline-stages-job-action-button-icon-is-not-aligned.yml b/changelogs/unreleased/56379-pipeline-stages-job-action-button-icon-is-not-aligned.yml
new file mode 100644
index 00000000000..ec8a1d9d6ea
--- /dev/null
+++ b/changelogs/unreleased/56379-pipeline-stages-job-action-button-icon-is-not-aligned.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve Pipeline stages job action button icon is not aligned
+merge_request: 24577
+author:
+type: fixed
diff --git a/changelogs/unreleased/56398-fix-cluster-installation-loading-state.yml b/changelogs/unreleased/56398-fix-cluster-installation-loading-state.yml
new file mode 100644
index 00000000000..39261cce8ef
--- /dev/null
+++ b/changelogs/unreleased/56398-fix-cluster-installation-loading-state.yml
@@ -0,0 +1,5 @@
+---
+title: Fix cluster installation processing spinner
+merge_request: 24485
+author:
+type: fixed
diff --git a/changelogs/unreleased/ab-54270-github-iid.yml b/changelogs/unreleased/ab-54270-github-iid.yml
new file mode 100644
index 00000000000..1776b0aeb86
--- /dev/null
+++ b/changelogs/unreleased/ab-54270-github-iid.yml
@@ -0,0 +1,5 @@
+---
+title: Improve efficiency of GitHub importer by reducing amount of locks needed.
+merge_request: 24102
+author:
+type: performance
diff --git a/changelogs/unreleased/adrianmoisey-GITLAB_PAGES_PREDEFINED_VARIABLES.yml b/changelogs/unreleased/adrianmoisey-GITLAB_PAGES_PREDEFINED_VARIABLES.yml
new file mode 100644
index 00000000000..a664c44e1d7
--- /dev/null
+++ b/changelogs/unreleased/adrianmoisey-GITLAB_PAGES_PREDEFINED_VARIABLES.yml
@@ -0,0 +1,5 @@
+---
+title: Add GitLab Pages predefined CI variables 'CI_PAGES_DOMAIN' and 'CI_PAGES_URL'
+merge_request: 24504
+author: Adrian Moisey
+type: added
diff --git a/changelogs/unreleased/an-opentracing-render-tracing.yml b/changelogs/unreleased/an-opentracing-render-tracing.yml
new file mode 100644
index 00000000000..6ff7f1f3cf2
--- /dev/null
+++ b/changelogs/unreleased/an-opentracing-render-tracing.yml
@@ -0,0 +1,5 @@
+---
+title: Add OpenTracing instrumentation for Action View Render events
+merge_request: 24728
+author:
+type: other
diff --git a/changelogs/unreleased/cluster_status_for_ugprading.yml b/changelogs/unreleased/cluster_status_for_ugprading.yml
new file mode 100644
index 00000000000..ca1f8b3a786
--- /dev/null
+++ b/changelogs/unreleased/cluster_status_for_ugprading.yml
@@ -0,0 +1,5 @@
+---
+title: Expose version for each application in cluster_status JSON endpoint
+merge_request: 24791
+author:
+type: other
diff --git a/changelogs/unreleased/gt-externalize-app-views-projects-milestones.yml b/changelogs/unreleased/gt-externalize-app-views-projects-milestones.yml
new file mode 100644
index 00000000000..56aaac812bb
--- /dev/null
+++ b/changelogs/unreleased/gt-externalize-app-views-projects-milestones.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings from `/app/views/projects/milestones`
+merge_request: 24726
+author: George Tsiolis
+type: other
diff --git a/changelogs/unreleased/sh-disable-nil-user-id-identity-validation.yml b/changelogs/unreleased/sh-disable-nil-user-id-identity-validation.yml
new file mode 100644
index 00000000000..5af3bdce51b
--- /dev/null
+++ b/changelogs/unreleased/sh-disable-nil-user-id-identity-validation.yml
@@ -0,0 +1,5 @@
+---
+title: Fix failed LDAP logins when nil user_id present
+merge_request: 24749
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-issue-53419-fix.yml b/changelogs/unreleased/sh-issue-53419-fix.yml
new file mode 100644
index 00000000000..ab8b65857e2
--- /dev/null
+++ b/changelogs/unreleased/sh-issue-53419-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Bitbucket Server import not allowing personal projects
+merge_request: 23601
+author:
+type: fixed
diff --git a/config/initializers/tracing.rb b/config/initializers/tracing.rb
index d5bef8edb43..ddd91150c90 100644
--- a/config/initializers/tracing.rb
+++ b/config/initializers/tracing.rb
@@ -25,6 +25,7 @@ if Gitlab::Tracing.enabled?
# Instrument Rails
Gitlab::Tracing::Rails::ActiveRecordSubscriber.instrument
+ Gitlab::Tracing::Rails::ActionViewSubscriber.instrument
# In multi-processed clustered architectures (puma, unicorn) don't
# start tracing until the worker processes are spawned. This works
diff --git a/db/post_migrate/20190102152410_delete_inconsistent_internal_id_records2.rb b/db/post_migrate/20190102152410_delete_inconsistent_internal_id_records2.rb
new file mode 100644
index 00000000000..ddcddcf72a3
--- /dev/null
+++ b/db/post_migrate/20190102152410_delete_inconsistent_internal_id_records2.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+class DeleteInconsistentInternalIdRecords2 < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ # This migration cleans up any inconsistent records in internal_ids.
+ #
+ # That is, it deletes records that track a `last_value` that is
+ # smaller than the maximum internal id (usually `iid`) found in
+ # the corresponding model records.
+
+ def up
+ disable_statement_timeout do
+ delete_internal_id_records('milestones', 'project_id')
+ delete_internal_id_records('milestones', 'namespace_id', 'group_id')
+ end
+ end
+
+ class InternalId < ActiveRecord::Base
+ self.table_name = 'internal_ids'
+ enum usage: { issues: 0, merge_requests: 1, deployments: 2, milestones: 3, epics: 4, ci_pipelines: 5 }
+ end
+
+ private
+
+ def delete_internal_id_records(base_table, scope_column_name, base_scope_column_name = scope_column_name)
+ sql = <<~SQL
+ SELECT id FROM ( -- workaround for MySQL
+ SELECT internal_ids.id FROM (
+ SELECT #{base_scope_column_name} AS #{scope_column_name}, max(iid) as maximum_iid from #{base_table} GROUP BY #{scope_column_name}
+ ) maxima JOIN internal_ids USING (#{scope_column_name})
+ WHERE internal_ids.usage=#{InternalId.usages.fetch(base_table)} AND maxima.maximum_iid > internal_ids.last_value
+ ) internal_ids
+ SQL
+
+ InternalId.where("id IN (#{sql})").tap do |ids| # rubocop:disable GitlabSecurity/SqlInjection
+ say "Deleting internal_id records for #{base_table}: #{ids.map { |i| [i.project_id, i.last_value] }}" unless ids.empty?
+ end.delete_all
+ end
+end
diff --git a/doc/administration/index.md b/doc/administration/index.md
index ecb0801bac4..0b673d61139 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -89,7 +89,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Libravatar](../customization/libravatar.md): Use Libravatar instead of Gravatar for user avatars.
- [Sign-up restrictions](../user/admin_area/settings/sign_up_restrictions.md): block email addresses of specific domains, or whitelist only specific domains.
- [Access restrictions](../user/admin_area/settings/visibility_and_access_controls.md#enabled-git-access-protocols): Define which Git access protocols can be used to talk to GitLab (SSH, HTTP, HTTPS).
-- [Authentication/Authorization](../topics/authentication/index.md#gitlab-administrators): Enforce 2FA, configure external authentication with LDAP, SAML, CAS and additional Omniauth providers.
+- [Authentication and Authorization](auth/README.md): Configure external authentication with LDAP, SAML, CAS and additional providers. See also other [authentication](../topics/authentication/index.md#gitlab-administrators) topics (for example, enforcing 2FA).
- [Incoming email](incoming_email.md): Configure incoming emails to allow
users to [reply by email], create [issues by email] and
[merge requests by email], and to enable [Service Desk].
diff --git a/doc/api/project_clusters.md b/doc/api/project_clusters.md
index c51a3564211..034b9172ffa 100644
--- a/doc/api/project_clusters.md
+++ b/doc/api/project_clusters.md
@@ -245,6 +245,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer | yes | The ID of the project owned by the authenticated user |
+| `cluster_id` | integer | yes | The ID of the cluster |
| `name` | String | no | The name of the cluster |
| `platform_kubernetes_attributes[api_url]` | String | no | The URL to access the Kubernetes API |
| `platform_kubernetes_attributes[token]` | String | no | The token to authenticate against Kubernetes |
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index 9f552a10589..104c64a89ce 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -112,7 +112,7 @@ GET /projects/:id/repository/archive[.format]
```
`format` is an optional suffix for the archive format. Default is
-`tar.gz`. Options are `tar.gz`, `tar.bz2`, `tbz`, 'tbz2`, `tb2`,
+`tar.gz`. Options are `tar.gz`, `tar.bz2`, `tbz`, `tbz2`, `tb2`,
`bz2`, `tar`, and `zip`. For example, specifying `archive.zip`
would send an archive in ZIP format.
diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md
index 495ec099111..8b2ce425cf5 100644
--- a/doc/ci/caching/index.md
+++ b/doc/ci/caching/index.md
@@ -29,7 +29,7 @@ needed to compile the project:
Cache was designed to be used to speed up invocations of subsequent runs of a
given job, by keeping things like dependencies (e.g., npm packages, Go vendor
packages, etc.) so they don't have to be re-fetched from the public internet.
- While the cache can be abused to pass intermediate build results between
+ While the cache can be abused to pass intermediate build results between
stages, there may be cases where artifacts are a better fit.
- `artifacts`: **Use for stage results that will be passed between stages.**
Artifacts were designed to upload some compiled/generated bits of the build,
@@ -40,10 +40,10 @@ needed to compile the project:
comply to this rule trigger an unintuitive and illogical error message (an
enhancement is discussed at
[https://gitlab.com/gitlab-org/gitlab-ce/issues/15530](https://gitlab.com/gitlab-org/gitlab-ce/issues/15530)
- ). Artifacts need to be uploaded to the GitLab instance (not only the GitLab
- runner) before the next stage job(s) can start, so you need to evaluate
- carefully whether your bandwidth allows you to profit from parallelization
- with stages and shared artifacts before investing time in changes to the
+ ). Artifacts need to be uploaded to the GitLab instance (not only the GitLab
+ runner) before the next stage job(s) can start, so you need to evaluate
+ carefully whether your bandwidth allows you to profit from parallelization
+ with stages and shared artifacts before investing time in changes to the
setup.
@@ -90,7 +90,7 @@ cache, when declaring `cache` in your jobs, use one or a mix of the following:
that will be only available to a particular project.
- [Use a `key`](../yaml/README.md#cache-key) that fits your workflow (e.g.,
different caches on each branch). For that, you can take advantage of the
- [CI/CD predefined variables](../variables/README.md#predefined-variables-environment-variables).
+ [CI/CD predefined variables](../variables/README.md#predefined-environment-variables).
TIP: **Tip:**
Using the same Runner for your pipeline, is the most simple and efficient way to
diff --git a/doc/ci/docker/using_kaniko.md b/doc/ci/docker/using_kaniko.md
index aa6b387bc58..f354cdb398e 100644
--- a/doc/ci/docker/using_kaniko.md
+++ b/doc/ci/docker/using_kaniko.md
@@ -40,7 +40,7 @@ In the following example, kaniko is used to build a Docker image and then push
it to [GitLab Container Registry](../../user/project/container_registry.md).
The job will run only when a tag is pushed. A `config.json` file is created under
`/kaniko/.docker` with the needed GitLab Container Registry credentials taken from the
-[environment variables](../variables/README.md#predefined-variables-environment-variables)
+[environment variables](../variables/README.md#predefined-environment-variables)
GitLab CI/CD provides. In the last step, kaniko uses the `Dockerfile` under the
root directory of the project, builds the Docker image and pushes it to the
project's Container Registry while tagging it with the Git tag:
diff --git a/doc/ci/environments.md b/doc/ci/environments.md
index b9b5ceab7fb..6a9917f6430 100644
--- a/doc/ci/environments.md
+++ b/doc/ci/environments.md
@@ -249,7 +249,7 @@ the basis of [Review apps](review_apps/index.md).
NOTE: **Note:**
The `name` and `url` parameters can use most of the CI/CD variables,
-including [predefined](variables/README.md#predefined-variables-environment-variables),
+including [predefined](variables/README.md#predefined-environment-variables),
[project/group ones](variables/README.md#variables) and
[`.gitlab-ci.yml` variables](yaml/README.md#variables). You however cannot use variables
defined under `script` or on the Runner's side. There are also other variables that
diff --git a/doc/ci/examples/artifactory_and_gitlab/index.md b/doc/ci/examples/artifactory_and_gitlab/index.md
index 04b48938e1a..9e657275d50 100644
--- a/doc/ci/examples/artifactory_and_gitlab/index.md
+++ b/doc/ci/examples/artifactory_and_gitlab/index.md
@@ -107,7 +107,7 @@ Now it's time we set up [GitLab CI/CD](https://about.gitlab.com/features/gitlab-
GitLab CI/CD uses a file in the root of the repo, named `.gitlab-ci.yml`, to read the definitions for jobs
that will be executed by the configured GitLab Runners. You can read more about this file in the [GitLab Documentation](https://docs.gitlab.com/ee/ci/yaml/).
-First of all, remember to set up variables for your deployment. Navigate to your project's **Settings > CI/CD > Variables** page
+First of all, remember to set up variables for your deployment. Navigate to your project's **Settings > CI/CD > Environment variables** page
and add the following ones (replace them with your current values, of course):
- **MAVEN_REPO_URL**: `http://artifactory.example.com:8081/artifactory` (your Artifactory URL)
diff --git a/doc/ci/examples/container_scanning.md b/doc/ci/examples/container_scanning.md
index 68330261910..31c3df81fef 100644
--- a/doc/ci/examples/container_scanning.md
+++ b/doc/ci/examples/container_scanning.md
@@ -22,7 +22,7 @@ container_scanning:
variables:
DOCKER_DRIVER: overlay2
## Define two new variables based on GitLab's CI/CD predefined variables
- ## https://docs.gitlab.com/ee/ci/variables/#predefined-variables-environment-variables
+ ## https://docs.gitlab.com/ee/ci/variables/#predefined-environment-variables
CI_APPLICATION_REPOSITORY: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
CI_APPLICATION_TAG: $CI_COMMIT_SHA
allow_failure: true
@@ -87,7 +87,7 @@ container_scanning:
variables:
DOCKER_DRIVER: overlay2
## Define two new variables based on GitLab's CI/CD predefined variables
- ## https://docs.gitlab.com/ee/ci/variables/#predefined-variables-environment-variables
+ ## https://docs.gitlab.com/ee/ci/variables/#predefined-environment-variables
CI_APPLICATION_REPOSITORY: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
CI_APPLICATION_TAG: $CI_COMMIT_SHA
allow_failure: true
diff --git a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md b/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md
index 8873a1596f7..6499413baf0 100644
--- a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md
+++ b/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md
@@ -104,7 +104,7 @@ to ensure our deployments only happen when we push to the master branch.
Now, since the steps defined in `.gitlab-ci.yml` require credentials to login
to CF, you'll need to add your CF credentials as [environment
-variables](../../variables/README.md#predefined-variables-environment-variables)
+variables](../../variables/README.md#predefined-environment-variables)
on GitLab CI/CD. To set the environment variables, navigate to your project's
**Settings > CI/CD** and expand **Variables**. Name the variables
`CF_USERNAME` and `CF_PASSWORD` and set them to the correct values.
diff --git a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
index b59271e400f..61bf68fa0e8 100644
--- a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
+++ b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
@@ -47,7 +47,7 @@ This project has three jobs:
## Store API keys
-You'll need to create two variables in **Settings > CI/CD > Variables** in your GitLab project:
+You'll need to create two variables in **Settings > CI/CD > Environment variables** in your GitLab project:
- `HEROKU_STAGING_API_KEY` - Heroku API key used to deploy staging app.
- `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app.
diff --git a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
index 33a353f17f5..46e6efccaf8 100644
--- a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
+++ b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
@@ -43,7 +43,7 @@ This project has three jobs:
## Store API keys
-You'll need to create two variables in your project's **Settings > CI/CD > Variables**:
+You'll need to create two variables in your project's **Settings > CI/CD > Environment variables**:
- `HEROKU_STAGING_API_KEY` - Heroku API key used to deploy staging app.
- `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app.
diff --git a/doc/ci/triggers/README.md b/doc/ci/triggers/README.md
index c9a60feb73f..61037360326 100644
--- a/doc/ci/triggers/README.md
+++ b/doc/ci/triggers/README.md
@@ -224,5 +224,5 @@ removed with one of the future versions of GitLab. You are advised to
[ee-2017]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2017
[ee]: https://about.gitlab.com/pricing/
[variables]: ../variables/README.md
-[predef]: ../variables/README.md#predefined-variables-environment-variables
+[predef]: ../variables/README.md#predefined-environment-variables
[registry]: ../../user/project/container_registry.md
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 5195c580734..45667caf65d 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -4,27 +4,33 @@ table_display_block: true
# GitLab CI/CD Variables
-When receiving a job from GitLab CI, the [Runner] prepares the build environment.
-It starts by setting a list of **predefined variables** (environment variables)
-and a list of **user-defined variables**.
+When receiving a job from GitLab CI, the [Runner](https://docs.gitlab.com/runner/) prepares the build environment.
+It starts by setting a list of:
+
+- [Predefined environment variables](#predefined-environment-variables).
+- Other variables.
## Priority of variables
-The variables can be overwritten and they take precedence over each other in
-this order:
+Variables of different types can take precedence over other variables, depending on where they are defined.
+
+The order of precedence for variables is (from highest to lowest):
+
+1. [Trigger variables](../triggers/README.md#pass-job-variables-to-a-trigger) or [scheduled pipeline variables](../../user/project/pipelines/schedules.md#making-use-of-scheduled-pipeline-variables).
+1. Project-level [variables](#variables) or [protected variables](#protected-variables).
+1. Group-level [variables](#variables) or [protected variables](#protected-variables).
+1. YAML-defined [job-level variables](../yaml/README.md#variables).
+1. YAML-defined [global variables](../yaml/README.md#variables).
+1. [Deployment variables](#deployment-variables).
+1. [Predefined environment variables](#predefined-environment-variables).
-1. [Trigger variables][triggers] or [scheduled pipeline variables](../../user/project/pipelines/schedules.md#making-use-of-scheduled-pipeline-variables) (take precedence over all)
-1. Project-level [variables](#variables) or [protected variables](#protected-variables)
-1. Group-level [variables](#variables) or [protected variables](#protected-variables)
-1. YAML-defined [job-level variables](../yaml/README.md#variables)
-1. YAML-defined [global variables](../yaml/README.md#variables)
-1. [Deployment variables](#deployment-variables)
-1. [Predefined variables](#predefined-variables-environment-variables) (are the
- lowest in the chain)
+For example, you define:
-For example, if you define `API_TOKEN=secure` as a project variable and
-`API_TOKEN=yaml` in your `.gitlab-ci.yml`, the `API_TOKEN` will take the value
-`secure` as the project variables are higher in the chain.
+- `API_TOKEN=secure` as a project variable.
+- `API_TOKEN=yaml` in your `.gitlab-ci.yml`.
+
+`API_TOKEN` will take the value `secure` as the project variables take precedence over those defined
+in `.gitlab-ci.yml`.
## Unsupported variables
@@ -32,10 +38,10 @@ There are cases where some variables cannot be used in the context of a
`.gitlab-ci.yml` definition (for example under `script`). Read more
about which variables are [not supported](where_variables_can_be_used.md).
-## Predefined variables (Environment variables)
+## Predefined environment variables
Some of the predefined environment variables are available only if a minimum
-version of [GitLab Runner][runner] is used. Consult the table below to find the
+version of [GitLab Runner](https://docs.gitlab.com/runner/) is used. Consult the table below to find the
version of Runner required.
NOTE: **Note:**
@@ -85,6 +91,8 @@ future GitLab releases.**
| **CI_NODE_INDEX** | 11.5 | all | Index of the job in the job set. If the job is not parallelized, this variable is not set. |
| **CI_NODE_TOTAL** | 11.5 | all | Total number of instances of this job running in parallel. If the job is not parallelized, this variable is set to `1`. |
| **CI_API_V4_URL** | 11.7 | all | The GitLab API v4 root URL |
+| **CI_PAGES_DOMAIN** | 11.8 | all | The configured domain that hosts GitLab Pages. |
+| **CI_PAGES_URL** | 11.8 | all | URL to GitLab Pages-built pages. Always belongs to a subdomain of `CI_PAGES_DOMAIN`. |
| **CI_PIPELINE_ID** | 8.10 | all | The unique id of the current pipeline that GitLab CI uses internally |
| **CI_PIPELINE_IID** | 11.0 | all | The unique id of the current pipeline scoped to project |
| **CI_PIPELINE_SOURCE** | 10.0 | all | Indicates how the pipeline was triggered. Possible options are: `push`, `web`, `trigger`, `schedule`, `api`, and `pipeline`. For pipelines created before GitLab 9.5, this will show as `unknown` |
@@ -158,7 +166,7 @@ This feature requires GitLab Runner 0.5.0 or higher and GitLab 7.14 or higher.
GitLab CI allows you to add to `.gitlab-ci.yml` variables that are set in the
build environment. The variables are hence saved in the repository, and they
-are meant to store non-sensitive project configuration, e.g., `RAILS_ENV` or
+are meant to store non-sensitive project configuration. For example, `RAILS_ENV` or
`DATABASE_URL`.
For example, if you set the variable below globally (not inside a job), it will
@@ -206,16 +214,18 @@ GitLab CI allows you to define per-project or per-group variables
that are set in the pipeline environment. The variables are stored out of
the repository (not in `.gitlab-ci.yml`) and are securely passed to GitLab Runner
making them available during a pipeline run. It's the recommended method to
-use for storing things like passwords, SSH keys and credentials.
+use for storing things like passwords, SSH keys, and credentials.
+
+Project-level variables can be added by:
-Project-level variables can be added by going to your project's
-**Settings > CI/CD**, then finding the section called **Variables**.
+1. Navigating to your project's **Settings > CI/CD** page.
+1. Inputing variable keys and values in the **Environment variables** section.
-Likewise, group-level variables can be added by going to your group's
-**Settings > CI/CD**, then finding the section called **Variables**.
-Any variables of [subgroups] will be inherited recursively.
+Group-level variables can be added by:
-![Variables](img/variables.png)
+1. Navigating to your group's **Settings > CI/CD** page.
+1. Inputing variable keys and values in the **Environment variables** section. Any variables of
+ [subgroups](../../user/group/subgroups/index.md) will be inherited recursively.
Once you set them, they will be available for all subsequent pipelines. You can also
[protect your variables](#protected-variables).
@@ -395,6 +405,10 @@ Running on runner-8a2f473d-project-1796893-concurrent-0 via runner-8a2f473d-mach
++ CI_SERVER_VERSION=8.14.3-ee
++ export CI_SERVER_REVISION=82823
++ CI_SERVER_REVISION=82823
+++ export CI_PAGES_DOMAIN=gitlab.io
+++ CI_PAGES_DOMAIN=gitlab.io
+++ export CI_PAGES_URL=https://gitlab-examples.gitlab.io/ci-debug-trace
+++ CI_PAGES_URL=https://gitlab-examples.gitlab.io/ci-debug-trace
++ export CI_PROJECT_ID=17893
++ CI_PROJECT_ID=17893
++ export CI_PROJECT_NAME=ci-debug-trace
@@ -498,6 +512,8 @@ export CI_JOB_TRIGGERED="true"
export CI_JOB_TOKEN="abcde-1234ABCD5678ef"
export CI_PIPELINE_ID="1000"
export CI_PIPELINE_IID="10"
+export CI_PAGES_DOMAIN="gitlab.io"
+export CI_PAGES_URL="https://gitlab-org.gitlab.io/gitlab-ce"
export CI_PROJECT_ID="34"
export CI_PROJECT_DIR="/builds/gitlab-org/gitlab-ce"
export CI_PROJECT_NAME="gitlab-ce"
@@ -613,11 +629,8 @@ Below you can find supported syntax reference:
[envs]: ../environments.md
[protected branches]: ../../user/project/protected_branches.md
[protected tags]: ../../user/project/protected_tags.md
-[runner]: https://docs.gitlab.com/runner/
[shellexecutors]: https://docs.gitlab.com/runner/executors/
[triggered]: ../triggers/README.md
-[triggers]: ../triggers/README.md#pass-job-variables-to-a-trigger
-[subgroups]: ../../user/group/subgroups/index.md
[builds-policies]: ../yaml/README.md#only-and-except-complex
[gitlab-deploy-token]: ../../user/project/deploy_tokens/index.md#gitlab-deploy-token
[registry]: ../../user/project/container_registry.md
diff --git a/doc/ci/variables/img/variables.png b/doc/ci/variables/img/variables.png
deleted file mode 100644
index 0795f7c888f..00000000000
--- a/doc/ci/variables/img/variables.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index fb69d888b94..4c39b14b1d0 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -1520,7 +1520,7 @@ parallel. This value has to be greater than or equal to two (2) and less than or
This creates N instances of the same job that run in parallel. They're named
sequentially from `job_name 1/N` to `job_name N/N`.
-For every job, `CI_NODE_INDEX` and `CI_NODE_TOTAL` [environment variables](../variables/README.html#predefined-variables-environment-variables) are set.
+For every job, `CI_NODE_INDEX` and `CI_NODE_TOTAL` [environment variables](../variables/README.html#predefined-environment-variables) are set.
A simple example:
@@ -1977,7 +1977,7 @@ The YAML-defined variables are also set to all created service containers,
thus allowing to fine tune them.
Except for the user defined variables, there are also the ones [set up by the
-Runner itself](../variables/README.md#predefined-variables-environment-variables).
+Runner itself](../variables/README.md#predefined-environment-variables).
One example would be `CI_COMMIT_REF_NAME` which has the value of
the branch or tag name for which project is built. Apart from the variables
you can set in `.gitlab-ci.yml`, there are also the so called
@@ -2027,8 +2027,8 @@ variables:
```
NOTE: **Note:** `GIT_STRATEGY` is not supported for
-[Kubernetes executor](https://docs.gitlab.com/runner/executors/kubernetes.html),
-but may be in the future. See the [support Git strategy with Kubernetes executor feature proposal](https://gitlab.com/gitlab-org/gitlab-runner/issues/3847)
+[Kubernetes executor](https://docs.gitlab.com/runner/executors/kubernetes.html),
+but may be in the future. See the [support Git strategy with Kubernetes executor feature proposal](https://gitlab.com/gitlab-org/gitlab-runner/issues/3847)
for updates.
### Git submodule strategy
diff --git a/doc/install/installation.md b/doc/install/installation.md
index b3ad1c5a91c..1f65e3415d1 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -6,7 +6,8 @@ Since an installation from source is a lot of work and error prone we strongly r
One reason the Omnibus package is more reliable is its use of Runit to restart any of the GitLab processes in case one crashes.
On heavily used GitLab instances the memory usage of the Sidekiq background worker will grow over time.
-Omnibus packages solve this by [letting the Sidekiq terminate gracefully](http://docs.gitlab.com/ce/operations/sidekiq_memory_killer.html) if it uses too much memory.
+
+Omnibus packages solve this by [letting the Sidekiq terminate gracefully](../administration/operations/sidekiq_memory_killer.md) if it uses too much memory.
After this termination Runit will detect Sidekiq is not running and will start it.
Since installations from source don't have Runit, Sidekiq can't be terminated and its memory usage will grow over time.
@@ -15,19 +16,19 @@ Since installations from source don't have Runit, Sidekiq can't be terminated an
Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md) from the branch (version) of GitLab you would like to install (e.g., `11-7-stable`).
You can select the branch in the version dropdown in the top left corner of GitLab (below the menu bar).
-If the highest number stable branch is unclear please check the [GitLab Blog](https://about.gitlab.com/blog/) for installation guide links by version.
+If the highest number stable branch is unclear, check the [GitLab blog](https://about.gitlab.com/blog/) for installation guide links by version.
## Important Notes
This guide is long because it covers many cases and includes all commands you need, this is [one of the few installation scripts that actually works out of the box](https://twitter.com/robinvdvleuten/status/424163226532986880).
-This installation guide was created for and tested on **Debian/Ubuntu** operating systems. Please read [requirements.md](requirements.md) for hardware and operating system requirements. If you want to install on RHEL/CentOS we recommend using the [Omnibus packages](https://about.gitlab.com/downloads/).
+This installation guide was created for and tested on **Debian/Ubuntu** operating systems. Read [requirements.md](requirements.md) for hardware and operating system requirements. If you want to install on RHEL/CentOS, we recommend using the [Omnibus packages](https://about.gitlab.com/downloads/).
-This is the official installation guide to set up a production server. To set up a **development installation** or for many other installation options please see [the installation section of the readme](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/README.md#installation).
+This is the official installation guide to set up a production server. To set up a **development installation** or for many other installation options, see [the installation section of the README](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/README.md#installation).
-The following steps have been known to work. Please **use caution when you deviate** from this guide. Make sure you don't violate any assumptions GitLab makes about its environment. For example many people run into permission problems because they changed the location of directories or run services as the wrong user.
+The following steps have been known to work. **Use caution when you deviate** from this guide. Make sure you don't violate any assumptions GitLab makes about its environment. For example, many people run into permission problems because they changed the location of directories or run services as the wrong user.
-If you find a bug/error in this guide please **submit a merge request**
+If you find a bug/error in this guide, **submit a merge request**
following the
[contributing guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md).
@@ -35,17 +36,17 @@ following the
The GitLab installation consists of setting up the following components:
-1. Packages / Dependencies
-1. Ruby
-1. Go
-1. Node
-1. System Users
-1. Database
-1. Redis
-1. GitLab
-1. Nginx
+1. [Packages and dependencies](#1-packages-and-dependencies).
+1. [Ruby](#2-ruby).
+1. [Go](#3-go).
+1. [Node](#4-node).
+1. [System users](#5-system-users).
+1. [Database](#6-database).
+1. [Redis](#7-redis).
+1. [GitLab](#8-gitlab).
+1. [Nginx](#9-nginx).
-## 1. Packages / Dependencies
+## 1. Packages and dependencies
`sudo` is not installed on Debian by default. Make sure your system is
up-to-date and install it.
@@ -57,7 +58,8 @@ apt-get upgrade -y
apt-get install sudo -y
```
-**Note:** During this installation some files will need to be edited manually. If you are familiar with vim set it as default editor with the commands below. If you are not familiar with vim please skip this and keep using the default editor.
+NOTE: **Note:**
+During this installation, some files will need to be edited manually. If you are familiar with vim, set it as default editor with the commands below. If you are not familiar with vim, skip this and keep using the default editor.
```sh
# Install vim and set as default editor
@@ -76,15 +78,16 @@ sudo apt-get install -y build-essential zlib1g-dev libyaml-dev libssl-dev libgdb
Ubuntu 14.04 (Trusty Tahr) doesn't have the `libre2-dev` package available, but
you can [install re2 manually](https://github.com/google/re2/wiki/Install).
-If you want to use Kerberos for user authentication, then install libkrb5-dev:
+If you want to use Kerberos for user authentication, install `libkrb5-dev`:
```sh
sudo apt-get install libkrb5-dev
```
-**Note:** If you don't know what Kerberos is, you can assume you don't need it.
+NOTE: **Note:**
+If you don't know what Kerberos is, you can assume you don't need it.
-Make sure you have the right version of Git installed
+Make sure you have the right version of Git installed:
```sh
# Install Git
@@ -117,7 +120,7 @@ sudo make prefix=/usr/local install
# When editing config/gitlab.yml (Step 5), change the git -> bin_path to /usr/local/bin/git
```
-For the [Custom Favicon](../customization/favicon.md) to work, graphicsmagick
+For the [Custom Favicon](../customization/favicon.md) to work, GraphicsMagick
needs to be installed.
```sh
@@ -167,7 +170,7 @@ make
sudo make install
```
-Then install the Bundler Gem:
+Then install the Bundler gem (a version below 2.x):
```sh
sudo gem install bundler --no-document --version '< 2'
@@ -193,9 +196,14 @@ rm go1.10.3.linux-amd64.tar.gz
## 4. Node
-Since GitLab 8.17, GitLab requires the use of Node to compile javascript
-assets, and Yarn to manage javascript dependencies. The current minimum
-requirements for these are node >= v8.10.0 and yarn >= v1.10.0. In many distros
+Since GitLab 8.17, GitLab requires the use of Node to compile JavaScript
+assets, and Yarn to manage JavaScript dependencies. The current minimum
+requirements for these are:
+
+- `node` >= v8.10.0.
+- `yarn` >= v1.10.0.
+
+In many distros,
the versions provided by the official package repositories are out of date, so
we'll need to install through the following commands:
@@ -212,7 +220,7 @@ sudo apt-get install yarn
Visit the official websites for [node](https://nodejs.org/en/download/package-manager/) and [yarn](https://yarnpkg.com/en/docs/install/) if you have any trouble with these steps.
-## 5. System Users
+## 5. System users
Create a `git` user for GitLab:
@@ -222,11 +230,10 @@ sudo adduser --disabled-login --gecos 'GitLab' git
## 6. Database
-We recommend using a PostgreSQL database. For MySQL check the
-[MySQL setup guide](database_mysql.md).
+We recommend using a PostgreSQL database. For MySQL, see the [MySQL setup guide](database_mysql.md).
-> **Note**: because we need to make use of extensions and concurrent index removal,
-you need at least PostgreSQL 9.2.
+NOTE: **Note:**
+Because we need to make use of extensions and concurrent index removal, you need at least PostgreSQL 9.2.
1. Install the database packages:
@@ -286,7 +293,7 @@ you need at least PostgreSQL 9.2.
GitLab requires at least Redis 2.8.
-If you are using Debian 8 or Ubuntu 14.04 and up, then you can simply install
+If you are using Debian 8 or Ubuntu 14.04 and up, you can simply install
Redis 2.8 with:
```sh
@@ -341,7 +348,8 @@ cd /home/git
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 11-7-stable gitlab
```
-**Note:** You can change `11-7-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
+CAUTION: **Caution:**
+You can change `11-7-stable` to `master` if you want the *bleeding edge* version, but never install `master` on a production server!
### Configure It
@@ -419,9 +427,11 @@ sudo -u git -H cp config/resque.yml.example config/resque.yml
sudo -u git -H editor config/resque.yml
```
-**Important Note:** Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup.
+CAUTION: **Caution:**
+Make sure to edit both `gitlab.yml` and `unicorn.rb` to match your setup.
-**Note:** If you want to use HTTPS, see [Using HTTPS](#using-https) for the additional steps.
+NOTE: **Note:**
+If you want to use HTTPS, see [Using HTTPS](#using-https) for the additional steps.
### Configure GitLab DB Settings
@@ -447,7 +457,13 @@ sudo -u git -H chmod o-rwx config/database.yml
### Install Gems
-**Note:** As of bundler 1.5.2, you can invoke `bundle install -jN` (where `N` the number of your processor cores) and enjoy the parallel gems installation with measurable difference in completion time (~60% faster). Check the number of your cores with `nproc`. For more information check this [post](https://robots.thoughtbot.com/parallel-gem-installing-using-bundler). First make sure you have bundler >= 1.5.2 (run `bundle -v`) as it addresses some [issues](https://devcenter.heroku.com/changelog-items/411) that were [fixed](https://github.com/bundler/bundler/pull/2817) in 1.5.2.
+NOTE: **Note:**
+As of Bundler 1.5.2, you can invoke `bundle install -jN` (where `N` is the number of your processor cores) and enjoy parallel gems installation with measurable difference in completion time (~60% faster). Check the number of your cores with `nproc`. For more information, see this [post](https://robots.thoughtbot.com/parallel-gem-installing-using-bundler).
+
+Make sure you have `bundle` (run `bundle -v`):
+
+- `>= 1.5.2`, because some [issues](https://devcenter.heroku.com/changelog-items/411) were [fixed](https://github.com/bundler/bundler/pull/2817) in 1.5.2.
+- `< 2.x`.
```sh
# For PostgreSQL (note, the option says "without ... mysql")
@@ -457,7 +473,8 @@ sudo -u git -H bundle install --deployment --without development test mysql aws
sudo -u git -H bundle install --deployment --without development test postgres aws kerberos
```
-**Note:** If you want to use Kerberos for user authentication, then omit `kerberos` in the `--without` option above.
+NOTE: **Note:**
+If you want to use Kerberos for user authentication, omit `kerberos` in the `--without` option above.
### Install GitLab Shell
@@ -472,11 +489,14 @@ sudo -u git -H bundle exec rake gitlab:shell:install REDIS_URL=unix:/var/run/red
sudo -u git -H editor /home/git/gitlab-shell/config.yml
```
-**Note:** If you want to use HTTPS, see [Using HTTPS](#using-https) for the additional steps.
+NOTE: **Note:**
+If you want to use HTTPS, see [Using HTTPS](#using-https) for the additional steps.
-**Note:** Make sure your hostname can be resolved on the machine itself by either a proper DNS record or an additional line in /etc/hosts ("127.0.0.1 hostname"). This might be necessary for example if you set up GitLab behind a reverse proxy. If the hostname cannot be resolved, the final installation check will fail with "Check GitLab API access: FAILED. code: 401" and pushing commits will be rejected with "[remote rejected] master -> master (hook declined)".
+NOTE: **Note:**
+Make sure your hostname can be resolved on the machine itself by either a proper DNS record or an additional line in `/etc/hosts` ("127.0.0.1 hostname"). This might be necessary, for example, if you set up GitLab behind a reverse proxy. If the hostname cannot be resolved, the final installation check will fail with "Check GitLab API access: FAILED. code: 401" and pushing commits will be rejected with "[remote rejected] master -> master (hook declined)".
-**Note:** GitLab Shell application startup time can be greatly reduced by disabling RubyGems. This can be done in several manners:
+NOTE: **Note:**
+GitLab Shell application startup time can be greatly reduced by disabling RubyGems. This can be done in several ways:
- Export `RUBYOPT=--disable-gems` environment variable for the processes.
- Compile Ruby with `configure --disable-rubygems` to disable RubyGems by default. Not recommended for system-wide Ruby.
@@ -498,9 +518,9 @@ You can specify a different Git repository by providing it as an extra parameter
sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse,https://example.com/gitlab-workhorse.git]" RAILS_ENV=production
```
-### Install gitlab-pages
+### Install GitLab Pages
-GitLab-Pages uses [GNU Make](https://www.gnu.org/software/make/). This step is optional and only needed if you wish to host static sites from within GitLab. The following commands will install GitLab-Pages in `/home/git/gitlab-pages`. For additional setup steps, please consult the [administration guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/administration/pages/source.md) for your version of GitLab as the GitLab Pages daemon can be ran several different ways.
+GitLab Pages uses [GNU Make](https://www.gnu.org/software/make/). This step is optional and only needed if you wish to host static sites from within GitLab. The following commands will install GitLab Pages in `/home/git/gitlab-pages`. For additional setup steps, consult the [administration guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/administration/pages/source.md) for your version of GitLab as the GitLab Pages daemon can be run several different ways.
```sh
cd /home/git
@@ -550,7 +570,8 @@ sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production force=yes
# When done you see 'Administrator account created:'
```
-**Note:** You can set the Administrator/root password and e-mail by supplying them in environmental variables, `GITLAB_ROOT_PASSWORD` and `GITLAB_ROOT_EMAIL` respectively, as seen below. If you don't set the password (and it is set to the default one) please wait with exposing GitLab to the public internet until the installation is done and you've logged into the server the first time. During the first login you'll be forced to change the default password.
+NOTE: **Note:**
+You can set the Administrator/root password and e-mail by supplying them in environmental variables, `GITLAB_ROOT_PASSWORD` and `GITLAB_ROOT_EMAIL` respectively, as seen below. If you don't set the password (and it is set to the default one), wait to expose GitLab to the public internet until the installation is done and you've logged into the server the first time. During the first login, you'll be forced to change the default password.
```sh
sudo -u git -H bundle exec rake gitlab:setup RAILS_ENV=production GITLAB_ROOT_PASSWORD=yourpassword GITLAB_ROOT_EMAIL=youremail
@@ -576,7 +597,7 @@ And if you are installing with a non-default folder or user copy and edit the de
sudo cp lib/support/init.d/gitlab.default.example /etc/default/gitlab
```
-If you installed GitLab in another directory or as a user other than the default you should change these settings in `/etc/default/gitlab`. Do not edit `/etc/init.d/gitlab` as it will be changed on upgrade.
+If you installed GitLab in another directory or as a user other than the default, you should change these settings in `/etc/default/gitlab`. Do not edit `/etc/init.d/gitlab` as it will be changed on upgrade.
Make GitLab start on boot:
@@ -621,7 +642,8 @@ sudo /etc/init.d/gitlab restart
## 9. Nginx
-**Note:** Nginx is the officially supported web server for GitLab. If you cannot or do not want to use Nginx as your web server, have a look at the [GitLab recipes](https://gitlab.com/gitlab-org/gitlab-recipes/).
+NOTE: **Note:**
+Nginx is the officially supported web server for GitLab. If you cannot or do not want to use Nginx as your web server, see [GitLab recipes](https://gitlab.com/gitlab-org/gitlab-recipes/).
### Installation
@@ -638,7 +660,7 @@ sudo cp lib/support/nginx/gitlab /etc/nginx/sites-available/gitlab
sudo ln -s /etc/nginx/sites-available/gitlab /etc/nginx/sites-enabled/gitlab
```
-Make sure to edit the config file to match your setup. Also, ensure that you match your paths to GitLab, especially if installing for a user other than the 'git' user:
+Make sure to edit the config file to match your setup. Also, ensure that you match your paths to GitLab, especially if installing for a user other than the `git` user:
```sh
# Change YOUR_SERVER_FQDN to the fully-qualified
@@ -685,7 +707,7 @@ To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
```
-If all items are green, then congratulations on successfully installing GitLab!
+If all items are green, congratulations on successfully installing GitLab!
NOTE: Supply `SANITIZE=true` environment variable to `gitlab:check` to omit project names from the output of the check command.
@@ -727,11 +749,11 @@ To use GitLab with HTTPS:
1. Update `ssl_certificate` and `ssl_certificate_key`.
1. Review the configuration file and consider applying other security and performance enhancing features.
-Using a self-signed certificate is discouraged but if you must use it follow the normal directions then:
+Using a self-signed certificate is discouraged but if you must use it, follow the normal directions. Then:
1. Generate a self-signed SSL certificate:
- ```
+ ```sh
mkdir -p /etc/nginx/ssl/
cd /etc/nginx/ssl/
sudo openssl req -newkey rsa:2048 -x509 -nodes -days 3560 -out gitlab.crt -keyout gitlab.key
@@ -745,16 +767,16 @@ See the ["Reply by email" documentation](../administration/reply_by_email.md) fo
### LDAP Authentication
-You can configure LDAP authentication in `config/gitlab.yml`. Please restart GitLab after editing this file.
+You can configure LDAP authentication in `config/gitlab.yml`. Restart GitLab after editing this file.
### Using Custom Omniauth Providers
-See the [omniauth integration document](../integration/omniauth.md)
+See the [omniauth integration document](../integration/omniauth.md).
### Build your projects
-GitLab can build your projects. To enable that feature you need GitLab Runners to do that for you.
-Checkout the [GitLab Runner section](https://about.gitlab.com/gitlab-ci/#gitlab-runner) to install it
+GitLab can build your projects. To enable that feature, you need GitLab Runners to do that for you.
+See the [GitLab Runner section](https://about.gitlab.com/product/continuous-integration/#gitlab-runner) to install it.
### Adding your Trusted Proxies
@@ -776,7 +798,7 @@ production:
url: redis://redis.example.tld:6379
```
-If you want to connect the Redis server via socket, then use the "unix:" URL scheme and the path to the Redis socket file in the `config/resque.yml` file.
+If you want to connect the Redis server via socket, use the "unix:" URL scheme and the path to the Redis socket file in the `config/resque.yml` file.
```
# example
@@ -808,7 +830,7 @@ You also need to change the corresponding options (e.g. `ssh_user`, `ssh_host`,
### Additional Markup Styles
-Apart from the always supported markdown style there are other rich text files that GitLab can display. But you might have to install a dependency to do so. Please see the [github-markup gem readme](https://github.com/gitlabhq/markup#markups) for more information.
+Apart from the always supported markdown style, there are other rich text files that GitLab can display. But you might have to install a dependency to do so. See the [github-markup gem README](https://github.com/gitlabhq/markup#markups) for more information.
## Troubleshooting
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index ff798a51eb7..325de50cab0 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -193,7 +193,7 @@ To add a different cluster for each environment:
and Ingress.
1. Make sure you have [configured your DNS](#auto-devops-base-domain) with the
specified Auto DevOps domains.
-1. Navigate to your project's **Settings > CI/CD > Variables** and add
+1. Navigate to your project's **Settings > CI/CD > Environment variables** and add
the `AUTO_DEVOPS_DOMAIN` variables with their respective environment
scope.
@@ -693,7 +693,7 @@ also be customized, and you can easily use a [custom buildpack](#custom-buildpac
| `POSTGRES_ENABLED` | Whether PostgreSQL is enabled; defaults to `"true"`. Set to `false` to disable the automatic deployment of PostgreSQL. |
| `POSTGRES_USER` | The PostgreSQL user; defaults to `user`. Set it to use a custom username. |
| `POSTGRES_PASSWORD` | The PostgreSQL password; defaults to `testing-password`. Set it to use a custom password. |
-| `POSTGRES_DB` | The PostgreSQL database name; defaults to the value of [`$CI_ENVIRONMENT_SLUG`](../../ci/variables/README.md#predefined-variables-environment-variables). Set it to use a custom database name. |
+| `POSTGRES_DB` | The PostgreSQL database name; defaults to the value of [`$CI_ENVIRONMENT_SLUG`](../../ci/variables/README.md#predefined-environment-variables). Set it to use a custom database name. |
| `BUILDPACK_URL` | The buildpack's full URL. It can point to either Git repositories or a tarball URL. For Git repositories, it is possible to point to a specific `ref`, for example `https://github.com/heroku/heroku-buildpack-ruby.git#v142` |
| `SAST_CONFIDENCE_LEVEL` | The minimum confidence level of security issues you want to be reported; `1` for Low, `2` for Medium, `3` for High; defaults to `3`.|
| `DEP_SCAN_DISABLE_REMOTE_CHECKS` | Whether remote Dependency Scanning checks are disabled; defaults to `"false"`. Set to `"true"` to disable checks that send data to GitLab central servers. [Read more about remote checks](https://gitlab.com/gitlab-org/security-products/dependency-scanning#remote-checks).|
diff --git a/doc/topics/autodevops/quick_start_guide.md b/doc/topics/autodevops/quick_start_guide.md
index 6326aadcdf2..9749bd63f2b 100644
--- a/doc/topics/autodevops/quick_start_guide.md
+++ b/doc/topics/autodevops/quick_start_guide.md
@@ -83,7 +83,7 @@ under which this application will be deployed.
![GitLab GKE cluster details](img/guide_gitlab_gke_details.png)
1. Once ready, click **Create Kubernetes cluster**.
-
+
NOTE: **Note:**
Do not select `f1-micro` from the **Machine type** dropdown. `f1-micro` machines cannot support a full GitLab installation.
@@ -216,7 +216,7 @@ deployment and clicking a square will take you to the pod's logs page.
TIP: **Tip:**
There is only one pod hosting the application at the moment, but you can add
more pods by defining the [`REPLICAS` variable](index.md#environment-variables)
-under **Settings > CI/CD > Variables**.
+under **Settings > CI/CD > Environment variables**.
### Working with branches
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 0c358390046..019652b2408 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -159,6 +159,13 @@ Confidential issues can be accessed by reporters and higher permission levels,
as well as by guest users that create a confidential issue. To learn more,
read through the documentation on [permissions and access to confidential issues](project/issues/confidential_issues.md#permissions-and-access-to-confidential-issues).
+### Releases permissions
+
+[Project Releases](project/releases/index.md) can be read by all project
+members (Reporters, Developers, Maintainers, Owners) **except Guests**.
+Releases can be created, updated, or deleted via [Releases APIs](../api/releases/index.md)
+by project Developers, Maintainers, and Owners.
+
## Group members permissions
NOTE: **Note:**
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
index d6ee678443f..a4698fd172a 100644
--- a/doc/user/project/integrations/prometheus.md
+++ b/doc/user/project/integrations/prometheus.md
@@ -89,7 +89,7 @@ to integrate with.
Once configured, GitLab will attempt to retrieve performance metrics for any
environment which has had a successful deployment.
-GitLab will automatically scan the Prometheus server for metrics from known serves like Kubernetes and NGINX, and attempt to identify individual environment. The supported metrics and scan process is detailed in our [Prometheus Metric Library documentation](prometheus_library/index.md).
+GitLab will automatically scan the Prometheus server for metrics from known serves like Kubernetes and NGINX, and attempt to identify individual environment. The supported metrics and scan process is detailed in our [Prometheus Metrics Library documentation](prometheus_library/index.md).
You can view the performance dashboard for an environment by [clicking on the monitoring button](../../../ci/environments.md#monitoring-environments).
@@ -132,7 +132,7 @@ If the "No data found" screen continues to appear, it could be due to:
[prometheus-docker-image]: https://hub.docker.com/r/prom/prometheus/
[prometheus-yml]:samples/prometheus.yml
[gitlab.com-ip-range]: https://gitlab.com/gitlab-com/infrastructure/issues/434
-[ci-environment-slug]: ../../../ci/variables/#predefined-variables-environment-variables
+[ci-environment-slug]: ../../../ci/variables/#predefined-environment-variables
[ce-8935]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8935
[ce-10408]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10408
[promgldocs]: ../../../administration/monitoring/prometheus/index.md
diff --git a/doc/user/project/integrations/prometheus_library/index.md b/doc/user/project/integrations/prometheus_library/index.md
index a79bc2bce06..f47884996d8 100644
--- a/doc/user/project/integrations/prometheus_library/index.md
+++ b/doc/user/project/integrations/prometheus_library/index.md
@@ -29,6 +29,6 @@ In order to isolate and only display relevant metrics for a given environment,
GitLab needs a method to detect which labels are associated. To do that,
GitLab uses the defined queries and fills in the environment specific variables.
Typically this involves looking for the
-[`$CI_ENVIRONMENT_SLUG`](../../../../ci/variables/README.md#predefined-variables-environment-variables),
+[`$CI_ENVIRONMENT_SLUG`](../../../../ci/variables/README.md#predefined-environment-variables),
but may also include other information such as the project's Kubernetes namespace.
Each search query is defined in the [exporter specific documentation](#exporters).
diff --git a/doc/user/project/integrations/prometheus_library/kubernetes.md b/doc/user/project/integrations/prometheus_library/kubernetes.md
index 6b190deaa6c..7a45c87ada0 100644
--- a/doc/user/project/integrations/prometheus_library/kubernetes.md
+++ b/doc/user/project/integrations/prometheus_library/kubernetes.md
@@ -34,4 +34,4 @@ Prometheus needs to be deployed into the cluster and configured properly in orde
In order to isolate and only display relevant CPU and Memory metrics for a given environment, GitLab needs a method to detect which containers it is running. Because these metrics are tracked at the container level, traditional Kubernetes labels are not available.
-Instead, the [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) or [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) name should begin with [CI_ENVIRONMENT_SLUG](../../../../ci/variables/README.md#predefined-variables-environment-variables). It can be followed by a `-` and additional content if desired. For example, a deployment name of `review-homepage-5620p5` would match the `review/homepage` environment.
+Instead, the [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) or [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) name should begin with [CI_ENVIRONMENT_SLUG](../../../../ci/variables/README.md#predefined-environment-variables). It can be followed by a `-` and additional content if desired. For example, a deployment name of `review-homepage-5620p5` would match the `review/homepage` environment.
diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md
index 2c8a590fc45..b4f5a72e148 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -76,10 +76,10 @@ You can [search and filter the results](../../search/index.md#issues-and-merge-r
![Group Issues list view](img/group_merge_requests_list_view.png)
-## Removing the source branch
+## Deleting the source branch
-When creating a merge request, select the "Remove source branch when merge
-request accepted" option and the source branch will be removed when the merge
+When creating a merge request, select the "Delete source branch when merge
+request accepted" option and the source branch will be deleted when the merge
request is merged.
This option is also visible in an existing merge request next to the merge
@@ -87,10 +87,10 @@ request button and can be selected/deselected before merging. It's only visible
to users with [Maintainer permissions](../../permissions.md) in the source project.
If the user viewing the merge request does not have the correct permissions to
-remove the source branch and the source branch is set for removal, the merge
-request widget will show the "Removes source branch" text.
+delete the source branch and the source branch is set for deletion, the merge
+request widget will show the "Deletes source branch" text.
-![Remove source branch status](img/remove_source_branch_status.png)
+![Delete source branch status](img/remove_source_branch_status.png)
## Allow collaboration on merge requests across forks
diff --git a/doc/user/project/new_ci_build_permissions_model.md b/doc/user/project/new_ci_build_permissions_model.md
index 9a53036b4d1..d7a1a69f29d 100644
--- a/doc/user/project/new_ci_build_permissions_model.md
+++ b/doc/user/project/new_ci_build_permissions_model.md
@@ -238,6 +238,6 @@ test:
[triggers]: ../../ci/triggers/README.md
[update-docs]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update
[workhorse]: https://gitlab.com/gitlab-org/gitlab-workhorse
-[jobenv]: ../../ci/variables/README.md#predefined-variables-environment-variables
+[jobenv]: ../../ci/variables/README.md#predefined-environment-variables
[2fa]: ../profile/account/two_factor_authentication.md
[pat]: ../profile/personal_access_tokens.md
diff --git a/lib/gitlab.rb b/lib/gitlab.rb
index b91394f7f58..e073450283b 100644
--- a/lib/gitlab.rb
+++ b/lib/gitlab.rb
@@ -7,6 +7,14 @@ module Gitlab
Pathname.new(File.expand_path('..', __dir__))
end
+ def self.version_info
+ Gitlab::VersionInfo.parse(Gitlab::VERSION)
+ end
+
+ def self.pre_release?
+ VERSION.include?('pre')
+ end
+
def self.config
Settings
end
@@ -27,52 +35,12 @@ module Gitlab
end
end
- def self.version_info
- Gitlab::VersionInfo.parse(Gitlab::VERSION)
- end
-
COM_URL = 'https://gitlab.com'.freeze
APP_DIRS_PATTERN = %r{^/?(app|config|ee|lib|spec|\(\w*\))}
SUBDOMAIN_REGEX = %r{\Ahttps://[a-z0-9]+\.gitlab\.com\z}
VERSION = File.read(root.join("VERSION")).strip.freeze
INSTALLATION_TYPE = File.read(root.join("INSTALLATION_TYPE")).strip.freeze
- def self.pre_release?
- VERSION.include?('pre')
- end
-
- def self.final_release?
- !VERSION.include?('rc') && !pre_release?
- end
-
- def self.minor_release
- "#{version_info.major}.#{version_info.minor}"
- end
-
- def self.prev_minor_release
- "#{version_info.major}.#{version_info.minor - 1}"
- end
-
- def self.prev_major_release
- "#{version_info.major.to_i - 1}"
- end
-
- def self.new_major_release?
- version_info.minor.to_i.zero?
- end
-
- def self.previous_release
- if version_info.minor_version?
- if version_info.patch_version?
- minor_release
- else
- prev_minor_release
- end
- else
- prev_major_release
- end
- end
-
def self.com?
# Check `gl_subdomain?` as well to keep parity with gitlab.com
Gitlab.config.gitlab.url == COM_URL || gl_subdomain?
diff --git a/lib/gitlab/ci/ansi2html.rb b/lib/gitlab/ci/ansi2html.rb
index 974b5ad6877..4dcb3869d4f 100644
--- a/lib/gitlab/ci/ansi2html.rb
+++ b/lib/gitlab/ci/ansi2html.rb
@@ -31,7 +31,7 @@ module Gitlab
end
class Converter
- def on_0(_) reset() end
+ def on_0(_) reset end
def on_1(_) enable(STYLE_SWITCHES[:bold]) end
@@ -177,7 +177,7 @@ module Gitlab
end
end
- close_open_tags()
+ close_open_tags
OpenStruct.new(
html: @out.force_encoding(Encoding.default_external),
@@ -194,7 +194,7 @@ module Gitlab
action = scanner[1]
timestamp = scanner[2]
section = scanner[3]
- line = scanner.matched()[0...-5] # strips \r\033[0K
+ line = scanner.matched[0...-5] # strips \r\033[0K
@out << %{<div class="hidden" data-action="#{action}" data-timestamp="#{timestamp}" data-section="#{section}">#{line}</div>}
end
@@ -209,10 +209,10 @@ module Gitlab
# sequence gets stripped (including stuff like "delete last line")
return unless indicator == '[' && terminator == 'm'
- close_open_tags()
+ close_open_tags
- if commands.empty?()
- reset()
+ if commands.empty?
+ reset
return
end
@@ -222,7 +222,7 @@ module Gitlab
end
def evaluate_command_stack(stack)
- return unless command = stack.shift()
+ return unless command = stack.shift
if self.respond_to?("on_#{command}", true)
self.__send__("on_#{command}", stack) # rubocop:disable GitlabSecurity/PublicSend
@@ -333,8 +333,8 @@ module Gitlab
return unless command_stack.length >= 2
return unless command_stack[0] == "5"
- command_stack.shift() # ignore the "5" command
- color_index = command_stack.shift().to_i
+ command_stack.shift # ignore the "5" command
+ color_index = command_stack.shift.to_i
return unless color_index >= 0
return unless color_index <= 255
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
index 47e3e8cd271..75a5bf142d2 100644
--- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -116,7 +116,7 @@ code_quality:
license_management:
stage: test
- image:
+ image:
name: "registry.gitlab.com/gitlab-org/security-products/license-management:$CI_SERVER_VERSION_MAJOR-$CI_SERVER_VERSION_MINOR-stable"
entrypoint: [""]
allow_failure: true
@@ -612,7 +612,7 @@ rollout 100%:
export APPLICATION_SECRET_NAME=$(application_secret_name "$track")
env | sed -n "s/^K8S_SECRET_\(.*\)$/\1/p" > k8s_prefixed_variables
-
+
kubectl create secret \
-n "$KUBE_NAMESPACE" generic "$APPLICATION_SECRET_NAME" \
--from-env-file k8s_prefixed_variables -o yaml --dry-run |
@@ -689,6 +689,7 @@ rollout 100%:
--set application.database_url="$DATABASE_URL" \
--set application.secretName="$APPLICATION_SECRET_NAME" \
--set application.secretChecksum="$APPLICATION_SECRET_CHECKSUM" \
+ --set service.commonName="le.$AUTO_DEVOPS_DOMAIN" \
--set service.url="$CI_ENVIRONMENT_URL" \
--set service.additionalHosts="$additional_hosts" \
--set replicaCount="$replicas" \
@@ -724,6 +725,7 @@ rollout 100%:
--set application.database_url="$DATABASE_URL" \
--set application.secretName="$APPLICATION_SECRET_NAME" \
--set application.secretChecksum="$APPLICATION_SECRET_CHECKSUM" \
+ --set service.commonName="le.$AUTO_DEVOPS_DOMAIN" \
--set service.url="$CI_ENVIRONMENT_URL" \
--set service.additionalHosts="$additional_hosts" \
--set replicaCount="$replicas" \
diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb
index 0f23b95ba15..e61fb50a303 100644
--- a/lib/gitlab/ci/trace/stream.rb
+++ b/lib/gitlab/ci/trace/stream.rb
@@ -46,7 +46,7 @@ module Gitlab
stream.seek(offset, IO::SEEK_SET)
stream.write(data)
stream.truncate(offset + data.bytesize)
- stream.flush()
+ stream.flush
end
def set(data)
diff --git a/lib/gitlab/github_import/bulk_importing.rb b/lib/gitlab/github_import/bulk_importing.rb
index da2f96b5c4b..147597289cf 100644
--- a/lib/gitlab/github_import/bulk_importing.rb
+++ b/lib/gitlab/github_import/bulk_importing.rb
@@ -15,12 +15,10 @@ module Gitlab
end
# Bulk inserts the given rows into the database.
- def bulk_insert(model, rows, batch_size: 100, pre_hook: nil)
+ def bulk_insert(model, rows, batch_size: 100)
rows.each_slice(batch_size) do |slice|
- pre_hook.call(slice) if pre_hook
Gitlab::Database.bulk_insert(model.table_name, slice)
end
- rows
end
end
end
diff --git a/lib/gitlab/github_import/importer/issue_importer.rb b/lib/gitlab/github_import/importer/issue_importer.rb
index 4226eee85cc..656d46b6a7d 100644
--- a/lib/gitlab/github_import/importer/issue_importer.rb
+++ b/lib/gitlab/github_import/importer/issue_importer.rb
@@ -57,11 +57,7 @@ module Gitlab
updated_at: issue.updated_at
}
- insert_and_return_id(attributes, project.issues).tap do |id|
- # We use .insert_and_return_id which effectively disables all callbacks.
- # Trigger iid logic here to make sure we track internal id values consistently.
- project.issues.find(id).ensure_project_iid!
- end
+ insert_and_return_id(attributes, project.issues)
rescue ActiveRecord::InvalidForeignKey
# It's possible the project has been deleted since scheduling this
# job. In this case we'll just skip creating the issue.
diff --git a/lib/gitlab/github_import/importer/milestones_importer.rb b/lib/gitlab/github_import/importer/milestones_importer.rb
index 8d54b27374c..87cf2c8b598 100644
--- a/lib/gitlab/github_import/importer/milestones_importer.rb
+++ b/lib/gitlab/github_import/importer/milestones_importer.rb
@@ -19,20 +19,10 @@ module Gitlab
# rubocop: enable CodeReuse/ActiveRecord
def execute
- # We insert records in bulk, by-passing any standard model callbacks.
- # The pre_hook here makes sure we track internal ids consistently.
- # Note this has to be called before performing an insert of a batch
- # because we're outside a transaction scope here.
- bulk_insert(Milestone, build_milestones, pre_hook: method(:track_greatest_iid))
+ bulk_insert(Milestone, build_milestones)
build_milestones_cache
end
- def track_greatest_iid(slice)
- greatest_iid = slice.max { |e| e[:iid] }[:iid]
-
- InternalId.track_greatest(nil, { project: project }, :milestones, greatest_iid, ->(_) { project.milestones.maximum(:iid) })
- end
-
def build_milestones
build_database_rows(each_milestone)
end
diff --git a/lib/gitlab/import/merge_request_helpers.rb b/lib/gitlab/import/merge_request_helpers.rb
index 9215067d973..fa3ff6c3f12 100644
--- a/lib/gitlab/import/merge_request_helpers.rb
+++ b/lib/gitlab/import/merge_request_helpers.rb
@@ -24,10 +24,6 @@ module Gitlab
merge_request = project.merge_requests.reload.find(merge_request_id)
- # We use .insert_and_return_id which effectively disables all callbacks.
- # Trigger iid logic here to make sure we track internal id values consistently.
- merge_request.ensure_target_project_iid!
-
[merge_request, false]
end
rescue ActiveRecord::InvalidForeignKey
diff --git a/lib/gitlab/metrics/influx_db.rb b/lib/gitlab/metrics/influx_db.rb
index 1359e973590..0b04340fbb5 100644
--- a/lib/gitlab/metrics/influx_db.rb
+++ b/lib/gitlab/metrics/influx_db.rb
@@ -147,9 +147,7 @@ module Gitlab
#
# See `Gitlab::Metrics::Transaction#add_event` for more details.
def add_event(*args)
- trans = current_transaction
-
- trans&.add_event(*args)
+ current_transaction&.add_event(*args)
end
# Returns the prefix to use for the name of a series.
diff --git a/lib/gitlab/release_blog_post.rb b/lib/gitlab/release_blog_post.rb
deleted file mode 100644
index 639aee61464..00000000000
--- a/lib/gitlab/release_blog_post.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-require 'singleton'
-
-module Gitlab
- class ReleaseBlogPost
- include Singleton
-
- RELEASE_RSS_URL = 'https://about.gitlab.com/releases.xml'
-
- def blog_post_url
- @url ||= fetch_blog_post_url
- end
-
- private
-
- def fetch_blog_post_url
- installed_version = Gitlab.final_release? ? Gitlab.minor_release : Gitlab.previous_release
- response = Gitlab::HTTP.get(RELEASE_RSS_URL, verify: false)
-
- return unless response.code == 200
-
- blog_entry = find_installed_blog_entry(response, installed_version)
- blog_entry['id'] if blog_entry
- end
-
- def find_installed_blog_entry(response, installed_version)
- response['feed']['entry'].find do |entry|
- entry['release'] == installed_version || matches_previous_release_post(entry['release'], installed_version)
- end
- end
-
- def should_match_previous_release_post?
- Gitlab.new_major_release? && !Gitlab.final_release?
- end
-
- def matches_previous_release_post(rss_release_version, installed_version)
- should_match_previous_release_post? && rss_release_version[/\d+/] == installed_version
- end
- end
-end
diff --git a/lib/gitlab/tracing/rails/action_view_subscriber.rb b/lib/gitlab/tracing/rails/action_view_subscriber.rb
new file mode 100644
index 00000000000..88816e1fb32
--- /dev/null
+++ b/lib/gitlab/tracing/rails/action_view_subscriber.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Tracing
+ module Rails
+ class ActionViewSubscriber
+ include RailsCommon
+
+ COMPONENT_TAG = 'ActionView'
+ RENDER_TEMPLATE_NOTIFICATION_TOPIC = 'render_template.action_view'
+ RENDER_COLLECTION_NOTIFICATION_TOPIC = 'render_collection.action_view'
+ RENDER_PARTIAL_NOTIFICATION_TOPIC = 'render_partial.action_view'
+
+ # Instruments Rails ActionView events for opentracing.
+ # Returns a lambda, which, when called will unsubscribe from the notifications
+ def self.instrument
+ subscriber = new
+
+ subscriptions = [
+ ActiveSupport::Notifications.subscribe(RENDER_TEMPLATE_NOTIFICATION_TOPIC) do |_, start, finish, _, payload|
+ subscriber.notify_render_template(start, finish, payload)
+ end,
+ ActiveSupport::Notifications.subscribe(RENDER_COLLECTION_NOTIFICATION_TOPIC) do |_, start, finish, _, payload|
+ subscriber.notify_render_collection(start, finish, payload)
+ end,
+ ActiveSupport::Notifications.subscribe(RENDER_PARTIAL_NOTIFICATION_TOPIC) do |_, start, finish, _, payload|
+ subscriber.notify_render_partial(start, finish, payload)
+ end
+ ]
+
+ create_unsubscriber subscriptions
+ end
+
+ # For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html
+ def notify_render_template(start, finish, payload)
+ generate_span_for_notification("render_template", start, finish, payload, tags_for_render_template(payload))
+ end
+
+ def notify_render_collection(start, finish, payload)
+ generate_span_for_notification("render_collection", start, finish, payload, tags_for_render_collection(payload))
+ end
+
+ def notify_render_partial(start, finish, payload)
+ generate_span_for_notification("render_partial", start, finish, payload, tags_for_render_partial(payload))
+ end
+
+ private
+
+ def tags_for_render_template(payload)
+ {
+ 'component' => COMPONENT_TAG,
+ 'template.id' => payload[:identifier],
+ 'template.layout' => payload[:layout]
+ }
+ end
+
+ def tags_for_render_collection(payload)
+ {
+ 'component' => COMPONENT_TAG,
+ 'template.id' => payload[:identifier],
+ 'template.count' => payload[:count] || 0,
+ 'template.cache.hits' => payload[:cache_hits] || 0
+ }
+ end
+
+ def tags_for_render_partial(payload)
+ {
+ 'component' => COMPONENT_TAG,
+ 'template.id' => payload[:identifier]
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/tracing/rails/active_record_subscriber.rb b/lib/gitlab/tracing/rails/active_record_subscriber.rb
index 214eac47e14..32f5658e57e 100644
--- a/lib/gitlab/tracing/rails/active_record_subscriber.rb
+++ b/lib/gitlab/tracing/rails/active_record_subscriber.rb
@@ -4,24 +4,37 @@ module Gitlab
module Tracing
module Rails
class ActiveRecordSubscriber
- include Gitlab::Tracing::Common
+ include RailsCommon
ACTIVE_RECORD_NOTIFICATION_TOPIC = 'sql.active_record'
- DEFAULT_OPERATION_NAME = "sqlquery"
+ OPERATION_NAME_PREFIX = 'active_record:'
+ DEFAULT_OPERATION_NAME = 'sqlquery'
+ # Instruments Rails ActiveRecord events for opentracing.
+ # Returns a lambda, which, when called will unsubscribe from the notifications
def self.instrument
subscriber = new
- ActiveSupport::Notifications.subscribe(ACTIVE_RECORD_NOTIFICATION_TOPIC) do |_, start, finish, _, payload|
+ subscription = ActiveSupport::Notifications.subscribe(ACTIVE_RECORD_NOTIFICATION_TOPIC) do |_, start, finish, _, payload|
subscriber.notify(start, finish, payload)
end
+
+ create_unsubscriber [subscription]
end
# For more information on the payloads: https://guides.rubyonrails.org/active_support_instrumentation.html
def notify(start, finish, payload)
- operation_name = payload[:name].presence || DEFAULT_OPERATION_NAME
- exception = payload[:exception]
- tags = {
+ generate_span_for_notification(notification_name(payload), start, finish, payload, tags_for_notification(payload))
+ end
+
+ private
+
+ def notification_name(payload)
+ OPERATION_NAME_PREFIX + (payload[:name].presence || DEFAULT_OPERATION_NAME)
+ end
+
+ def tags_for_notification(payload)
+ {
'component' => 'ActiveRecord',
'span.kind' => 'client',
'db.type' => 'sql',
@@ -29,8 +42,6 @@ module Gitlab
'db.cached' => payload[:cached] || false,
'db.statement' => payload[:sql]
}
-
- postnotify_span("active_record:#{operation_name}", start, finish, tags: tags, exception: exception)
end
end
end
diff --git a/lib/gitlab/tracing/rails/rails_common.rb b/lib/gitlab/tracing/rails/rails_common.rb
new file mode 100644
index 00000000000..88e914f62f8
--- /dev/null
+++ b/lib/gitlab/tracing/rails/rails_common.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Tracing
+ module Rails
+ module RailsCommon
+ extend ActiveSupport::Concern
+ include Gitlab::Tracing::Common
+
+ class_methods do
+ def create_unsubscriber(subscriptions)
+ -> { subscriptions.each { |subscriber| ActiveSupport::Notifications.unsubscribe(subscriber) } }
+ end
+ end
+
+ def generate_span_for_notification(operation_name, start, finish, payload, tags)
+ exception = payload[:exception]
+
+ postnotify_span(operation_name, start, finish, tags: tags, exception: exception)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/version_info.rb b/lib/gitlab/version_info.rb
index 142ead12c08..aa6d5310161 100644
--- a/lib/gitlab/version_info.rb
+++ b/lib/gitlab/version_info.rb
@@ -20,14 +20,6 @@ module Gitlab
@patch = patch
end
- def minor_version?
- minor.to_i > 0
- end
-
- def patch_version?
- patch.to_i > 0
- end
-
def <=>(other)
return unless other.is_a? VersionInfo
return unless valid? && other.valid?
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index b910a85b702..5b794ae587b 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -504,6 +504,9 @@ msgstr ""
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
msgstr ""
+msgid "All issues for this milestone are closed. You may close this milestone now."
+msgstr ""
+
msgid "All users"
msgstr ""
@@ -765,6 +768,9 @@ msgstr ""
msgid "Assign milestone"
msgstr ""
+msgid "Assign some issues to this milestone."
+msgstr ""
+
msgid "Assign to"
msgstr ""
@@ -1494,6 +1500,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close milestone"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -2297,6 +2306,9 @@ msgstr ""
msgid "Create merge request and branch"
msgstr ""
+msgid "Create milestone"
+msgstr ""
+
msgid "Create new branch"
msgstr ""
@@ -2758,6 +2770,9 @@ msgstr ""
msgid "Edit Label"
msgstr ""
+msgid "Edit Milestone"
+msgstr ""
+
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
@@ -4587,6 +4602,9 @@ msgstr[1] ""
msgid "New Label"
msgstr ""
+msgid "New Milestone"
+msgstr ""
+
msgid "New Pages Domain"
msgstr ""
@@ -4629,6 +4647,9 @@ msgstr ""
msgid "New merge request"
msgstr ""
+msgid "New milestone"
+msgstr ""
+
msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
@@ -4710,6 +4731,9 @@ msgstr ""
msgid "No messages were logged"
msgstr ""
+msgid "No milestones to show"
+msgstr ""
+
msgid "No other labels with such name or description"
msgstr ""
@@ -4994,6 +5018,9 @@ msgstr ""
msgid "Password"
msgstr ""
+msgid "Past due"
+msgstr ""
+
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
@@ -5902,6 +5929,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen milestone"
+msgstr ""
+
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
@@ -7923,9 +7953,6 @@ msgstr ""
msgid "Web terminal"
msgstr ""
-msgid "What's new?"
-msgstr ""
-
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
@@ -8085,6 +8112,9 @@ msgstr ""
msgid "Write a comment or drag your files here…"
msgstr ""
+msgid "Write milestone description..."
+msgstr ""
+
msgid "Yes"
msgstr ""
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index 419cacdb2af..9f84bdc3828 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -97,7 +97,7 @@ DEPENDENCIES
airborne (~> 0.2.13)
capybara (~> 2.16.1)
capybara-screenshot (~> 1.0.18)
- nokogiri (~> 1.10.0)
+ nokogiri (~> 1.10.1)
pry-byebug (~> 3.5.1)
rake (~> 12.3.0)
rspec (~> 3.7)
diff --git a/qa/Rakefile b/qa/Rakefile
index 8df1cfdc174..9a7b9c6bb35 100644
--- a/qa/Rakefile
+++ b/qa/Rakefile
@@ -1,6 +1,12 @@
require_relative 'qa/tools/revoke_all_personal_access_tokens'
+require_relative 'qa/tools/delete_subgroups'
desc "Revokes all personal access tokens"
task :revoke_personal_access_tokens do
QA::Tools::RevokeAllPersonalAccessTokens.new.run
end
+
+desc "Deletes subgroups within a provided group"
+task :delete_subgroups do
+ QA::Tools::DeleteSubgroups.new.run
+end
diff --git a/qa/qa/page/group/show.rb b/qa/qa/page/group/show.rb
index 0f0ab81a4ef..6dd9ff997a4 100644
--- a/qa/qa/page/group/show.rb
+++ b/qa/qa/page/group/show.rb
@@ -6,7 +6,7 @@ module QA
class Show < Page::Base
include Page::Component::GroupsFilter
- view 'app/views/groups/show.html.haml' do
+ view 'app/views/groups/_home_panel.html.haml' do
element :new_project_or_subgroup_dropdown
element :new_project_or_subgroup_dropdown_toggle
element :new_project_option
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/user_views_raw_diff_patch_requests_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/user_views_raw_diff_patch_requests_spec.rb
index 621cca0f9a5..b862a7bd1ed 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/user_views_raw_diff_patch_requests_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/user_views_raw_diff_patch_requests_spec.rb
@@ -2,7 +2,10 @@
module QA
context 'Create' do
- describe 'Commit data' do
+ # failure reported: https://gitlab.com/gitlab-org/quality/nightly/issues/42
+ # also failing in staging until the fix is picked into the next release:
+ # https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/24533
+ describe 'Commit data', :quarantine do
before(:context) do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_credentials)
diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
index 5147b17d7ab..553550eef8b 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
@@ -3,7 +3,8 @@
require 'pathname'
module QA
- context 'Configure', :orchestrated, :kubernetes do
+ # Transient failure issue: https://gitlab.com/gitlab-org/quality/nightly/issues/68
+ context 'Configure', :orchestrated, :kubernetes, :quarantine do
describe 'Auto DevOps support' do
def login
Runtime::Browser.visit(:gitlab, Page::Main::Login)
diff --git a/qa/qa/support/api.rb b/qa/qa/support/api.rb
index 1107d43161e..8aa7d6812ac 100644
--- a/qa/qa/support/api.rb
+++ b/qa/qa/support/api.rb
@@ -20,6 +20,24 @@ module QA
e.response
end
+ def delete(url)
+ RestClient::Request.execute(
+ method: :delete,
+ url: url,
+ verify_ssl: false)
+ rescue RestClient::ExceptionWithResponse => e
+ e.response
+ end
+
+ def head(url)
+ RestClient::Request.execute(
+ method: :head,
+ url: url,
+ verify_ssl: false)
+ rescue RestClient::ExceptionWithResponse => e
+ e.response
+ end
+
def parse_body(response)
JSON.parse(response.body, symbolize_names: true)
end
diff --git a/qa/qa/tools/delete_subgroups.rb b/qa/qa/tools/delete_subgroups.rb
new file mode 100644
index 00000000000..c5c48e77ade
--- /dev/null
+++ b/qa/qa/tools/delete_subgroups.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require_relative '../../qa'
+
+# This script deletes all subgroups of a group specified by ENV['GROUP_NAME_OR_PATH']
+# Required environment variables: PERSONAL_ACCESS_TOKEN and GITLAB_ADDRESS
+# Optional environment variable: GROUP_NAME_OR_PATH (defaults to 'gitlab-qa-sandbox-group')
+# Run `rake delete_subgroups`
+
+module QA
+ module Tools
+ class DeleteSubgroups
+ include Support::Api
+
+ def initialize
+ raise ArgumentError, "Please provide GITLAB_ADDRESS" unless ENV['GITLAB_ADDRESS']
+ raise ArgumentError, "Please provide PERSONAL_ACCESS_TOKEN" unless ENV['PERSONAL_ACCESS_TOKEN']
+
+ @api_client = Runtime::API::Client.new(ENV['GITLAB_ADDRESS'], personal_access_token: ENV['PERSONAL_ACCESS_TOKEN'])
+ end
+
+ def run
+ STDOUT.puts 'Running...'
+
+ # Fetch group's id
+ group_id = fetch_group_id
+
+ sub_groups_head_response = head Runtime::API::Request.new(@api_client, "/groups/#{group_id}/subgroups", per_page: "100").url
+ total_sub_groups = sub_groups_head_response.headers[:x_total]
+ total_sub_group_pages = sub_groups_head_response.headers[:x_total_pages]
+
+ STDOUT.puts "total_sub_groups: #{total_sub_groups}"
+ STDOUT.puts "total_sub_group_pages: #{total_sub_group_pages}"
+
+ total_sub_group_pages.to_i.times do |page_no|
+ # Fetch all subgroups for the top level group
+ sub_groups_response = get Runtime::API::Request.new(@api_client, "/groups/#{group_id}/subgroups", per_page: "100").url
+
+ sub_group_ids = JSON.parse(sub_groups_response.body).map { |subgroup| subgroup["id"] }
+
+ if sub_group_ids.any?
+ STDOUT.puts "\n==== Current Page: #{page_no + 1} ====\n"
+
+ delete_subgroups(sub_group_ids)
+ end
+ end
+ STDOUT.puts "\nDone"
+ end
+
+ private
+
+ def delete_subgroups(sub_group_ids)
+ sub_group_ids.each do |subgroup_id|
+ delete_response = delete Runtime::API::Request.new(@api_client, "/groups/#{subgroup_id}").url
+ dot_or_f = delete_response.code == 202 ? "\e[32m.\e[0m" : "\e[31mF\e[0m"
+ print dot_or_f
+ end
+ end
+
+ def fetch_group_id
+ group_search_response = get Runtime::API::Request.new(@api_client, "/groups", search: ENV['GROUP_NAME_OR_PATH'] || 'gitlab-qa-sandbox-group').url
+ JSON.parse(group_search_response.body).first["id"]
+ end
+ end
+ end
+end
diff --git a/qa/spec/page/logging_spec.rb b/qa/spec/page/logging_spec.rb
index 2666dd3b03b..f289ee3c2bb 100644
--- a/qa/spec/page/logging_spec.rb
+++ b/qa/spec/page/logging_spec.rb
@@ -6,7 +6,7 @@ require 'logger'
describe QA::Support::Page::Logging do
include Support::StubENV
- let(:page) { double().as_null_object }
+ let(:page) { double.as_null_object }
before do
logger = ::Logger.new $stdout
diff --git a/qa/spec/support/stub_env.rb b/qa/spec/support/stub_env.rb
index 044804cd599..4788e0ab46c 100644
--- a/qa/spec/support/stub_env.rb
+++ b/qa/spec/support/stub_env.rb
@@ -19,7 +19,7 @@ module Support
allow(ENV).to receive(:[]).with(key).and_return(value)
allow(ENV).to receive(:key?).with(key).and_return(true)
allow(ENV).to receive(:fetch).with(key).and_return(value)
- allow(ENV).to receive(:fetch).with(key, anything()) do |_, default_val|
+ allow(ENV).to receive(:fetch).with(key, anything) do |_, default_val|
value || default_val
end
end
diff --git a/scripts/trigger-build b/scripts/trigger-build
index fbf35e7217c..9dbafffddfc 100755
--- a/scripts/trigger-build
+++ b/scripts/trigger-build
@@ -140,6 +140,7 @@ module Trigger
# Back-compatibility until https://gitlab.com/gitlab-org/build/CNG/merge_requests/189 is merged
"GITLAB_#{edition}_VERSION" => ENV['CI_COMMIT_REF_NAME'],
"GITLAB_VERSION" => ENV['CI_COMMIT_REF_NAME'],
+ "GITLAB_TAG" => ENV['CI_COMMIT_TAG'],
"GITLAB_ASSETS_TAG" => ENV['CI_COMMIT_REF_SLUG'],
"#{edition}_PIPELINE" => 'true'
}
diff --git a/spec/controllers/import/bitbucket_server_controller_spec.rb b/spec/controllers/import/bitbucket_server_controller_spec.rb
index bb282db5a41..a125e6ed16d 100644
--- a/spec/controllers/import/bitbucket_server_controller_spec.rb
+++ b/spec/controllers/import/bitbucket_server_controller_spec.rb
@@ -28,9 +28,11 @@ describe Import::BitbucketServerController do
end
describe 'POST create' do
+ let(:project_name) { "my-project_123" }
+
before do
allow(controller).to receive(:bitbucket_client).and_return(client)
- repo = double(name: 'my-project')
+ repo = double(name: project_name)
allow(client).to receive(:repo).with(project_key, repo_slug).and_return(repo)
assign_session_tokens
end
@@ -39,7 +41,7 @@ describe Import::BitbucketServerController do
it 'returns the new project' do
allow(Gitlab::BitbucketServerImport::ProjectCreator)
- .to receive(:new).with(project_key, repo_slug, anything, 'my-project', user.namespace, user, anything)
+ .to receive(:new).with(project_key, repo_slug, anything, project_name, user.namespace, user, anything)
.and_return(double(execute: project))
post :create, params: { project: project_key, repository: repo_slug }, format: :json
@@ -47,6 +49,20 @@ describe Import::BitbucketServerController do
expect(response).to have_gitlab_http_status(200)
end
+ context 'with project key with tildes' do
+ let(:project_key) { '~someuser_123' }
+
+ it 'successfully creates a project' do
+ allow(Gitlab::BitbucketServerImport::ProjectCreator)
+ .to receive(:new).with(project_key, repo_slug, anything, project_name, user.namespace, user, anything)
+ .and_return(double(execute: project))
+
+ post :create, params: { project: project_key, repository: repo_slug, format: :json }
+
+ expect(response).to have_gitlab_http_status(200)
+ end
+ end
+
it 'returns an error when an invalid project key is used' do
post :create, params: { project: 'some&project' }
@@ -69,7 +85,7 @@ describe Import::BitbucketServerController do
it 'returns an error when the project cannot be saved' do
allow(Gitlab::BitbucketServerImport::ProjectCreator)
- .to receive(:new).with(project_key, repo_slug, anything, 'my-project', user.namespace, user, anything)
+ .to receive(:new).with(project_key, repo_slug, anything, project_name, user.namespace, user, anything)
.and_return(double(execute: build(:project)))
post :create, params: { project: project_key, repository: repo_slug }, format: :json
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index 8ea5b4ea09c..c2afff6b732 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -68,7 +68,7 @@ describe Projects::IssuesController do
end
context 'with page param' do
- let(:last_page) { project.issues.page().total_pages }
+ let(:last_page) { project.issues.page.total_pages }
let!(:issue_list) { create_list(:issue, 2, project: project) }
before do
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 01a27f0429b..ca5ff9b1e3b 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -158,7 +158,7 @@ describe Projects::MergeRequestsController do
end
context 'when page param' do
- let(:last_page) { project.merge_requests.page().total_pages }
+ let(:last_page) { project.merge_requests.page.total_pages }
let!(:merge_request) { create(:merge_request_with_diffs, target_project: project, source_project: project) }
it 'redirects to last_page if page number is larger than number of pages' do
diff --git a/spec/controllers/projects/snippets_controller_spec.rb b/spec/controllers/projects/snippets_controller_spec.rb
index 75c9839dd9b..8d9cb2c8ac0 100644
--- a/spec/controllers/projects/snippets_controller_spec.rb
+++ b/spec/controllers/projects/snippets_controller_spec.rb
@@ -12,7 +12,7 @@ describe Projects::SnippetsController do
describe 'GET #index' do
context 'when page param' do
- let(:last_page) { project.snippets.page().total_pages }
+ let(:last_page) { project.snippets.page.total_pages }
let!(:project_snippet) { create(:project_snippet, :public, project: project, author: user) }
it 'redirects to last_page if page number is larger than number of pages' do
diff --git a/spec/features/dashboard/datetime_on_tooltips_spec.rb b/spec/features/dashboard/datetime_on_tooltips_spec.rb
index 0db8093411b..f44bd55ecf6 100644
--- a/spec/features/dashboard/datetime_on_tooltips_spec.rb
+++ b/spec/features/dashboard/datetime_on_tooltips_spec.rb
@@ -15,7 +15,7 @@ describe 'Tooltips on .timeago dates', :js do
sign_in user
visit user_activity_path(user)
- wait_for_requests()
+ wait_for_requests
page.find('.js-timeago').hover
end
@@ -32,7 +32,7 @@ describe 'Tooltips on .timeago dates', :js do
sign_in user
visit user_snippets_path(user)
- wait_for_requests()
+ wait_for_requests
page.find('.js-timeago.snippet-created-ago').hover
end
diff --git a/spec/features/dashboard/help_spec.rb b/spec/features/dashboard/help_spec.rb
index fa12cecc984..467a503a62d 100644
--- a/spec/features/dashboard/help_spec.rb
+++ b/spec/features/dashboard/help_spec.rb
@@ -5,14 +5,6 @@ RSpec.describe 'Dashboard Help' do
sign_in(create(:user))
end
- context 'help dropdown' do
- it 'shows the "What\'s new?" menu item' do
- visit root_dashboard_path
-
- expect(page.find('.header-help .dropdown-menu')).to have_text("What's new?")
- end
- end
-
context 'documentation' do
it 'renders correctly markdown' do
visit help_page_path("administration/raketasks/maintenance")
diff --git a/spec/features/groups/group_settings_spec.rb b/spec/features/groups/group_settings_spec.rb
index 2cdbdcffbc3..378e4d5febc 100644
--- a/spec/features/groups/group_settings_spec.rb
+++ b/spec/features/groups/group_settings_spec.rb
@@ -18,14 +18,14 @@ describe 'Edit group settings' do
update_path(new_group_path)
visit new_group_full_path
expect(current_path).to eq(new_group_full_path)
- expect(find('h1.group-title')).to have_content(group.name)
+ expect(find('h1.home-panel-title')).to have_content(group.name)
end
it 'the old group path redirects to the new path' do
update_path(new_group_path)
visit old_group_full_path
expect(current_path).to eq(new_group_full_path)
- expect(find('h1.group-title')).to have_content(group.name)
+ expect(find('h1.home-panel-title')).to have_content(group.name)
end
context 'with a subgroup' do
@@ -37,14 +37,14 @@ describe 'Edit group settings' do
update_path(new_group_path)
visit new_subgroup_full_path
expect(current_path).to eq(new_subgroup_full_path)
- expect(find('h1.group-title')).to have_content(subgroup.name)
+ expect(find('h1.home-panel-title')).to have_content(subgroup.name)
end
it 'the old subgroup path redirects to the new path' do
update_path(new_group_path)
visit old_subgroup_full_path
expect(current_path).to eq(new_subgroup_full_path)
- expect(find('h1.group-title')).to have_content(subgroup.name)
+ expect(find('h1.home-panel-title')).to have_content(subgroup.name)
end
end
diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb
index f3e573ccbc4..c2f32c76422 100644
--- a/spec/features/groups_spec.rb
+++ b/spec/features/groups_spec.rb
@@ -203,7 +203,7 @@ describe 'Group' do
visit path
- expect(page).to have_css('.group-home-desc > p > strong')
+ expect(page).to have_css('.home-panel-description-markdown > p > strong')
end
it 'passes through html-pipeline' do
@@ -211,7 +211,7 @@ describe 'Group' do
visit path
- expect(page).to have_css('.group-home-desc > p > gl-emoji')
+ expect(page).to have_css('.home-panel-description-markdown > p > gl-emoji')
end
it 'sanitizes unwanted tags' do
@@ -219,7 +219,7 @@ describe 'Group' do
visit path
- expect(page).not_to have_css('.group-home-desc h1')
+ expect(page).not_to have_css('.home-panel-description-markdown h1')
end
it 'permits `rel` attribute on links' do
@@ -227,7 +227,7 @@ describe 'Group' do
visit path
- expect(page).to have_css('.group-home-desc a[rel]')
+ expect(page).to have_css('.home-panel-description-markdown a[rel]')
end
end
diff --git a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
index 00c88c61538..e0b1e286dee 100644
--- a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
@@ -37,7 +37,7 @@ describe 'Dropdown assignee', :js do
end
it 'closes when the search bar is unfocused' do
- find('body').click()
+ find('body').click
expect(page).to have_css(js_dropdown_assignee, visible: false)
end
diff --git a/spec/features/issues/filtered_search/dropdown_author_spec.rb b/spec/features/issues/filtered_search/dropdown_author_spec.rb
index 50d819a6161..bedc61b9eed 100644
--- a/spec/features/issues/filtered_search/dropdown_author_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_author_spec.rb
@@ -45,7 +45,7 @@ describe 'Dropdown author', :js do
end
it 'closes when the search bar is unfocused' do
- find('body').click()
+ find('body').click
expect(page).to have_css(js_dropdown_author, visible: false)
end
diff --git a/spec/features/issues/filtered_search/dropdown_emoji_spec.rb b/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
index 2ba0fc08c2c..f36d4e8f23f 100644
--- a/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
@@ -64,7 +64,7 @@ describe 'Dropdown emoji', :js do
end
it 'closes when the search bar is unfocused' do
- find('body').click()
+ find('body').click
expect(page).to have_css(js_dropdown_emoji, visible: false)
end
diff --git a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
index e651e83ada3..b330eafe1d1 100644
--- a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
@@ -44,7 +44,7 @@ describe 'Dropdown milestone', :js do
end
it 'closes when the search bar is unfocused' do
- find('body').click()
+ find('body').click
expect(page).to have_css(js_dropdown_milestone, visible: false)
end
diff --git a/spec/features/projects/deploy_keys_spec.rb b/spec/features/projects/deploy_keys_spec.rb
index e12532e97fa..1fa9babaff5 100644
--- a/spec/features/projects/deploy_keys_spec.rb
+++ b/spec/features/projects/deploy_keys_spec.rb
@@ -20,7 +20,7 @@ describe 'Project deploy keys', :js do
page.within(find('.deploy-keys')) do
expect(page).to have_selector('.deploy-key', count: 1)
- accept_confirm { find('.ic-remove').click() }
+ accept_confirm { find('.ic-remove').click }
wait_for_requests
diff --git a/spec/features/projects/files/undo_template_spec.rb b/spec/features/projects/files/undo_template_spec.rb
index 5de0bc009fb..fa785ed10ef 100644
--- a/spec/features/projects/files/undo_template_spec.rb
+++ b/spec/features/projects/files/undo_template_spec.rb
@@ -50,7 +50,7 @@ end
def check_content_reverted(template_content)
find('.template-selectors-undo-menu .btn-info').click
expect(page).not_to have_content(template_content)
- expect(find('.template-type-selector .dropdown-toggle-text')).to have_content()
+ expect(find('.template-type-selector .dropdown-toggle-text')).to have_content
end
def select_file_template(template_selector_selector, template_name)
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index 8230396a4cc..24830b2bd3e 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -103,7 +103,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
it 'shows commit`s data', :js do
- requests = inspect_requests() do
+ requests = inspect_requests do
visit project_job_path(project, job)
end
@@ -214,7 +214,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
it 'downloads the zip file when user clicks the download button' do
- requests = inspect_requests() do
+ requests = inspect_requests do
click_link 'Download'
end
@@ -824,7 +824,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
before do
job.run!
visit project_job_path(project, job)
- find('.js-cancel-job').click()
+ find('.js-cancel-job').click
end
it 'loads the page and shows all needed controls' do
@@ -884,7 +884,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
it do
- requests = inspect_requests() do
+ requests = inspect_requests do
visit download_project_job_artifacts_path(project, job2)
end
diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb
index 1982136b89d..1259ad45791 100644
--- a/spec/features/projects/settings/repository_settings_spec.rb
+++ b/spec/features/projects/settings/repository_settings_spec.rb
@@ -54,7 +54,7 @@ describe 'Projects > Settings > Repository settings' do
project.deploy_keys << private_deploy_key
visit project_settings_repository_path(project)
- find('.deploy-key', text: private_deploy_key.title).find('.ic-pencil').click()
+ find('.deploy-key', text: private_deploy_key.title).find('.ic-pencil').click
fill_in 'deploy_key_title', with: 'updated_deploy_key'
check 'deploy_key_deploy_keys_projects_attributes_0_can_push'
@@ -71,14 +71,14 @@ describe 'Projects > Settings > Repository settings' do
visit project_settings_repository_path(project)
- find('.js-deployKeys-tab-available_project_keys').click()
+ find('.js-deployKeys-tab-available_project_keys').click
- find('.deploy-key', text: private_deploy_key.title).find('.ic-pencil').click()
+ find('.deploy-key', text: private_deploy_key.title).find('.ic-pencil').click
fill_in 'deploy_key_title', with: 'updated_deploy_key'
click_button 'Save changes'
- find('.js-deployKeys-tab-available_project_keys').click()
+ find('.js-deployKeys-tab-available_project_keys').click
expect(page).to have_content('updated_deploy_key')
end
@@ -87,7 +87,7 @@ describe 'Projects > Settings > Repository settings' do
project.deploy_keys << private_deploy_key
visit project_settings_repository_path(project)
- accept_confirm { find('.deploy-key', text: private_deploy_key.title).find('.ic-remove').click() }
+ accept_confirm { find('.deploy-key', text: private_deploy_key.title).find('.ic-remove').click }
expect(page).not_to have_content(private_deploy_key.title)
end
diff --git a/spec/features/projects/snippets/user_comments_on_snippet_spec.rb b/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
index d82e350e0f7..9c1ef78b0ca 100644
--- a/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
+++ b/spec/features/projects/snippets/user_comments_on_snippet_spec.rb
@@ -31,7 +31,7 @@ describe 'Projects > Snippets > User comments on a snippet', :js do
end
it 'should have zen mode' do
- find('.js-zen-enter').click()
+ find('.js-zen-enter').click
expect(page).to have_selector('.fullscreen')
end
end
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index 4cb49ab02e2..f7efc3f325c 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -55,30 +55,30 @@ describe 'Project' do
it 'parses Markdown' do
project.update_attribute(:description, 'This is **my** project')
visit path
- expect(page).to have_css('.project-description > .project-description-markdown > p > strong')
+ expect(page).to have_css('.home-panel-description > .home-panel-description-markdown > p > strong')
end
it 'passes through html-pipeline' do
project.update_attribute(:description, 'This project is the :poop:')
visit path
- expect(page).to have_css('.project-description > .project-description-markdown > p > gl-emoji')
+ expect(page).to have_css('.home-panel-description > .home-panel-description-markdown > p > gl-emoji')
end
it 'sanitizes unwanted tags' do
project.update_attribute(:description, "```\ncode\n```")
visit path
- expect(page).not_to have_css('.project-description code')
+ expect(page).not_to have_css('.home-panel-description code')
end
it 'permits `rel` attribute on links' do
project.update_attribute(:description, 'https://google.com/')
visit path
- expect(page).to have_css('.project-description a[rel]')
+ expect(page).to have_css('.home-panel-description a[rel]')
end
context 'read more', :js do
let(:read_more_selector) { '.read-more-container' }
- let(:read_more_trigger_selector) { '.project-home-desc .js-read-more-trigger' }
+ let(:read_more_trigger_selector) { '.home-panel-home-desc .js-read-more-trigger' }
it 'does not display "read more" link on desktop breakpoint' do
project.update_attribute(:description, 'This is **my** project')
@@ -94,7 +94,7 @@ describe 'Project' do
find(read_more_trigger_selector).click
- expect(page).to have_css('.project-description .is-expanded')
+ expect(page).to have_css('.home-panel-description .is-expanded')
end
end
end
@@ -111,14 +111,14 @@ describe 'Project' do
it 'shows project topics' do
project.update_attribute(:tag_list, 'topic1')
visit path
- expect(page).to have_css('.project-topic-list')
+ expect(page).to have_css('.home-panel-topic-list')
expect(page).to have_content('topic1')
end
it 'shows up to 3 project tags' do
project.update_attribute(:tag_list, 'topic1, topic2, topic3, topic4')
visit path
- expect(page).to have_css('.project-topic-list')
+ expect(page).to have_css('.home-panel-topic-list')
expect(page).to have_content('topic1, topic2, topic3 + 1 more')
end
end
diff --git a/spec/fixtures/api/schemas/cluster_status.json b/spec/fixtures/api/schemas/cluster_status.json
index 3d9e0628f63..138a6c5ed6b 100644
--- a/spec/fixtures/api/schemas/cluster_status.json
+++ b/spec/fixtures/api/schemas/cluster_status.json
@@ -30,6 +30,7 @@
]
}
},
+ "version": { "type": "string" },
"status_reason": { "type": ["string", "null"] },
"external_ip": { "type": ["string", "null"] },
"hostname": { "type": ["string", "null"] },
diff --git a/spec/helpers/import_helper_spec.rb b/spec/helpers/import_helper_spec.rb
index cb0ea4e26ba..af4931e3370 100644
--- a/spec/helpers/import_helper_spec.rb
+++ b/spec/helpers/import_helper_spec.rb
@@ -2,6 +2,10 @@ require 'rails_helper'
describe ImportHelper do
describe '#sanitize_project_name' do
+ it 'removes leading tildes' do
+ expect(helper.sanitize_project_name('~~root')).to eq('root')
+ end
+
it 'removes whitespace' do
expect(helper.sanitize_project_name('my test repo')).to eq('my-test-repo')
end
diff --git a/spec/helpers/submodule_helper_spec.rb b/spec/helpers/submodule_helper_spec.rb
index 8662cadc7a0..ea48c69e0ae 100644
--- a/spec/helpers/submodule_helper_spec.rb
+++ b/spec/helpers/submodule_helper_spec.rb
@@ -6,7 +6,7 @@ describe SubmoduleHelper do
describe 'submodule links' do
let(:submodule_item) { double(id: 'hash', path: 'rack') }
let(:config) { Gitlab.config.gitlab }
- let(:repo) { double() }
+ let(:repo) { double }
before do
self.instance_variable_set(:@repository, repo)
diff --git a/spec/javascripts/clusters/clusters_bundle_spec.js b/spec/javascripts/clusters/clusters_bundle_spec.js
index 880b469284b..7928feeadfa 100644
--- a/spec/javascripts/clusters/clusters_bundle_spec.js
+++ b/spec/javascripts/clusters/clusters_bundle_spec.js
@@ -1,10 +1,5 @@
import Clusters from '~/clusters/clusters_bundle';
-import {
- REQUEST_LOADING,
- REQUEST_SUCCESS,
- REQUEST_FAILURE,
- APPLICATION_STATUS,
-} from '~/clusters/constants';
+import { REQUEST_SUBMITTED, REQUEST_FAILURE, APPLICATION_STATUS } from '~/clusters/constants';
import getSetTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
describe('Clusters', () => {
@@ -196,67 +191,43 @@ describe('Clusters', () => {
});
describe('installApplication', () => {
- it('tries to install helm', done => {
+ it('tries to install helm', () => {
spyOn(cluster.service, 'installApplication').and.returnValue(Promise.resolve());
expect(cluster.store.state.applications.helm.requestStatus).toEqual(null);
cluster.installApplication({ id: 'helm' });
- expect(cluster.store.state.applications.helm.requestStatus).toEqual(REQUEST_LOADING);
+ expect(cluster.store.state.applications.helm.requestStatus).toEqual(REQUEST_SUBMITTED);
expect(cluster.store.state.applications.helm.requestReason).toEqual(null);
expect(cluster.service.installApplication).toHaveBeenCalledWith('helm', undefined);
-
- getSetTimeoutPromise()
- .then(() => {
- expect(cluster.store.state.applications.helm.requestStatus).toEqual(REQUEST_SUCCESS);
- expect(cluster.store.state.applications.helm.requestReason).toEqual(null);
- })
- .then(done)
- .catch(done.fail);
});
- it('tries to install ingress', done => {
+ it('tries to install ingress', () => {
spyOn(cluster.service, 'installApplication').and.returnValue(Promise.resolve());
expect(cluster.store.state.applications.ingress.requestStatus).toEqual(null);
cluster.installApplication({ id: 'ingress' });
- expect(cluster.store.state.applications.ingress.requestStatus).toEqual(REQUEST_LOADING);
+ expect(cluster.store.state.applications.ingress.requestStatus).toEqual(REQUEST_SUBMITTED);
expect(cluster.store.state.applications.ingress.requestReason).toEqual(null);
expect(cluster.service.installApplication).toHaveBeenCalledWith('ingress', undefined);
-
- getSetTimeoutPromise()
- .then(() => {
- expect(cluster.store.state.applications.ingress.requestStatus).toEqual(REQUEST_SUCCESS);
- expect(cluster.store.state.applications.ingress.requestReason).toEqual(null);
- })
- .then(done)
- .catch(done.fail);
});
- it('tries to install runner', done => {
+ it('tries to install runner', () => {
spyOn(cluster.service, 'installApplication').and.returnValue(Promise.resolve());
expect(cluster.store.state.applications.runner.requestStatus).toEqual(null);
cluster.installApplication({ id: 'runner' });
- expect(cluster.store.state.applications.runner.requestStatus).toEqual(REQUEST_LOADING);
+ expect(cluster.store.state.applications.runner.requestStatus).toEqual(REQUEST_SUBMITTED);
expect(cluster.store.state.applications.runner.requestReason).toEqual(null);
expect(cluster.service.installApplication).toHaveBeenCalledWith('runner', undefined);
-
- getSetTimeoutPromise()
- .then(() => {
- expect(cluster.store.state.applications.runner.requestStatus).toEqual(REQUEST_SUCCESS);
- expect(cluster.store.state.applications.runner.requestReason).toEqual(null);
- })
- .then(done)
- .catch(done.fail);
});
- it('tries to install jupyter', done => {
+ it('tries to install jupyter', () => {
spyOn(cluster.service, 'installApplication').and.returnValue(Promise.resolve());
expect(cluster.store.state.applications.jupyter.requestStatus).toEqual(null);
@@ -265,19 +236,11 @@ describe('Clusters', () => {
params: { hostname: cluster.store.state.applications.jupyter.hostname },
});
- expect(cluster.store.state.applications.jupyter.requestStatus).toEqual(REQUEST_LOADING);
+ expect(cluster.store.state.applications.jupyter.requestStatus).toEqual(REQUEST_SUBMITTED);
expect(cluster.store.state.applications.jupyter.requestReason).toEqual(null);
expect(cluster.service.installApplication).toHaveBeenCalledWith('jupyter', {
hostname: cluster.store.state.applications.jupyter.hostname,
});
-
- getSetTimeoutPromise()
- .then(() => {
- expect(cluster.store.state.applications.jupyter.requestStatus).toEqual(REQUEST_SUCCESS);
- expect(cluster.store.state.applications.jupyter.requestReason).toEqual(null);
- })
- .then(done)
- .catch(done.fail);
});
it('sets error request status when the request fails', done => {
@@ -289,7 +252,7 @@ describe('Clusters', () => {
cluster.installApplication({ id: 'helm' });
- expect(cluster.store.state.applications.helm.requestStatus).toEqual(REQUEST_LOADING);
+ expect(cluster.store.state.applications.helm.requestStatus).toEqual(REQUEST_SUBMITTED);
expect(cluster.store.state.applications.helm.requestReason).toEqual(null);
expect(cluster.service.installApplication).toHaveBeenCalled();
diff --git a/spec/javascripts/clusters/components/application_row_spec.js b/spec/javascripts/clusters/components/application_row_spec.js
index 45d56514930..d1f4a1cebb4 100644
--- a/spec/javascripts/clusters/components/application_row_spec.js
+++ b/spec/javascripts/clusters/components/application_row_spec.js
@@ -1,11 +1,6 @@
import Vue from 'vue';
import eventHub from '~/clusters/event_hub';
-import {
- APPLICATION_STATUS,
- REQUEST_LOADING,
- REQUEST_SUCCESS,
- REQUEST_FAILURE,
-} from '~/clusters/constants';
+import { APPLICATION_STATUS, REQUEST_SUBMITTED, REQUEST_FAILURE } from '~/clusters/constants';
import applicationRow from '~/clusters/components/application_row.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { DEFAULT_APPLICATION_STATE } from '../services/mock_data';
@@ -57,6 +52,12 @@ describe('Application Row', () => {
expect(vm.installButtonLabel).toBeUndefined();
});
+ it('has install button', () => {
+ const installationBtn = vm.$el.querySelector('.js-cluster-application-install-button');
+
+ expect(installationBtn).not.toBe(null);
+ });
+
it('has disabled "Install" when APPLICATION_STATUS.NOT_INSTALLABLE', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
@@ -101,6 +102,18 @@ describe('Application Row', () => {
expect(vm.installButtonDisabled).toEqual(true);
});
+ it('has loading "Installing" when REQUEST_SUBMITTED', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.INSTALLABLE,
+ requestStatus: REQUEST_SUBMITTED,
+ });
+
+ expect(vm.installButtonLabel).toEqual('Installing');
+ expect(vm.installButtonLoading).toEqual(true);
+ expect(vm.installButtonDisabled).toEqual(true);
+ });
+
it('has disabled "Installed" when APPLICATION_STATUS.INSTALLED', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
@@ -134,30 +147,6 @@ describe('Application Row', () => {
expect(vm.installButtonDisabled).toEqual(false);
});
- it('has loading "Install" when REQUEST_LOADING', () => {
- vm = mountComponent(ApplicationRow, {
- ...DEFAULT_APPLICATION_STATE,
- status: APPLICATION_STATUS.INSTALLABLE,
- requestStatus: REQUEST_LOADING,
- });
-
- expect(vm.installButtonLabel).toEqual('Install');
- expect(vm.installButtonLoading).toEqual(true);
- expect(vm.installButtonDisabled).toEqual(true);
- });
-
- it('has disabled "Install" when REQUEST_SUCCESS', () => {
- vm = mountComponent(ApplicationRow, {
- ...DEFAULT_APPLICATION_STATE,
- status: APPLICATION_STATUS.INSTALLABLE,
- requestStatus: REQUEST_SUCCESS,
- });
-
- expect(vm.installButtonLabel).toEqual('Install');
- expect(vm.installButtonLoading).toEqual(false);
- expect(vm.installButtonDisabled).toEqual(true);
- });
-
it('has enabled "Install" when REQUEST_FAILURE (so you can try installing again)', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
diff --git a/spec/javascripts/notes/components/noteable_discussion_spec.js b/spec/javascripts/notes/components/noteable_discussion_spec.js
index 3aff2dd0641..c4b7eb17393 100644
--- a/spec/javascripts/notes/components/noteable_discussion_spec.js
+++ b/spec/javascripts/notes/components/noteable_discussion_spec.js
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
import createStore from '~/notes/stores';
import noteableDiscussion from '~/notes/components/noteable_discussion.vue';
import '~/behaviors/markdown/render_gfm';
@@ -8,9 +8,8 @@ import mockDiffFile from '../../diffs/mock_data/diff_file';
const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json';
describe('noteable_discussion component', () => {
- const Component = Vue.extend(noteableDiscussion);
let store;
- let vm;
+ let wrapper;
preloadFixtures(discussionWithTwoUnresolvedNotes);
@@ -20,54 +19,62 @@ describe('noteable_discussion component', () => {
store.dispatch('setNoteableData', noteableDataMock);
store.dispatch('setNotesData', notesDataMock);
- vm = new Component({
+ const localVue = createLocalVue();
+ wrapper = shallowMount(noteableDiscussion, {
store,
propsData: { discussion: discussionMock },
- }).$mount();
+ localVue,
+ sync: false,
+ });
});
afterEach(() => {
- vm.$destroy();
+ wrapper.destroy();
});
it('should render user avatar', () => {
- expect(vm.$el.querySelector('.user-avatar-link')).not.toBeNull();
+ expect(wrapper.find('.user-avatar-link').exists()).toBe(true);
});
it('should not render discussion header for non diff discussions', () => {
- expect(vm.$el.querySelector('.discussion-header')).toBeNull();
+ expect(wrapper.find('.discussion-header').exists()).toBe(false);
});
- it('should render discussion header', () => {
+ it('should render discussion header', done => {
const discussion = { ...discussionMock };
discussion.diff_file = mockDiffFile;
discussion.diff_discussion = true;
- vm.$destroy();
- vm = new Component({
- store,
- propsData: { discussion },
- }).$mount();
+ wrapper.setProps({ discussion });
- expect(vm.$el.querySelector('.discussion-header')).not.toBeNull();
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ expect(wrapper.find('.discussion-header').exists()).toBe(true);
+ })
+ .then(done)
+ .catch(done.fail);
});
describe('actions', () => {
it('should render reply button', () => {
- expect(vm.$el.querySelector('.js-vue-discussion-reply').textContent.trim()).toEqual(
- 'Reply...',
- );
+ expect(
+ wrapper
+ .find('.js-vue-discussion-reply')
+ .text()
+ .trim(),
+ ).toEqual('Reply...');
});
it('should toggle reply form', done => {
- vm.$el.querySelector('.js-vue-discussion-reply').click();
+ wrapper.find('.js-vue-discussion-reply').trigger('click');
- Vue.nextTick(() => {
- expect(vm.isReplying).toEqual(true);
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.vm.isReplying).toEqual(true);
// There is a watcher for `isReplying` which will init autosave in the next tick
- Vue.nextTick(() => {
- expect(vm.$refs.noteForm).not.toBeNull();
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.vm.$refs.noteForm).not.toBeNull();
done();
});
});
@@ -75,8 +82,8 @@ describe('noteable_discussion component', () => {
it('does not render jump to discussion button', () => {
expect(
- vm.$el.querySelector('*[data-original-title="Jump to next unresolved discussion"]'),
- ).toBeNull();
+ wrapper.find('*[data-original-title="Jump to next unresolved discussion"]').exists(),
+ ).toBe(false);
});
});
@@ -87,12 +94,13 @@ describe('noteable_discussion component', () => {
discussion2.resolved = false;
discussion2.active = true;
discussion2.id = 'next'; // prepare this for being identified as next one (to be jumped to)
- vm.$store.dispatch('setInitialNotes', [discussionMock, discussion2]);
+ store.dispatch('setInitialNotes', [discussionMock, discussion2]);
window.mrTabs.currentAction = 'show';
- Vue.nextTick()
+ wrapper.vm
+ .$nextTick()
.then(() => {
- spyOn(vm, 'expandDiscussion').and.stub();
+ spyOn(wrapper.vm, 'expandDiscussion').and.stub();
const nextDiscussionId = discussion2.id;
@@ -100,9 +108,11 @@ describe('noteable_discussion component', () => {
<div class="discussion" data-discussion-id="${nextDiscussionId}"></div>
`);
- vm.jumpToNextDiscussion();
+ wrapper.vm.jumpToNextDiscussion();
- expect(vm.expandDiscussion).toHaveBeenCalledWith({ discussionId: nextDiscussionId });
+ expect(wrapper.vm.expandDiscussion).toHaveBeenCalledWith({
+ discussionId: nextDiscussionId,
+ });
})
.then(done)
.catch(done.fail);
@@ -117,7 +127,7 @@ describe('noteable_discussion component', () => {
notes: [{ body: 'hello world!' }],
};
- const note = vm.componentData(data);
+ const note = wrapper.vm.componentData(data);
expect(note).toEqual(data.notes[0]);
});
@@ -127,7 +137,7 @@ describe('noteable_discussion component', () => {
notes: [{ id: 12 }],
};
- const note = vm.componentData(data);
+ const note = wrapper.vm.componentData(data);
expect(note).toEqual(data);
});
@@ -138,46 +148,48 @@ describe('noteable_discussion component', () => {
const truncatedCommitId = commitId.substr(0, 8);
let commitElement;
- beforeEach(() => {
- vm.$destroy();
-
+ beforeEach(done => {
store.state.diffs = {
projectPath: 'something',
};
- vm = new Component({
- propsData: {
- discussion: {
- ...discussionMock,
- for_commit: true,
- commit_id: commitId,
- diff_discussion: true,
- diff_file: {
- ...mockDiffFile,
- },
+ wrapper.setProps({
+ discussion: {
+ ...discussionMock,
+ for_commit: true,
+ commit_id: commitId,
+ diff_discussion: true,
+ diff_file: {
+ ...mockDiffFile,
},
- renderDiffFile: true,
},
- store,
- }).$mount();
+ renderDiffFile: true,
+ });
- commitElement = vm.$el.querySelector('.commit-sha');
+ wrapper.vm
+ .$nextTick()
+ .then(() => {
+ commitElement = wrapper.find('.commit-sha');
+ })
+ .then(done)
+ .catch(done.fail);
});
describe('for commit discussions', () => {
it('should display a monospace started a discussion on commit', () => {
- expect(vm.$el).toContainText(`started a discussion on commit ${truncatedCommitId}`);
- expect(commitElement).not.toBe(null);
- expect(commitElement).toHaveText(truncatedCommitId);
+ expect(wrapper.text()).toContain(`started a discussion on commit ${truncatedCommitId}`);
+ expect(commitElement.exists()).toBe(true);
+ expect(commitElement.text()).toContain(truncatedCommitId);
});
});
describe('for diff discussion with a commit id', () => {
it('should display started discussion on commit header', done => {
- vm.discussion.for_commit = false;
+ wrapper.vm.discussion.for_commit = false;
+
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.text()).toContain(`started a discussion on commit ${truncatedCommitId}`);
- vm.$nextTick(() => {
- expect(vm.$el).toContainText(`started a discussion on commit ${truncatedCommitId}`);
expect(commitElement).not.toBe(null);
done();
@@ -185,11 +197,11 @@ describe('noteable_discussion component', () => {
});
it('should display outdated change on commit header', done => {
- vm.discussion.for_commit = false;
- vm.discussion.active = false;
+ wrapper.vm.discussion.for_commit = false;
+ wrapper.vm.discussion.active = false;
- vm.$nextTick(() => {
- expect(vm.$el).toContainText(
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.text()).toContain(
`started a discussion on an outdated change in commit ${truncatedCommitId}`,
);
@@ -202,27 +214,27 @@ describe('noteable_discussion component', () => {
describe('for diff discussions without a commit id', () => {
it('should show started a discussion on the diff text', done => {
- Object.assign(vm.discussion, {
+ Object.assign(wrapper.vm.discussion, {
for_commit: false,
commit_id: null,
});
- vm.$nextTick(() => {
- expect(vm.$el).toContainText('started a discussion on the diff');
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.text()).toContain('started a discussion on the diff');
done();
});
});
it('should show discussion on older version text', done => {
- Object.assign(vm.discussion, {
+ Object.assign(wrapper.vm.discussion, {
for_commit: false,
commit_id: null,
active: false,
});
- vm.$nextTick(() => {
- expect(vm.$el).toContainText('started a discussion on an old version of the diff');
+ wrapper.vm.$nextTick(() => {
+ expect(wrapper.text()).toContain('started a discussion on an old version of the diff');
done();
});
diff --git a/spec/lib/gitlab/data_builder/pipeline_spec.rb b/spec/lib/gitlab/data_builder/pipeline_spec.rb
index 98f1696badb..9ef987a0826 100644
--- a/spec/lib/gitlab/data_builder/pipeline_spec.rb
+++ b/spec/lib/gitlab/data_builder/pipeline_spec.rb
@@ -37,7 +37,7 @@ describe Gitlab::DataBuilder::Pipeline do
context 'pipeline without variables' do
it 'has empty variables hash' do
expect(attributes[:variables]).to be_a(Array)
- expect(attributes[:variables]).to be_empty()
+ expect(attributes[:variables]).to be_empty
end
end
diff --git a/spec/lib/gitlab/github_import/bulk_importing_spec.rb b/spec/lib/gitlab/github_import/bulk_importing_spec.rb
index 861710f7e9b..91229d9c7d4 100644
--- a/spec/lib/gitlab/github_import/bulk_importing_spec.rb
+++ b/spec/lib/gitlab/github_import/bulk_importing_spec.rb
@@ -58,17 +58,5 @@ describe Gitlab::GithubImport::BulkImporting do
importer.bulk_insert(model, rows, batch_size: 5)
end
-
- it 'calls pre_hook for each slice if given' do
- rows = [{ title: 'Foo' }] * 10
- model = double(:model, table_name: 'kittens')
- pre_hook = double('pre_hook', call: nil)
- allow(Gitlab::Database).to receive(:bulk_insert)
-
- expect(pre_hook).to receive(:call).with(rows[0..4])
- expect(pre_hook).to receive(:call).with(rows[5..9])
-
- importer.bulk_insert(model, rows, batch_size: 5, pre_hook: pre_hook)
- end
end
end
diff --git a/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb b/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb
index 65a2e1cb5cb..7901ae005d9 100644
--- a/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/issue_importer_spec.rb
@@ -78,11 +78,6 @@ describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_cach
.to receive(:id_for)
.with(issue)
.and_return(milestone.id)
-
- allow(importer.user_finder)
- .to receive(:author_id_for)
- .with(issue)
- .and_return([user.id, true])
end
context 'when the issue author could be found' do
@@ -177,23 +172,6 @@ describe Gitlab::GithubImport::Importer::IssueImporter, :clean_gitlab_redis_cach
expect(importer.create_issue).to be_a_kind_of(Numeric)
end
-
- it 'triggers internal_id functionality to track greatest iids' do
- allow(importer.user_finder)
- .to receive(:author_id_for)
- .with(issue)
- .and_return([user.id, true])
-
- issue = build_stubbed(:issue, project: project)
- allow(importer)
- .to receive(:insert_and_return_id)
- .and_return(issue.id)
- allow(project.issues).to receive(:find).with(issue.id).and_return(issue)
-
- expect(issue).to receive(:ensure_project_iid!)
-
- importer.create_issue
- end
end
describe '#create_assignees' do
diff --git a/spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb b/spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb
index db0be760c7b..b1cac3b6e46 100644
--- a/spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb
@@ -29,25 +29,13 @@ describe Gitlab::GithubImport::Importer::MilestonesImporter, :clean_gitlab_redis
expect(importer)
.to receive(:bulk_insert)
- .with(Milestone, [milestone_hash], any_args)
+ .with(Milestone, [milestone_hash])
expect(importer)
.to receive(:build_milestones_cache)
importer.execute
end
-
- it 'tracks internal ids' do
- milestone_hash = { iid: 1, title: '1.0', project_id: project.id }
- allow(importer)
- .to receive(:build_milestones)
- .and_return([milestone_hash])
-
- expect(InternalId).to receive(:track_greatest)
- .with(nil, { project: project }, :milestones, 1, any_args)
-
- importer.execute
- end
end
describe '#build_milestones' do
diff --git a/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb
index 25684ea9e2c..0f21b8843b6 100644
--- a/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb
@@ -111,16 +111,6 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi
expect(mr).to be_instance_of(MergeRequest)
expect(exists).to eq(false)
end
-
- it 'triggers internal_id functionality to track greatest iids' do
- mr = build_stubbed(:merge_request, source_project: project, target_project: project)
- allow(importer).to receive(:insert_and_return_id).and_return(mr.id)
- allow(project.merge_requests).to receive(:find).with(mr.id).and_return(mr)
-
- expect(mr).to receive(:ensure_target_project_iid!)
-
- importer.create_merge_request
- end
end
context 'when the author could not be found' do
diff --git a/spec/lib/gitlab/release_blog_post_spec.rb b/spec/lib/gitlab/release_blog_post_spec.rb
deleted file mode 100644
index 2c987df3767..00000000000
--- a/spec/lib/gitlab/release_blog_post_spec.rb
+++ /dev/null
@@ -1,97 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::ReleaseBlogPost do
- describe '.blog_post_url' do
- let(:releases_xml) do
- <<~EOS
- <?xml version='1.0' encoding='utf-8' ?>
- <feed xmlns='http://www.w3.org/2005/Atom'>
- <entry>
- <release>11.2</release>
- <id>https://about.gitlab.com/2018/08/22/gitlab-11-2-released/</id>
- </entry>
- <entry>
- <release>11.1</release>
- <id>https://about.gitlab.com/2018/07/22/gitlab-11-1-released/</id>
- </entry>
- <entry>
- <release>11.0</release>
- <id>https://about.gitlab.com/2018/06/22/gitlab-11-0-released/</id>
- </entry>
- <entry>
- <release>10.8</release>
- <id>https://about.gitlab.com/2018/05/22/gitlab-10-8-released/</id>
- </entry>
- </feed>
- EOS
- end
-
- subject { described_class.send(:new).blog_post_url }
-
- before do
- stub_request(:get, 'https://about.gitlab.com/releases.xml')
- .to_return(status: 200, headers: { 'content-type' => ['text/xml'] }, body: releases_xml)
- end
-
- context 'matches GitLab version to blog post url' do
- it 'returns the correct url for major pre release' do
- stub_const('Gitlab::VERSION', '11.0.0-pre')
-
- expect(subject).to eql('https://about.gitlab.com/2018/05/22/gitlab-10-8-released/')
- end
-
- it 'returns the correct url for major release candidate' do
- stub_const('Gitlab::VERSION', '11.0.0-rc3')
-
- expect(subject).to eql('https://about.gitlab.com/2018/05/22/gitlab-10-8-released/')
- end
-
- it 'returns the correct url for major release' do
- stub_const('Gitlab::VERSION', '11.0.0')
-
- expect(subject).to eql('https://about.gitlab.com/2018/06/22/gitlab-11-0-released/')
- end
-
- it 'returns the correct url for minor pre release' do
- stub_const('Gitlab::VERSION', '11.2.0-pre')
-
- expect(subject).to eql('https://about.gitlab.com/2018/07/22/gitlab-11-1-released/')
- end
-
- it 'returns the correct url for minor release candidate' do
- stub_const('Gitlab::VERSION', '11.2.0-rc3')
-
- expect(subject).to eql('https://about.gitlab.com/2018/07/22/gitlab-11-1-released/')
- end
-
- it 'returns the correct url for minor release' do
- stub_const('Gitlab::VERSION', '11.2.0')
-
- expect(subject).to eql('https://about.gitlab.com/2018/08/22/gitlab-11-2-released/')
- end
-
- it 'returns the correct url for patch pre release' do
- stub_const('Gitlab::VERSION', '11.2.1-pre')
- expect(subject).to eql('https://about.gitlab.com/2018/08/22/gitlab-11-2-released/')
- end
-
- it 'returns the correct url for patch release candidate' do
- stub_const('Gitlab::VERSION', '11.2.1-rc3')
-
- expect(subject).to eql('https://about.gitlab.com/2018/08/22/gitlab-11-2-released/')
- end
-
- it 'returns the correct url for patch release' do
- stub_const('Gitlab::VERSION', '11.2.1')
-
- expect(subject).to eql('https://about.gitlab.com/2018/08/22/gitlab-11-2-released/')
- end
-
- it 'returns nil when no blog post is matched' do
- stub_const('Gitlab::VERSION', '9.0.0')
-
- expect(subject).to be(nil)
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb b/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
index a9d15f1d522..7bc4599e20f 100644
--- a/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
+++ b/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
@@ -16,7 +16,7 @@ describe Gitlab::SidekiqLogging::StructuredLogger do
"correlation_id" => 'cid'
}
end
- let(:logger) { double() }
+ let(:logger) { double }
let(:start_payload) do
job.merge(
'message' => 'TestWorker JID-da883554ee4fe414012f5f42: start',
diff --git a/spec/lib/gitlab/tracing/rails/action_view_subscriber_spec.rb b/spec/lib/gitlab/tracing/rails/action_view_subscriber_spec.rb
new file mode 100644
index 00000000000..c9d1a06b3e6
--- /dev/null
+++ b/spec/lib/gitlab/tracing/rails/action_view_subscriber_spec.rb
@@ -0,0 +1,147 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rspec-parameterized'
+
+describe Gitlab::Tracing::Rails::ActionViewSubscriber do
+ using RSpec::Parameterized::TableSyntax
+
+ shared_examples 'an actionview notification' do
+ it 'should notify the tracer when the hash contains null values' do
+ expect(subject).to receive(:postnotify_span).with(notification_name, start, finish, tags: expected_tags, exception: exception)
+
+ subject.public_send(notify_method, start, finish, payload)
+ end
+
+ it 'should notify the tracer when the payload is missing values' do
+ expect(subject).to receive(:postnotify_span).with(notification_name, start, finish, tags: expected_tags, exception: exception)
+
+ subject.public_send(notify_method, start, finish, payload.compact)
+ end
+
+ it 'should not throw exceptions when with the default tracer' do
+ expect { subject.public_send(notify_method, start, finish, payload) }.not_to raise_error
+ end
+ end
+
+ describe '.instrument' do
+ it 'is unsubscribeable' do
+ unsubscribe = described_class.instrument
+
+ expect(unsubscribe).not_to be_nil
+ expect { unsubscribe.call }.not_to raise_error
+ end
+ end
+
+ describe '#notify_render_template' do
+ subject { described_class.new }
+ let(:start) { Time.now }
+ let(:finish) { Time.now }
+ let(:notification_name) { 'render_template' }
+ let(:notify_method) { :notify_render_template }
+
+ where(:identifier, :layout, :exception) do
+ nil | nil | nil
+ "" | nil | nil
+ "show.haml" | nil | nil
+ nil | "" | nil
+ nil | "layout.haml" | nil
+ nil | nil | StandardError.new
+ end
+
+ with_them do
+ let(:payload) do
+ {
+ exception: exception,
+ identifier: identifier,
+ layout: layout
+ }
+ end
+
+ let(:expected_tags) do
+ {
+ 'component' => 'ActionView',
+ 'template.id' => identifier,
+ 'template.layout' => layout
+ }
+ end
+
+ it_behaves_like 'an actionview notification'
+ end
+ end
+
+ describe '#notify_render_collection' do
+ subject { described_class.new }
+ let(:start) { Time.now }
+ let(:finish) { Time.now }
+ let(:notification_name) { 'render_collection' }
+ let(:notify_method) { :notify_render_collection }
+
+ where(
+ :identifier, :count, :expected_count, :cache_hits, :expected_cache_hits, :exception) do
+ nil | nil | 0 | nil | 0 | nil
+ "" | nil | 0 | nil | 0 | nil
+ "show.haml" | nil | 0 | nil | 0 | nil
+ nil | 0 | 0 | nil | 0 | nil
+ nil | 1 | 1 | nil | 0 | nil
+ nil | nil | 0 | 0 | 0 | nil
+ nil | nil | 0 | 1 | 1 | nil
+ nil | nil | 0 | nil | 0 | StandardError.new
+ end
+
+ with_them do
+ let(:payload) do
+ {
+ exception: exception,
+ identifier: identifier,
+ count: count,
+ cache_hits: cache_hits
+ }
+ end
+
+ let(:expected_tags) do
+ {
+ 'component' => 'ActionView',
+ 'template.id' => identifier,
+ 'template.count' => expected_count,
+ 'template.cache.hits' => expected_cache_hits
+ }
+ end
+
+ it_behaves_like 'an actionview notification'
+ end
+ end
+
+ describe '#notify_render_partial' do
+ subject { described_class.new }
+ let(:start) { Time.now }
+ let(:finish) { Time.now }
+ let(:notification_name) { 'render_partial' }
+ let(:notify_method) { :notify_render_partial }
+
+ where(:identifier, :exception) do
+ nil | nil
+ "" | nil
+ "show.haml" | nil
+ nil | StandardError.new
+ end
+
+ with_them do
+ let(:payload) do
+ {
+ exception: exception,
+ identifier: identifier
+ }
+ end
+
+ let(:expected_tags) do
+ {
+ 'component' => 'ActionView',
+ 'template.id' => identifier
+ }
+ end
+
+ it_behaves_like 'an actionview notification'
+ end
+ end
+end
diff --git a/spec/lib/gitlab/tracing/rails/active_record_subscriber_spec.rb b/spec/lib/gitlab/tracing/rails/active_record_subscriber_spec.rb
index 5eb5c044f84..3d066843148 100644
--- a/spec/lib/gitlab/tracing/rails/active_record_subscriber_spec.rb
+++ b/spec/lib/gitlab/tracing/rails/active_record_subscriber_spec.rb
@@ -7,11 +7,11 @@ describe Gitlab::Tracing::Rails::ActiveRecordSubscriber do
using RSpec::Parameterized::TableSyntax
describe '.instrument' do
- it 'is unsubscribable' do
- subscription = described_class.instrument
+ it 'is unsubscribeable' do
+ unsubscribe = described_class.instrument
- expect(subscription).not_to be_nil
- expect { ActiveSupport::Notifications.unsubscribe(subscription) }.not_to raise_error
+ expect(unsubscribe).not_to be_nil
+ expect { unsubscribe.call }.not_to raise_error
end
end
diff --git a/spec/lib/gitlab_spec.rb b/spec/lib/gitlab_spec.rb
index 6ac3d115bc6..5f7a0cca351 100644
--- a/spec/lib/gitlab_spec.rb
+++ b/spec/lib/gitlab_spec.rb
@@ -70,82 +70,6 @@ describe Gitlab do
end
end
- describe '.final_release?' do
- subject { described_class.final_release? }
-
- context 'returns the corrent boolean value' do
- it 'is false for a pre release' do
- stub_const('Gitlab::VERSION', '11.0.0-pre')
-
- expect(subject).to be false
- end
-
- it 'is false for a release candidate' do
- stub_const('Gitlab::VERSION', '11.0.0-rc2')
-
- expect(subject).to be false
- end
-
- it 'is true for a final release' do
- stub_const('Gitlab::VERSION', '11.0.2')
-
- expect(subject).to be true
- end
- end
- end
-
- describe '.minor_release' do
- subject { described_class.minor_release }
-
- it 'returns the minor release of the full GitLab version' do
- stub_const('Gitlab::VERSION', '11.0.1-rc3')
-
- expect(subject).to eql '11.0'
- end
- end
-
- describe '.previous_release' do
- subject { described_class.previous_release }
-
- context 'it should return the previous release' do
- it 'returns the previous major version when GitLab major version is not final' do
- stub_const('Gitlab::VERSION', '11.0.1-pre')
-
- expect(subject).to eql '10'
- end
-
- it 'returns the current minor version when the GitLab patch version is RC and > 0' do
- stub_const('Gitlab::VERSION', '11.2.1-rc3')
-
- expect(subject).to eql '11.2'
- end
-
- it 'returns the previous minor version when the GitLab patch version is RC and 0' do
- stub_const('Gitlab::VERSION', '11.2.0-rc3')
-
- expect(subject).to eql '11.1'
- end
- end
- end
-
- describe '.new_major_release?' do
- subject { described_class.new_major_release? }
-
- context 'returns the corrent boolean value' do
- it 'is true when the minor version is 0 and the patch is a pre release' do
- stub_const('Gitlab::VERSION', '11.0.1-pre')
-
- expect(subject).to be true
- end
-
- it 'is false when the minor version is above 0' do
- stub_const('Gitlab::VERSION', '11.2.1-rc3')
-
- expect(subject).to be false
- end
- end
- end
-
describe '.com?' do
it 'is true when on GitLab.com' do
stub_config_setting(url: 'https://gitlab.com')
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 8ba33ff9c04..8a1bbb26e57 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -2133,6 +2133,8 @@ describe Ci::Build do
{ key: 'CI_PROJECT_NAMESPACE', value: project.namespace.full_path, public: true },
{ key: 'CI_PROJECT_URL', value: project.web_url, public: true },
{ key: 'CI_PROJECT_VISIBILITY', value: 'private', public: true },
+ { key: 'CI_PAGES_DOMAIN', value: Gitlab.config.pages.host, public: true },
+ { key: 'CI_PAGES_URL', value: project.pages_url, public: true },
{ key: 'CI_API_V4_URL', value: 'http://localhost/api/v4', public: true },
{ key: 'CI_PIPELINE_IID', value: pipeline.iid.to_s, public: true },
{ key: 'CI_CONFIG_PATH', value: pipeline.ci_yaml_file_path, public: true },
diff --git a/spec/models/identity_spec.rb b/spec/models/identity_spec.rb
index a5ce245c21d..e1a7a59dfd1 100644
--- a/spec/models/identity_spec.rb
+++ b/spec/models/identity_spec.rb
@@ -10,6 +10,40 @@ describe Identity do
it { is_expected.to respond_to(:extern_uid) }
end
+ describe 'validations' do
+ set(:user) { create(:user) }
+
+ context 'with existing user and provider' do
+ before do
+ create(:identity, provider: 'ldapmain', user_id: user.id)
+ end
+
+ it 'returns false for a duplicate entry' do
+ identity = user.identities.build(provider: 'ldapmain', user_id: user.id)
+
+ expect(identity.validate).to be_falsey
+ end
+
+ it 'returns true when a different provider is used' do
+ identity = user.identities.build(provider: 'gitlab', user_id: user.id)
+
+ expect(identity.validate).to be_truthy
+ end
+ end
+
+ context 'with newly-created user' do
+ before do
+ create(:identity, provider: 'ldapmain', user_id: nil)
+ end
+
+ it 'successfully validates even with a nil user_id' do
+ identity = user.identities.build(provider: 'ldapmain')
+
+ expect(identity.validate).to be_truthy
+ end
+ end
+ end
+
describe '#is_ldap?' do
let(:ldap_identity) { create(:identity, provider: 'ldapmain') }
let(:other_identity) { create(:identity, provider: 'twitter') }
diff --git a/spec/models/internal_id_spec.rb b/spec/models/internal_id_spec.rb
index 4696341c05f..d32f163f05b 100644
--- a/spec/models/internal_id_spec.rb
+++ b/spec/models/internal_id_spec.rb
@@ -13,6 +13,29 @@ describe InternalId do
it { is_expected.to validate_presence_of(:usage) }
end
+ describe '.flush_records!' do
+ subject { described_class.flush_records!(project: project) }
+
+ let(:another_project) { create(:project) }
+
+ before do
+ create_list(:issue, 2, project: project)
+ create_list(:issue, 2, project: another_project)
+ end
+
+ it 'deletes all records for the given project' do
+ expect { subject }.to change { described_class.where(project: project).count }.from(1).to(0)
+ end
+
+ it 'retains records for other projects' do
+ expect { subject }.not_to change { described_class.where(project: another_project).count }
+ end
+
+ it 'does not allow an empty filter' do
+ expect { described_class.flush_records!({}) }.to raise_error(/filter cannot be empty/)
+ end
+ end
+
describe '.generate_next' do
subject { described_class.generate_next(issue, scope, usage, init) }
diff --git a/spec/models/project_services/bamboo_service_spec.rb b/spec/models/project_services/bamboo_service_spec.rb
index ee84fa95f0e..b880d90d28f 100644
--- a/spec/models/project_services/bamboo_service_spec.rb
+++ b/spec/models/project_services/bamboo_service_spec.rb
@@ -144,7 +144,7 @@ describe BambooService, :use_clean_rails_memory_store_caching do
end
end
- describe '#calculate_reactive_cache' do
+ shared_examples 'reactive cache calculation' do
context '#build_page' do
subject { service.calculate_reactive_cache('123', 'unused')[:build_page] }
@@ -155,7 +155,7 @@ describe BambooService, :use_clean_rails_memory_store_caching do
end
it 'returns a specific URL when response has no results' do
- stub_request(body: bamboo_response(size: 0))
+ stub_request(body: %q({"results":{"results":{"size":"0"}}}))
is_expected.to eq('http://gitlab.com/bamboo/browse/foo')
end
@@ -224,6 +224,24 @@ describe BambooService, :use_clean_rails_memory_store_caching do
end
end
+ describe '#calculate_reactive_cache' do
+ context 'when Bamboo API returns single result' do
+ let(:bamboo_response_template) do
+ %q({"results":{"results":{"size":"1","result":{"buildState":"%{build_state}","planResultKey":{"key":"42"}}}}})
+ end
+
+ it_behaves_like 'reactive cache calculation'
+ end
+
+ context 'when Bamboo API returns an array of results and we only consider the last one' do
+ let(:bamboo_response_template) do
+ %q({"results":{"results":{"size":"2","result":[{"buildState":"%{build_state}","planResultKey":{"key":"41"}},{"buildState":"%{build_state}","planResultKey":{"key":"42"}}]}}})
+ end
+
+ it_behaves_like 'reactive cache calculation'
+ end
+ end
+
def stub_update_and_build_request(status: 200, body: nil)
bamboo_full_url = 'http://gitlab.com/bamboo/updateAndBuild.action?buildKey=foo&os_authType=basic'
@@ -244,8 +262,8 @@ describe BambooService, :use_clean_rails_memory_store_caching do
).with(basic_auth: %w(mic password))
end
- def bamboo_response(result_key: 42, build_state: 'success', size: 1)
+ def bamboo_response(build_state: 'success')
# reference: https://docs.atlassian.com/atlassian-bamboo/REST/6.2.5/#d2e786
- %Q({"results":{"results":{"size":"#{size}","result":[{"buildState":"#{build_state}","planResultKey":{"key":"#{result_key}"}}]}}})
+ bamboo_response_template % { build_state: build_state }
end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 4b061b5e24f..7d3f2dfe374 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -3767,6 +3767,7 @@ describe Project do
expect(import_state).to receive(:remove_jid)
expect(project).to receive(:after_create_default_branch)
expect(project).to receive(:refresh_markdown_cache!)
+ expect(InternalId).to receive(:flush_records!).with(project: project)
project.after_import
end
diff --git a/spec/serializers/cluster_application_entity_spec.rb b/spec/serializers/cluster_application_entity_spec.rb
index 852b6af9f7f..88d16a5b360 100644
--- a/spec/serializers/cluster_application_entity_spec.rb
+++ b/spec/serializers/cluster_application_entity_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe ClusterApplicationEntity do
describe '#as_json' do
- let(:application) { build(:clusters_applications_helm) }
+ let(:application) { build(:clusters_applications_helm, version: '0.1.1') }
subject { described_class.new(application).as_json }
it 'has name' do
@@ -13,6 +13,10 @@ describe ClusterApplicationEntity do
expect(subject[:status]).to eq(:not_installable)
end
+ it 'has version' do
+ expect(subject[:version]).to eq('0.1.1')
+ end
+
it 'has no status_reason' do
expect(subject[:status_reason]).to be_nil
end
diff --git a/spec/services/resource_events/merge_into_notes_service_spec.rb b/spec/services/resource_events/merge_into_notes_service_spec.rb
index 14c43b46c15..72467091791 100644
--- a/spec/services/resource_events/merge_into_notes_service_spec.rb
+++ b/spec/services/resource_events/merge_into_notes_service_spec.rb
@@ -44,7 +44,7 @@ describe ResourceEvents::MergeIntoNotesService do
create_event(created_at: time, user: user2)
create_event(created_at: 1.day.ago, label: label2)
- notes = described_class.new(resource, user).execute()
+ notes = described_class.new(resource, user).execute
expected = [
"added #{label.to_reference} label and removed #{label2.to_reference} label",
@@ -61,7 +61,7 @@ describe ResourceEvents::MergeIntoNotesService do
event = create_event(created_at: 1.day.ago)
notes = described_class.new(resource, user,
- last_fetched_at: 2.days.ago.to_i).execute()
+ last_fetched_at: 2.days.ago.to_i).execute
expect(notes.count).to eq 1
expect(notes.first.discussion_id).to eq event.discussion_id
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 72684caad32..97e7a019222 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -127,11 +127,6 @@ RSpec.configure do |config|
.and_return(false)
end
- config.before(:suite) do
- # Set latest release blog post URL for "What's new?" link
- Gitlab::ReleaseBlogPost.instance.instance_variable_set(:@url, 'https://about.gitlab.com')
- end
-
config.before(:example, :quarantine) do
# Skip tests in quarantine unless we explicitly focus on them.
skip('In quarantine') unless config.inclusion_filter[:quarantine]
diff --git a/spec/support/helpers/kubernetes_helpers.rb b/spec/support/helpers/kubernetes_helpers.rb
index 6930b809048..9dc89b483b2 100644
--- a/spec/support/helpers/kubernetes_helpers.rb
+++ b/spec/support/helpers/kubernetes_helpers.rb
@@ -369,6 +369,6 @@ module KubernetesHelpers
end
def empty_deployment_rollout_status
- ::Gitlab::Kubernetes::RolloutStatus.from_deployments()
+ ::Gitlab::Kubernetes::RolloutStatus.from_deployments
end
end
diff --git a/spec/support/helpers/rake_helpers.rb b/spec/support/helpers/rake_helpers.rb
index acd9cce6a67..7d8d7750bf3 100644
--- a/spec/support/helpers/rake_helpers.rb
+++ b/spec/support/helpers/rake_helpers.rb
@@ -14,7 +14,7 @@ module RakeHelpers
end
def silence_progress_bar
- allow_any_instance_of(ProgressBar::Output).to receive(:stream).and_return(double().as_null_object)
+ allow_any_instance_of(ProgressBar::Output).to receive(:stream).and_return(double.as_null_object)
end
def main_object
diff --git a/spec/support/helpers/stub_env.rb b/spec/support/helpers/stub_env.rb
index 36b90fc68d6..1c2f474a015 100644
--- a/spec/support/helpers/stub_env.rb
+++ b/spec/support/helpers/stub_env.rb
@@ -18,7 +18,7 @@ module StubENV
allow(ENV).to receive(:[]).with(key).and_return(value)
allow(ENV).to receive(:key?).with(key).and_return(true)
allow(ENV).to receive(:fetch).with(key).and_return(value)
- allow(ENV).to receive(:fetch).with(key, anything()) do |_, default_val|
+ allow(ENV).to receive(:fetch).with(key, anything) do |_, default_val|
value || default_val
end
end
diff --git a/spec/views/projects/_home_panel.html.haml_spec.rb b/spec/views/projects/_home_panel.html.haml_spec.rb
index 006c93686d5..908ecb898e4 100644
--- a/spec/views/projects/_home_panel.html.haml_spec.rb
+++ b/spec/views/projects/_home_panel.html.haml_spec.rb
@@ -23,7 +23,7 @@ describe 'projects/_home_panel' do
it 'makes it possible to set notification level' do
render
- expect(view).to render_template('projects/buttons/_notifications')
+ expect(view).to render_template('shared/notifications/_new_button')
expect(rendered).to have_selector('.notification-dropdown')
end
end