Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml19
-rw-r--r--.gitlab/ci/pages.gitlab-ci.yml3
-rw-r--r--.gitlab/ci/qa.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml5
-rw-r--r--.rubocop_todo.yml2
-rw-r--r--app/assets/javascripts/boards/models/issue.js4
-rw-r--r--app/assets/javascripts/groups/components/app.vue7
-rw-r--r--app/assets/javascripts/groups/service/groups_service.js21
-rw-r--r--app/models/board.rb1
-rw-r--r--app/models/concerns/issuable.rb4
-rw-r--r--app/models/event.rb1
-rw-r--r--app/models/merge_request_diff.rb6
-rw-r--r--app/models/milestone.rb1
-rw-r--r--app/models/note.rb1
-rw-r--r--app/models/todo.rb1
-rw-r--r--app/services/event_create_service.rb13
-rw-r--r--app/views/projects/settings/ci_cd/_autodevops_form.html.haml18
-rw-r--r--app/views/shared/empty_states/_priority_labels.html.haml4
-rw-r--r--changelogs/unreleased/change-prioritized-labels-empty-state-message.yml5
-rw-r--r--changelogs/unreleased/je-add-cluster-domain-warning.yml5
-rw-r--r--changelogs/unreleased/remove-vue-resource-from-group-service.yml5
-rw-r--r--changelogs/unreleased/remove-vue-resource-from-issue.yml5
-rw-r--r--config/gitlab.yml.example1
-rw-r--r--db/migrate/20190826100605_add_group_column_to_events.rb9
-rw-r--r--db/schema.rb3
-rw-r--r--doc/administration/logs.md13
-rw-r--r--doc/ci/environments.md5
-rw-r--r--doc/ci/large_repositories/index.md2
-rw-r--r--doc/ci/variables/README.md2
-rw-r--r--doc/development/database_review.md3
-rw-r--r--doc/user/instance/clusters/index.md2
-rw-r--r--doc/user/project/operations/feature_flags.md6
-rw-r--r--lib/api/api.rb2
-rw-r--r--lib/api/internal.rb294
-rw-r--r--lib/api/internal/base.rb296
-rw-r--r--lib/api/release/links.rb4
-rw-r--r--lib/api/releases.rb8
-rw-r--r--lib/gitlab/git/diff_collection.rb6
-rw-r--r--lib/gitlab/jwt_authenticatable.rb42
-rw-r--r--lib/gitlab/workhorse.rb28
-rw-r--r--lib/peek/views/active_record.rb8
-rw-r--r--lib/peek/views/gitaly.rb10
-rw-r--r--locale/gitlab.pot8
-rwxr-xr-xscripts/review_apps/review-apps.sh7
-rw-r--r--spec/javascripts/boards/issue_spec.js6
-rw-r--r--spec/javascripts/groups/components/app_spec.js3
-rw-r--r--spec/javascripts/groups/service/groups_service_spec.js17
-rw-r--r--spec/lib/gitlab/favicon_spec.rb8
-rw-r--r--spec/lib/gitlab/git/diff_collection_spec.rb69
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml1
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml1
-rw-r--r--spec/lib/gitlab/jwt_authenticatable_spec.rb93
-rw-r--r--spec/lib/gitlab/workhorse_spec.rb51
-rw-r--r--spec/lib/gitlab_spec.rb8
-rw-r--r--spec/models/merge_request/metrics_spec.rb2
-rw-r--r--spec/models/merge_request_diff_spec.rb14
-rw-r--r--spec/requests/api/internal/base_spec.rb (renamed from spec/requests/api/internal_spec.rb)2
-rw-r--r--spec/support/helpers/rails_helpers.rb7
-rw-r--r--spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb8
-rw-r--r--yarn.lock4
60 files changed, 702 insertions, 484 deletions
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index 0d73092cfba..0720ea3e056 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -233,22 +233,3 @@ qa-frontend-node:latest:
extends: .qa-frontend-node
image: node:latest
allow_failure: true
-
-jsdoc:
- extends:
- - .default-tags
- - .default-retry
- - .default-cache
- - .except-docs
- variables:
- SETUP_DB: "false"
- stage: post-test
- dependencies: ["compile-assets", "compile-assets pull-cache"]
- script:
- - date
- - yarn run jsdoc || true # ignore exit code
- artifacts:
- name: jsdoc
- expire_in: 31d
- paths:
- - jsdoc/
diff --git a/.gitlab/ci/pages.gitlab-ci.yml b/.gitlab/ci/pages.gitlab-ci.yml
index 5d13a72e224..2de09753cca 100644
--- a/.gitlab/ci/pages.gitlab-ci.yml
+++ b/.gitlab/ci/pages.gitlab-ci.yml
@@ -9,7 +9,7 @@ pages:
- master@gitlab-org/gitlab-ce
- master@gitlab-org/gitlab-ee
stage: pages
- dependencies: ["coverage", "karma", "gitlab:assets:compile", "jsdoc"]
+ dependencies: ["coverage", "karma", "gitlab:assets:compile"]
script:
- mv public/ .public/
- mkdir public/
@@ -18,7 +18,6 @@ pages:
- mv webpack-report/ public/webpack-report/ || true
- cp .public/assets/application-*.css public/application.css || true
- cp .public/assets/application-*.css.gz public/application.css.gz || true
- - mv jsdoc/ public/jsdoc/ || true
artifacts:
paths:
- public
diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml
index 8628e1e0a14..9c021b23db6 100644
--- a/.gitlab/ci/qa.gitlab-ci.yml
+++ b/.gitlab/ci/qa.gitlab-ci.yml
@@ -19,6 +19,8 @@ package-and-qa-manual:
except:
refs:
- master
+ - /(^docs[\/-].+|.+-docs$)/
+ - /(^qa[\/-].*|.*-qa$)/
when: manual
needs: ["build-qa-image", "gitlab:assets:compile pull-cache"]
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index c4a81a021a9..6695404653c 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -128,8 +128,9 @@ review-stop:
- source utils.sh
- source review-apps.sh
script:
- - delete
- artifacts: {}
+ - delete_release
+ artifacts:
+ paths: []
.review-qa-base:
extends:
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index be147d72f71..f1f8ff6e862 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -218,7 +218,7 @@ Lint/UriEscapeUnescape:
- 'app/models/project_services/drone_ci_service.rb'
- 'spec/lib/google_api/auth_spec.rb'
- 'spec/requests/api/files_spec.rb'
- - 'spec/requests/api/internal_spec.rb'
+ - 'spec/requests/api/internal/base_spec.rb'
# Offense count: 1
# Configuration parameters: CheckForMethodsWithNoSideEffects.
diff --git a/app/assets/javascripts/boards/models/issue.js b/app/assets/javascripts/boards/models/issue.js
index 9069b35db9a..086340105b7 100644
--- a/app/assets/javascripts/boards/models/issue.js
+++ b/app/assets/javascripts/boards/models/issue.js
@@ -3,7 +3,7 @@
/* global ListMilestone */
/* global ListAssignee */
-import Vue from 'vue';
+import axios from '~/lib/utils/axios_utils';
import './label';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import IssueProject from './project';
@@ -133,7 +133,7 @@ class ListIssue {
}
const projectPath = this.project ? this.project.path : '';
- return Vue.http.patch(`${this.path}.json`, data).then(({ body = {} } = {}) => {
+ return axios.patch(`${this.path}.json`, data).then(({ data: body = {} } = {}) => {
/**
* Since post implementation of Scoped labels, server can reject
* same key-ed labels. To keep the UI and server Model consistent,
diff --git a/app/assets/javascripts/groups/components/app.vue b/app/assets/javascripts/groups/components/app.vue
index aa50fd8ff62..8d2dac47ff2 100644
--- a/app/assets/javascripts/groups/components/app.vue
+++ b/app/assets/javascripts/groups/components/app.vue
@@ -95,10 +95,8 @@ export default {
if (updatePagination) {
this.updatePagination(res.headers);
}
-
- return res;
+ return res.data;
})
- .then(res => res.json())
.catch(() => {
this.isLoading = false;
$.scrollTo(0);
@@ -190,11 +188,10 @@ export default {
this.targetGroup.isBeingRemoved = true;
this.service
.leaveGroup(this.targetGroup.leavePath)
- .then(res => res.json())
.then(res => {
$.scrollTo(0);
this.store.removeGroup(this.targetGroup, this.targetParentGroup);
- Flash(res.notice, 'notice');
+ Flash(res.data.notice, 'notice');
})
.catch(err => {
let message = COMMON_STR.FAILURE;
diff --git a/app/assets/javascripts/groups/service/groups_service.js b/app/assets/javascripts/groups/service/groups_service.js
index b79ba291463..790b581a7c0 100644
--- a/app/assets/javascripts/groups/service/groups_service.js
+++ b/app/assets/javascripts/groups/service/groups_service.js
@@ -1,40 +1,39 @@
-import Vue from 'vue';
-import '../../vue_shared/vue_resource_interceptor';
+import axios from '~/lib/utils/axios_utils';
export default class GroupsService {
constructor(endpoint) {
- this.groups = Vue.resource(endpoint);
+ this.endpoint = endpoint;
}
getGroups(parentId, page, filterGroups, sort, archived) {
- const data = {};
+ const params = {};
if (parentId) {
- data.parent_id = parentId;
+ params.parent_id = parentId;
} else {
// Do not send the following param for sub groups
if (page) {
- data.page = page;
+ params.page = page;
}
if (filterGroups) {
- data.filter = filterGroups;
+ params.filter = filterGroups;
}
if (sort) {
- data.sort = sort;
+ params.sort = sort;
}
if (archived) {
- data.archived = archived;
+ params.archived = archived;
}
}
- return this.groups.get(data);
+ return axios.get(this.endpoint, { params });
}
// eslint-disable-next-line class-methods-use-this
leaveGroup(endpoint) {
- return Vue.http.delete(endpoint);
+ return axios.delete(endpoint);
}
}
diff --git a/app/models/board.rb b/app/models/board.rb
index 50b6ca9b70f..b5d07f1b282 100644
--- a/app/models/board.rb
+++ b/app/models/board.rb
@@ -19,6 +19,7 @@ class Board < ApplicationRecord
def parent
@parent ||= group || project
end
+ alias_method :resource_parent, :parent
def group_board?
group_id.present?
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index eefe9f00836..a998d9b7e1b 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -277,6 +277,10 @@ module Issuable
end
end
+ def resource_parent
+ project
+ end
+
def milestone_available?
project_id == milestone&.project_id || project.ancestors_upto.compact.include?(milestone&.group)
end
diff --git a/app/models/event.rb b/app/models/event.rb
index 392d7368033..52d54be39a9 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -51,6 +51,7 @@ class Event < ApplicationRecord
belongs_to :author, class_name: "User"
belongs_to :project
+ belongs_to :group
belongs_to :target, -> {
# If the association for "target" defines an "author" association we want to
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index 2402fa8e38f..4db2b7a74e5 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -197,7 +197,7 @@ class MergeRequestDiff < ApplicationRecord
def lines_count
strong_memoize(:lines_count) do
- diffs.diff_files.sum(&:line_count)
+ raw_diffs(limits: false).line_count
end
end
@@ -222,6 +222,10 @@ class MergeRequestDiff < ApplicationRecord
commits.last
end
+ def last_commit
+ commits.first
+ end
+
def base_commit
return unless base_commit_sha
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 101e963ea29..cb87b46a31d 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -260,6 +260,7 @@ class Milestone < ApplicationRecord
def parent
group || project
end
+ alias_method :resource_parent, :parent
def group_milestone?
group_id.present?
diff --git a/app/models/note.rb b/app/models/note.rb
index ebd13675dc9..0d024b0a25c 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -477,6 +477,7 @@ class Note < ApplicationRecord
def parent
project
end
+ alias_method :resource_parent, :parent
private
diff --git a/app/models/todo.rb b/app/models/todo.rb
index 1ec04189482..f7f30aed832 100644
--- a/app/models/todo.rb
+++ b/app/models/todo.rb
@@ -146,6 +146,7 @@ class Todo < ApplicationRecord
def parent
project
end
+ alias_method :resource_parent, :parent
def unmergeable?
action == UNMERGEABLE
diff --git a/app/services/event_create_service.rb b/app/services/event_create_service.rb
index e7464fd9d5f..39266a6c961 100644
--- a/app/services/event_create_service.rb
+++ b/app/services/event_create_service.rb
@@ -95,16 +95,23 @@ class EventCreateService
private
def create_record_event(record, current_user, status)
- create_event(record.project, current_user, status, target_id: record.id, target_type: record.class.name)
+ create_event(record.resource_parent, current_user, status, target_id: record.id, target_type: record.class.name)
end
- def create_event(project, current_user, status, attributes = {})
+ def create_event(resource_parent, current_user, status, attributes = {})
attributes.reverse_merge!(
- project: project,
action: status,
author_id: current_user.id
)
+ resource_parent_attr = case resource_parent
+ when Project
+ :project
+ when Group
+ :group
+ end
+ attributes[resource_parent_attr] = resource_parent if resource_parent_attr
+
Event.create!(attributes)
end
end
diff --git a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
index 04b77fb987a..1d5d90593ae 100644
--- a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
@@ -1,3 +1,14 @@
+- has_base_domain = @project.all_clusters.any? { |cluster| cluster.base_domain && !cluster.base_domain.empty? }
+
+- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe
+- link_end = '</a>'.html_safe
+
+- kubernetes_cluster_path = help_page_path('user/project/clusters/index')
+- kubernetes_cluster_link_start = link_start % { url: kubernetes_cluster_path }
+
+- base_domain_path = help_page_path('user/project/clusters/index', anchor: 'base-domain')
+- base_domain_link_start = link_start % { url: base_domain_path }
+
.row
.col-lg-12
= form_for @project, url: project_settings_ci_cd_path(@project, anchor: 'autodevops-settings') do |f|
@@ -19,9 +30,10 @@
.card-footer.js-extra-settings{ class: auto_devops_enabled || 'hidden' }
- if @project.all_clusters.empty?
%p.settings-message.text-center
- - kubernetes_cluster_link = help_page_path('user/project/clusters/index')
- - kubernetes_cluster_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: kubernetes_cluster_link }
- = s_('CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly.').html_safe % { kubernetes_cluster_start: kubernetes_cluster_start, kubernetes_cluster_end: '</a>'.html_safe }
+ = s_('CICD|You must add a %{kubernetes_cluster_link_start}Kubernetes cluster integration%{link_end} to this project with a domain in order for your deployment strategy to work correctly.').html_safe % { kubernetes_cluster_link_start: kubernetes_cluster_link_start, link_end: link_end }
+ - elsif !has_base_domain
+ %p.settings-message.text-center
+ = s_('CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work.').html_safe % { base_domain_link_start: base_domain_link_start, kubernetes_cluster_link_start: kubernetes_cluster_link_start, link_end: link_end }
%label.prepend-top-10
%strong= s_('CICD|Deployment strategy')
.form-check
diff --git a/app/views/shared/empty_states/_priority_labels.html.haml b/app/views/shared/empty_states/_priority_labels.html.haml
index bba3475d244..a93f6e4c795 100644
--- a/app/views/shared/empty_states/_priority_labels.html.haml
+++ b/app/views/shared/empty_states/_priority_labels.html.haml
@@ -1,4 +1,6 @@
.text-center
.svg-content.qa-label-svg
= image_tag 'illustrations/priority_labels.svg'
- %p Star labels to start sorting by priority
+ - if can?(current_user, :admin_label, @project)
+ %p
+ = _("Star labels to start sorting by priority")
diff --git a/changelogs/unreleased/change-prioritized-labels-empty-state-message.yml b/changelogs/unreleased/change-prioritized-labels-empty-state-message.yml
new file mode 100644
index 00000000000..d5df889d15c
--- /dev/null
+++ b/changelogs/unreleased/change-prioritized-labels-empty-state-message.yml
@@ -0,0 +1,5 @@
+---
+title: Change prioritized labels empty state message
+merge_request: 32338
+author: Lee Tickett
+type: other
diff --git a/changelogs/unreleased/je-add-cluster-domain-warning.yml b/changelogs/unreleased/je-add-cluster-domain-warning.yml
new file mode 100644
index 00000000000..e7d244f730f
--- /dev/null
+++ b/changelogs/unreleased/je-add-cluster-domain-warning.yml
@@ -0,0 +1,5 @@
+---
+title: Add cluster domain warning
+merge_request: 32260
+author:
+type: changed
diff --git a/changelogs/unreleased/remove-vue-resource-from-group-service.yml b/changelogs/unreleased/remove-vue-resource-from-group-service.yml
new file mode 100644
index 00000000000..771d301cabf
--- /dev/null
+++ b/changelogs/unreleased/remove-vue-resource-from-group-service.yml
@@ -0,0 +1,5 @@
+---
+title: Remove vue resource from group service
+merge_request:
+author: Lee Tickett
+type: other
diff --git a/changelogs/unreleased/remove-vue-resource-from-issue.yml b/changelogs/unreleased/remove-vue-resource-from-issue.yml
new file mode 100644
index 00000000000..b2de1b0913a
--- /dev/null
+++ b/changelogs/unreleased/remove-vue-resource-from-issue.yml
@@ -0,0 +1,5 @@
+---
+title: Remove vue resource from issue
+merge_request: 32421
+author: Lee Tickett
+type: other
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 20b1020e025..6dcaefc05d5 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -431,6 +431,7 @@ production: &base
# key: config/registry.key
# path: shared/registry
# issuer: gitlab-issuer
+ # notification_secret: '' # only set it when you use Geo replication feature without built-in Registry
# Add notification settings if you plan to use Geo Replication for the registry
# notifications:
diff --git a/db/migrate/20190826100605_add_group_column_to_events.rb b/db/migrate/20190826100605_add_group_column_to_events.rb
new file mode 100644
index 00000000000..cd7b2b1d96a
--- /dev/null
+++ b/db/migrate/20190826100605_add_group_column_to_events.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddGroupColumnToEvents < ActiveRecord::Migration[5.2]
+ DOWNTIME = false
+
+ def change
+ add_reference :events, :group, index: true, foreign_key: { to_table: :namespaces, on_delete: :cascade }
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 0f535e4d674..f2d6f70217b 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -1310,9 +1310,11 @@ ActiveRecord::Schema.define(version: 2019_09_02_160015) do
t.datetime_with_timezone "updated_at", null: false
t.integer "action", limit: 2, null: false
t.string "target_type"
+ t.bigint "group_id"
t.index ["action"], name: "index_events_on_action"
t.index ["author_id", "project_id"], name: "index_events_on_author_id_and_project_id"
t.index ["created_at", "author_id"], name: "analytics_index_events_on_created_at_and_author_id"
+ t.index ["group_id"], name: "index_events_on_group_id"
t.index ["project_id", "created_at"], name: "index_events_on_project_id_and_created_at"
t.index ["project_id", "id"], name: "index_events_on_project_id_and_id"
t.index ["target_type", "target_id"], name: "index_events_on_target_type_and_target_id"
@@ -3838,6 +3840,7 @@ ActiveRecord::Schema.define(version: 2019_09_02_160015) do
add_foreign_key "epics", "users", column: "assignee_id", name: "fk_dccd3f98fc", on_delete: :nullify
add_foreign_key "epics", "users", column: "author_id", name: "fk_3654b61b03", on_delete: :cascade
add_foreign_key "epics", "users", column: "closed_by_id", name: "fk_aa5798e761", on_delete: :nullify
+ add_foreign_key "events", "namespaces", column: "group_id", on_delete: :cascade
add_foreign_key "events", "projects", on_delete: :cascade
add_foreign_key "events", "users", column: "author_id", name: "fk_edfd187b6f", on_delete: :cascade
add_foreign_key "fork_network_members", "fork_networks", on_delete: :cascade
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index 9b1efb610f8..4c43a434817 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -341,9 +341,10 @@ installations from source.
## `database_load_balancing.log`
-Introduced in GitLab 12.3 for observability of [Database Load
-Balancing](https://docs.gitlab.com/ee/administration/database_load_balancing.html)
-when enabled. This file lives in
-`/var/log/gitlab/gitlab-rails/database_load_balancing.log` for Omnibus GitLab
-packages or in `/home/git/gitlab/log/database_load_balancing.log` for
-installations from source.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/15442) in GitLab 12.3.
+
+This log is used for observability of [Database Load Balancing](database_load_balancing.md).
+It is stored at:
+
+- `/var/log/gitlab/gitlab-rails/database_load_balancing.log` for Omnibus GitLab packages.
+- `/home/git/gitlab/log/database_load_balancing.log` for installations from source.
diff --git a/doc/ci/environments.md b/doc/ci/environments.md
index f6c47a99712..c2d444cb1d6 100644
--- a/doc/ci/environments.md
+++ b/doc/ci/environments.md
@@ -675,9 +675,10 @@ fetch line:
fetch = +refs/environments/*:refs/remotes/origin/environments/*
```
-### Scoping environments with specs **(PREMIUM)**
+### Scoping environments with specs
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2112) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.4.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2112) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.4.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/30779) to Core in Gitlab 12.2.
You can limit the environment scope of a variable by
defining which environments it can be available for.
diff --git a/doc/ci/large_repositories/index.md b/doc/ci/large_repositories/index.md
index 29d649ad717..b1359537fca 100644
--- a/doc/ci/large_repositories/index.md
+++ b/doc/ci/large_repositories/index.md
@@ -84,7 +84,7 @@ Fork workflow from GitLab Runner's perspective is stored as a separate repositor
with separate worktree. That means that GitLab Runner cannot optimize the usage
of worktrees and you might have to instruct GitLab Runner to use that.
-In such cases, ideally you want to make the GitLab Runner executor be used only used only
+In such cases, ideally you want to make the GitLab Runner executor be used only
for the given project and not shared across different projects to make this
process more efficient.
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 5a15b907da0..438b7c03b51 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -401,7 +401,7 @@ Once you set them, they will be available for all subsequent pipelines.
You can limit the environment scope of a variable by
[defining which environments][envs] it can be available for.
-To learn more about about scoping environments, see [Scoping environments with specs](../environments.md#scoping-environments-with-specs-premium).
+To learn more about about scoping environments, see [Scoping environments with specs](../environments.md#scoping-environments-with-specs).
### Deployment environment variables
diff --git a/doc/development/database_review.md b/doc/development/database_review.md
index 367a481ee11..157c64b514c 100644
--- a/doc/development/database_review.md
+++ b/doc/development/database_review.md
@@ -38,6 +38,7 @@ A Merge Request author's role is to:
- If database review is needed, add the ~database label.
- Use the [database changes](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab/merge_request_templates/Database%20changes.md)
merge request template, or include the appropriate items in the MR description.
+- [Prepare the merge request for a database review](#how-to-prepare-the-merge-request-for-a-database-review).
A database **reviewer**'s role is to:
@@ -68,7 +69,7 @@ make sure you have applied the ~database label and rerun the
`danger-review` CI job, or pick someone from the
[`@gl-database` team](https://gitlab.com/groups/gl-database/-/group_members).
-### How to prepare for speedy database reviews
+### How to prepare the merge request for a database review
In order to make reviewing easier and therefore faster, please consider preparing a comment
and details for a database reviewer:
diff --git a/doc/user/instance/clusters/index.md b/doc/user/instance/clusters/index.md
index f557dcf4b3c..cb1bfc69826 100644
--- a/doc/user/instance/clusters/index.md
+++ b/doc/user/instance/clusters/index.md
@@ -19,4 +19,4 @@ GitLab will try match to clusters in the following order:
- Instance level
To be selected, the cluster must be enabled and
-match the [environment selector](../../../ci/environments.md#scoping-environments-with-specs-premium).
+match the [environment selector](../../../ci/environments.md#scoping-environments-with-specs).
diff --git a/doc/user/project/operations/feature_flags.md b/doc/user/project/operations/feature_flags.md
index 28248ad3696..39ca1bd0c77 100644
--- a/doc/user/project/operations/feature_flags.md
+++ b/doc/user/project/operations/feature_flags.md
@@ -63,15 +63,15 @@ For example, you may not want to enable a feature flag on production until your
first confirmed that the feature is working correctly on testing environments.
To handle these situations, you can enable a feature flag on a particular environment
-with [Environment specs](../../../ci/environments.md#scoping-environments-with-specs-premium).
+with [Environment specs](../../../ci/environments.md#scoping-environments-with-specs).
You can define multiple specs per flag so that you can control your feature flag more granularly.
To define specs for each environment:
1. Navigate to your project's **Operations > Feature Flags**.
1. Click on the **New Feature Flag** button or edit an existing flag.
-1. Set the status of the default [spec](../../../ci/environments.md#scoping-environments-with-specs-premium) (`*`). Choose a rollout strategy. This status and rollout strategy combination will be used for _all_ environments.
-1. If you want to enable/disable the feature on a specific environment, create a new [spec](../../../ci/environments.md#scoping-environments-with-specs-premium) and type the environment name.
+1. Set the status of the default [spec](../../../ci/environments.md#scoping-environments-with-specs) (`*`). Choose a rollout strategy. This status and rollout strategy combination will be used for _all_ environments.
+1. If you want to enable/disable the feature on a specific environment, create a new [spec](../../../ci/environments.md#scoping-environments-with-specs) and type the environment name.
1. Set the status and rollout strategy of the additional spec. This status and rollout strategy combination takes precedence over the default spec since we always use the most specific match available.
1. Click **Create feature flag** or **Update feature flag**.
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 219ed45eff6..aa6a67d817a 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -118,7 +118,7 @@ module API
mount ::API::GroupContainerRepositories
mount ::API::GroupVariables
mount ::API::ImportGithub
- mount ::API::Internal
+ mount ::API::Internal::Base
mount ::API::Issues
mount ::API::JobArtifacts
mount ::API::Jobs
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
deleted file mode 100644
index 088ea5bd79a..00000000000
--- a/lib/api/internal.rb
+++ /dev/null
@@ -1,294 +0,0 @@
-# frozen_string_literal: true
-
-module API
- # Internal access API
- class Internal < Grape::API
- before { authenticate_by_gitlab_shell_token! }
-
- helpers ::API::Helpers::InternalHelpers
- helpers ::Gitlab::Identifier
-
- UNKNOWN_CHECK_RESULT_ERROR = 'Unknown check result'.freeze
-
- helpers do
- def response_with_status(code: 200, success: true, message: nil, **extra_options)
- status code
- { status: success, message: message }.merge(extra_options).compact
- end
-
- def lfs_authentication_url(project)
- # This is a separate method so that EE can alter its behaviour more
- # easily.
- project.http_url_to_repo
- end
- end
-
- namespace 'internal' do
- # Check if git command is allowed for project
- #
- # Params:
- # key_id - ssh key id for Git over SSH
- # user_id - user id for Git over HTTP or over SSH in keyless SSH CERT mode
- # username - user name for Git over SSH in keyless SSH cert mode
- # protocol - Git access protocol being used, e.g. HTTP or SSH
- # project - project full_path (not path on disk)
- # action - git action (git-upload-pack or git-receive-pack)
- # changes - changes as "oldrev newrev ref", see Gitlab::ChangesList
- # rubocop: disable CodeReuse/ActiveRecord
- post "/allowed" do
- # Stores some Git-specific env thread-safely
- env = parse_env
- Gitlab::Git::HookEnv.set(gl_repository, env) if project
-
- actor =
- if params[:key_id]
- Key.find_by(id: params[:key_id])
- elsif params[:user_id]
- User.find_by(id: params[:user_id])
- elsif params[:username]
- UserFinder.new(params[:username]).find_by_username
- end
-
- protocol = params[:protocol]
-
- actor.update_last_used_at if actor.is_a?(Key)
- user =
- if actor.is_a?(Key)
- actor.user
- else
- actor
- end
-
- access_checker_klass = repo_type.access_checker_class
- access_checker = access_checker_klass.new(actor, project,
- protocol, authentication_abilities: ssh_authentication_abilities,
- namespace_path: namespace_path, project_path: project_path,
- redirected_path: redirected_path)
-
- check_result = begin
- result = access_checker.check(params[:action], params[:changes])
- @project ||= access_checker.project
- result
- rescue Gitlab::GitAccess::UnauthorizedError => e
- break response_with_status(code: 401, success: false, message: e.message)
- rescue Gitlab::GitAccess::TimeoutError => e
- break response_with_status(code: 503, success: false, message: e.message)
- rescue Gitlab::GitAccess::NotFoundError => e
- break response_with_status(code: 404, success: false, message: e.message)
- end
-
- log_user_activity(actor)
-
- case check_result
- when ::Gitlab::GitAccessResult::Success
- payload = {
- gl_repository: gl_repository,
- gl_project_path: gl_project_path,
- gl_id: Gitlab::GlId.gl_id(user),
- gl_username: user&.username,
- git_config_options: [],
- gitaly: gitaly_payload(params[:action]),
- gl_console_messages: check_result.console_messages
- }
-
- # Custom option for git-receive-pack command
- receive_max_input_size = Gitlab::CurrentSettings.receive_max_input_size.to_i
- if receive_max_input_size > 0
- payload[:git_config_options] << "receive.maxInputSize=#{receive_max_input_size.megabytes}"
- end
-
- response_with_status(**payload)
- when ::Gitlab::GitAccessResult::CustomAction
- response_with_status(code: 300, message: check_result.message, payload: check_result.payload)
- else
- response_with_status(code: 500, success: false, message: UNKNOWN_CHECK_RESULT_ERROR)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- # rubocop: disable CodeReuse/ActiveRecord
- post "/lfs_authenticate" do
- status 200
-
- if params[:key_id]
- actor = Key.find(params[:key_id])
- actor.update_last_used_at
- elsif params[:user_id]
- actor = User.find_by(id: params[:user_id])
- raise ActiveRecord::RecordNotFound.new("No such user id!") unless actor
- else
- raise ActiveRecord::RecordNotFound.new("No key_id or user_id passed!")
- end
-
- Gitlab::LfsToken
- .new(actor)
- .authentication_payload(lfs_authentication_url(project))
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- get "/merge_request_urls" do
- merge_request_urls
- end
-
- #
- # Get a ssh key using the fingerprint
- #
- # rubocop: disable CodeReuse/ActiveRecord
- get "/authorized_keys" do
- fingerprint = params.fetch(:fingerprint) do
- Gitlab::InsecureKeyFingerprint.new(params.fetch(:key)).fingerprint
- end
- key = Key.find_by(fingerprint: fingerprint)
- not_found!("Key") if key.nil?
- present key, with: Entities::SSHKey
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- #
- # Discover user by ssh key, user id or username
- #
- # rubocop: disable CodeReuse/ActiveRecord
- get "/discover" do
- if params[:key_id]
- key = Key.find(params[:key_id])
- user = key.user
- elsif params[:user_id]
- user = User.find_by(id: params[:user_id])
- elsif params[:username]
- user = UserFinder.new(params[:username]).find_by_username
- end
-
- present user, with: Entities::UserSafe
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- get "/check" do
- {
- api_version: API.version,
- gitlab_version: Gitlab::VERSION,
- gitlab_rev: Gitlab.revision,
- redis: redis_ping
- }
- end
-
- get "/broadcast_messages" do
- if messages = BroadcastMessage.current
- present messages, with: Entities::BroadcastMessage
- else
- []
- end
- end
-
- get "/broadcast_message" do
- if message = BroadcastMessage.current&.last
- present message, with: Entities::BroadcastMessage
- else
- {}
- end
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- post '/two_factor_recovery_codes' do
- status 200
-
- if params[:key_id]
- key = Key.find_by(id: params[:key_id])
-
- if key
- key.update_last_used_at
- else
- break { 'success' => false, 'message' => 'Could not find the given key' }
- end
-
- if key.is_a?(DeployKey)
- break { success: false, message: 'Deploy keys cannot be used to retrieve recovery codes' }
- end
-
- user = key.user
-
- unless user
- break { success: false, message: 'Could not find a user for the given key' }
- end
- elsif params[:user_id]
- user = User.find_by(id: params[:user_id])
-
- unless user
- break { success: false, message: 'Could not find the given user' }
- end
- end
-
- unless user.two_factor_enabled?
- break { success: false, message: 'Two-factor authentication is not enabled for this user' }
- end
-
- codes = nil
-
- ::Users::UpdateService.new(current_user, user: user).execute! do |user|
- codes = user.generate_otp_backup_codes!
- end
-
- { success: true, recovery_codes: codes }
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- post '/pre_receive' do
- status 200
-
- reference_counter_increased = Gitlab::ReferenceCounter.new(params[:gl_repository]).increase
-
- { reference_counter_increased: reference_counter_increased }
- end
-
- post "/notify_post_receive" do
- status 200
-
- # TODO: Re-enable when Gitaly is processing the post-receive notification
- # return unless Gitlab::GitalyClient.enabled?
- #
- # begin
- # repository = wiki? ? project.wiki.repository : project.repository
- # Gitlab::GitalyClient::NotificationService.new(repository.raw_repository).post_receive
- # rescue GRPC::Unavailable => e
- # render_api_error!(e, 500)
- # end
- end
-
- post '/post_receive' do
- status 200
-
- response = Gitlab::InternalPostReceive::Response.new
- user = identify(params[:identifier])
- project = Gitlab::GlRepository.parse(params[:gl_repository]).first
- push_options = Gitlab::PushOptions.new(params[:push_options])
-
- response.reference_counter_decreased = Gitlab::ReferenceCounter.new(params[:gl_repository]).decrease
-
- PostReceive.perform_async(params[:gl_repository], params[:identifier],
- params[:changes], push_options.as_json)
-
- mr_options = push_options.get(:merge_request)
- if mr_options.present?
- message = process_mr_push_options(mr_options, project, user, params[:changes])
- response.add_alert_message(message)
- end
-
- broadcast_message = BroadcastMessage.current&.last&.message
- response.add_alert_message(broadcast_message)
-
- response.add_merge_request_urls(merge_request_urls)
-
- # A user is not guaranteed to be returned; an orphaned write deploy
- # key could be used
- if user
- redirect_message = Gitlab::Checks::ProjectMoved.fetch_message(user.id, project.id)
- project_created_message = Gitlab::Checks::ProjectCreated.fetch_message(user.id, project.id)
-
- response.add_basic_message(redirect_message)
- response.add_basic_message(project_created_message)
- end
-
- present response, with: Entities::InternalPostReceive::Response
- end
- end
- end
-end
diff --git a/lib/api/internal/base.rb b/lib/api/internal/base.rb
new file mode 100644
index 00000000000..622032b8355
--- /dev/null
+++ b/lib/api/internal/base.rb
@@ -0,0 +1,296 @@
+# frozen_string_literal: true
+
+module API
+ # Internal access API
+ module Internal
+ class Base < Grape::API
+ before { authenticate_by_gitlab_shell_token! }
+
+ helpers ::API::Helpers::InternalHelpers
+ helpers ::Gitlab::Identifier
+
+ UNKNOWN_CHECK_RESULT_ERROR = 'Unknown check result'.freeze
+
+ helpers do
+ def response_with_status(code: 200, success: true, message: nil, **extra_options)
+ status code
+ { status: success, message: message }.merge(extra_options).compact
+ end
+
+ def lfs_authentication_url(project)
+ # This is a separate method so that EE can alter its behaviour more
+ # easily.
+ project.http_url_to_repo
+ end
+ end
+
+ namespace 'internal' do
+ # Check if git command is allowed for project
+ #
+ # Params:
+ # key_id - ssh key id for Git over SSH
+ # user_id - user id for Git over HTTP or over SSH in keyless SSH CERT mode
+ # username - user name for Git over SSH in keyless SSH cert mode
+ # protocol - Git access protocol being used, e.g. HTTP or SSH
+ # project - project full_path (not path on disk)
+ # action - git action (git-upload-pack or git-receive-pack)
+ # changes - changes as "oldrev newrev ref", see Gitlab::ChangesList
+ # rubocop: disable CodeReuse/ActiveRecord
+ post "/allowed" do
+ # Stores some Git-specific env thread-safely
+ env = parse_env
+ Gitlab::Git::HookEnv.set(gl_repository, env) if project
+
+ actor =
+ if params[:key_id]
+ Key.find_by(id: params[:key_id])
+ elsif params[:user_id]
+ User.find_by(id: params[:user_id])
+ elsif params[:username]
+ UserFinder.new(params[:username]).find_by_username
+ end
+
+ protocol = params[:protocol]
+
+ actor.update_last_used_at if actor.is_a?(Key)
+ user =
+ if actor.is_a?(Key)
+ actor.user
+ else
+ actor
+ end
+
+ access_checker_klass = repo_type.access_checker_class
+ access_checker = access_checker_klass.new(actor, project,
+ protocol, authentication_abilities: ssh_authentication_abilities,
+ namespace_path: namespace_path, project_path: project_path,
+ redirected_path: redirected_path)
+
+ check_result = begin
+ result = access_checker.check(params[:action], params[:changes])
+ @project ||= access_checker.project
+ result
+ rescue Gitlab::GitAccess::UnauthorizedError => e
+ break response_with_status(code: 401, success: false, message: e.message)
+ rescue Gitlab::GitAccess::TimeoutError => e
+ break response_with_status(code: 503, success: false, message: e.message)
+ rescue Gitlab::GitAccess::NotFoundError => e
+ break response_with_status(code: 404, success: false, message: e.message)
+ end
+
+ log_user_activity(actor)
+
+ case check_result
+ when ::Gitlab::GitAccessResult::Success
+ payload = {
+ gl_repository: gl_repository,
+ gl_project_path: gl_project_path,
+ gl_id: Gitlab::GlId.gl_id(user),
+ gl_username: user&.username,
+ git_config_options: [],
+ gitaly: gitaly_payload(params[:action]),
+ gl_console_messages: check_result.console_messages
+ }
+
+ # Custom option for git-receive-pack command
+ receive_max_input_size = Gitlab::CurrentSettings.receive_max_input_size.to_i
+ if receive_max_input_size > 0
+ payload[:git_config_options] << "receive.maxInputSize=#{receive_max_input_size.megabytes}"
+ end
+
+ response_with_status(**payload)
+ when ::Gitlab::GitAccessResult::CustomAction
+ response_with_status(code: 300, message: check_result.message, payload: check_result.payload)
+ else
+ response_with_status(code: 500, success: false, message: UNKNOWN_CHECK_RESULT_ERROR)
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ post "/lfs_authenticate" do
+ status 200
+
+ if params[:key_id]
+ actor = Key.find(params[:key_id])
+ actor.update_last_used_at
+ elsif params[:user_id]
+ actor = User.find_by(id: params[:user_id])
+ raise ActiveRecord::RecordNotFound.new("No such user id!") unless actor
+ else
+ raise ActiveRecord::RecordNotFound.new("No key_id or user_id passed!")
+ end
+
+ Gitlab::LfsToken
+ .new(actor)
+ .authentication_payload(lfs_authentication_url(project))
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ get "/merge_request_urls" do
+ merge_request_urls
+ end
+
+ #
+ # Get a ssh key using the fingerprint
+ #
+ # rubocop: disable CodeReuse/ActiveRecord
+ get "/authorized_keys" do
+ fingerprint = params.fetch(:fingerprint) do
+ Gitlab::InsecureKeyFingerprint.new(params.fetch(:key)).fingerprint
+ end
+ key = Key.find_by(fingerprint: fingerprint)
+ not_found!("Key") if key.nil?
+ present key, with: Entities::SSHKey
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ #
+ # Discover user by ssh key, user id or username
+ #
+ # rubocop: disable CodeReuse/ActiveRecord
+ get "/discover" do
+ if params[:key_id]
+ key = Key.find(params[:key_id])
+ user = key.user
+ elsif params[:user_id]
+ user = User.find_by(id: params[:user_id])
+ elsif params[:username]
+ user = UserFinder.new(params[:username]).find_by_username
+ end
+
+ present user, with: Entities::UserSafe
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ get "/check" do
+ {
+ api_version: API.version,
+ gitlab_version: Gitlab::VERSION,
+ gitlab_rev: Gitlab.revision,
+ redis: redis_ping
+ }
+ end
+
+ get "/broadcast_messages" do
+ if messages = BroadcastMessage.current
+ present messages, with: Entities::BroadcastMessage
+ else
+ []
+ end
+ end
+
+ get "/broadcast_message" do
+ if message = BroadcastMessage.current&.last
+ present message, with: Entities::BroadcastMessage
+ else
+ {}
+ end
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ post '/two_factor_recovery_codes' do
+ status 200
+
+ if params[:key_id]
+ key = Key.find_by(id: params[:key_id])
+
+ if key
+ key.update_last_used_at
+ else
+ break { 'success' => false, 'message' => 'Could not find the given key' }
+ end
+
+ if key.is_a?(DeployKey)
+ break { success: false, message: 'Deploy keys cannot be used to retrieve recovery codes' }
+ end
+
+ user = key.user
+
+ unless user
+ break { success: false, message: 'Could not find a user for the given key' }
+ end
+ elsif params[:user_id]
+ user = User.find_by(id: params[:user_id])
+
+ unless user
+ break { success: false, message: 'Could not find the given user' }
+ end
+ end
+
+ unless user.two_factor_enabled?
+ break { success: false, message: 'Two-factor authentication is not enabled for this user' }
+ end
+
+ codes = nil
+
+ ::Users::UpdateService.new(current_user, user: user).execute! do |user|
+ codes = user.generate_otp_backup_codes!
+ end
+
+ { success: true, recovery_codes: codes }
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ post '/pre_receive' do
+ status 200
+
+ reference_counter_increased = Gitlab::ReferenceCounter.new(params[:gl_repository]).increase
+
+ { reference_counter_increased: reference_counter_increased }
+ end
+
+ post "/notify_post_receive" do
+ status 200
+
+ # TODO: Re-enable when Gitaly is processing the post-receive notification
+ # return unless Gitlab::GitalyClient.enabled?
+ #
+ # begin
+ # repository = wiki? ? project.wiki.repository : project.repository
+ # Gitlab::GitalyClient::NotificationService.new(repository.raw_repository).post_receive
+ # rescue GRPC::Unavailable => e
+ # render_api_error!(e, 500)
+ # end
+ end
+
+ post '/post_receive' do
+ status 200
+
+ response = Gitlab::InternalPostReceive::Response.new
+ user = identify(params[:identifier])
+ project = Gitlab::GlRepository.parse(params[:gl_repository]).first
+ push_options = Gitlab::PushOptions.new(params[:push_options])
+
+ response.reference_counter_decreased = Gitlab::ReferenceCounter.new(params[:gl_repository]).decrease
+
+ PostReceive.perform_async(params[:gl_repository], params[:identifier],
+ params[:changes], push_options.as_json)
+
+ mr_options = push_options.get(:merge_request)
+ if mr_options.present?
+ message = process_mr_push_options(mr_options, project, user, params[:changes])
+ response.add_alert_message(message)
+ end
+
+ broadcast_message = BroadcastMessage.current&.last&.message
+ response.add_alert_message(broadcast_message)
+
+ response.add_merge_request_urls(merge_request_urls)
+
+ # A user is not guaranteed to be returned; an orphaned write deploy
+ # key could be used
+ if user
+ redirect_message = Gitlab::Checks::ProjectMoved.fetch_message(user.id, project.id)
+ project_created_message = Gitlab::Checks::ProjectCreated.fetch_message(user.id, project.id)
+
+ response.add_basic_message(redirect_message)
+ response.add_basic_message(project_created_message)
+ end
+
+ present response, with: Entities::InternalPostReceive::Response
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/release/links.rb b/lib/api/release/links.rb
index 5d1b40e3bff..def36dc8529 100644
--- a/lib/api/release/links.rb
+++ b/lib/api/release/links.rb
@@ -5,7 +5,7 @@ module API
class Links < Grape::API
include PaginationParams
- RELEASE_ENDPOINT_REQUIREMETS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS
+ RELEASE_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS
.merge(tag_name: API::NO_SLASH_URL_PART_REGEX)
before { authorize! :read_release, user_project }
@@ -17,7 +17,7 @@ module API
params do
requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
end
- resource 'releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMETS do
+ resource 'releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMENTS do
resource :assets do
desc 'Get a list of links of a release' do
detail 'This feature was introduced in GitLab 11.7.'
diff --git a/lib/api/releases.rb b/lib/api/releases.rb
index 11a9a085068..5a31581c4da 100644
--- a/lib/api/releases.rb
+++ b/lib/api/releases.rb
@@ -4,7 +4,7 @@ module API
class Releases < Grape::API
include PaginationParams
- RELEASE_ENDPOINT_REQUIREMETS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS
+ RELEASE_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS
.merge(tag_name: API::NO_SLASH_URL_PART_REGEX)
before { authorize_read_releases! }
@@ -33,7 +33,7 @@ module API
params do
requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
end
- get ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMETS do
+ get ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMENTS do
authorize_download_code!
present release, with: Entities::Release, current_user: current_user
@@ -82,7 +82,7 @@ module API
optional :released_at, type: DateTime, desc: 'The date when the release will be/was ready.'
optional :milestone, type: String, desc: 'The title of the related milestone'
end
- put ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMETS do
+ put ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMENTS do
authorize_update_release!
result = ::Releases::UpdateService
@@ -103,7 +103,7 @@ module API
params do
requires :tag_name, type: String, desc: 'The name of the tag', as: :tag
end
- delete ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMETS do
+ delete ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMENTS do
authorize_destroy_release!
result = ::Releases::DestroyService
diff --git a/lib/gitlab/git/diff_collection.rb b/lib/gitlab/git/diff_collection.rb
index 5c70cb6c66c..cb9154cb1e8 100644
--- a/lib/gitlab/git/diff_collection.rb
+++ b/lib/gitlab/git/diff_collection.rb
@@ -81,6 +81,12 @@ module Gitlab
end
end
+ def line_count
+ populate!
+
+ @line_count
+ end
+
def decorate!
collection = each_with_index do |element, i|
@array[i] = yield(element)
diff --git a/lib/gitlab/jwt_authenticatable.rb b/lib/gitlab/jwt_authenticatable.rb
new file mode 100644
index 00000000000..1270a148e8d
--- /dev/null
+++ b/lib/gitlab/jwt_authenticatable.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module JwtAuthenticatable
+ # Supposedly the effective key size for HMAC-SHA256 is 256 bits, i.e. 32
+ # bytes https://tools.ietf.org/html/rfc4868#section-2.6
+ SECRET_LENGTH = 32
+
+ def self.included(base)
+ base.extend(ClassMethods)
+ end
+
+ module ClassMethods
+ include Gitlab::Utils::StrongMemoize
+
+ def decode_jwt_for_issuer(issuer, encoded_message)
+ JWT.decode(
+ encoded_message,
+ secret,
+ true,
+ { iss: issuer, verify_iss: true, algorithm: 'HS256' }
+ )
+ end
+
+ def secret
+ strong_memoize(:secret) do
+ Base64.strict_decode64(File.read(secret_path).chomp).tap do |bytes|
+ raise "#{secret_path} does not contain #{SECRET_LENGTH} bytes" if bytes.length != SECRET_LENGTH
+ end
+ end
+ end
+
+ def write_secret
+ bytes = SecureRandom.random_bytes(SECRET_LENGTH)
+ File.open(secret_path, 'w:BINARY', 0600) do |f|
+ f.chmod(0600) # If the file already existed, the '0600' passed to 'open' above was a no-op.
+ f.write(Base64.strict_encode64(bytes))
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb
index 29087d26007..139ec6e384a 100644
--- a/lib/gitlab/workhorse.rb
+++ b/lib/gitlab/workhorse.rb
@@ -15,9 +15,7 @@ module Gitlab
ALLOWED_GIT_HTTP_ACTIONS = %w[git_receive_pack git_upload_pack info_refs].freeze
DETECT_HEADER = 'Gitlab-Workhorse-Detect-Content-Type'.freeze
- # Supposedly the effective key size for HMAC-SHA256 is 256 bits, i.e. 32
- # bytes https://tools.ietf.org/html/rfc4868#section-2.6
- SECRET_LENGTH = 32
+ include JwtAuthenticatable
class << self
def git_http_ok(repository, repo_type, user, action, show_all_refs: false)
@@ -187,34 +185,12 @@ module Gitlab
path.readable? ? path.read.chomp : 'unknown'
end
- def secret
- @secret ||= begin
- bytes = Base64.strict_decode64(File.read(secret_path).chomp)
- raise "#{secret_path} does not contain #{SECRET_LENGTH} bytes" if bytes.length != SECRET_LENGTH
-
- bytes
- end
- end
-
- def write_secret
- bytes = SecureRandom.random_bytes(SECRET_LENGTH)
- File.open(secret_path, 'w:BINARY', 0600) do |f|
- f.chmod(0600) # If the file already existed, the '0600' passed to 'open' above was a no-op.
- f.write(Base64.strict_encode64(bytes))
- end
- end
-
def verify_api_request!(request_headers)
decode_jwt(request_headers[INTERNAL_API_REQUEST_HEADER])
end
def decode_jwt(encoded_message)
- JWT.decode(
- encoded_message,
- secret,
- true,
- { iss: 'gitlab-workhorse', verify_iss: true, algorithm: 'HS256' }
- )
+ decode_jwt_for_issuer('gitlab-workhorse', encoded_message)
end
def secret_path
diff --git a/lib/peek/views/active_record.rb b/lib/peek/views/active_record.rb
index bbc9f11e90f..1bb3ddb964a 100644
--- a/lib/peek/views/active_record.rb
+++ b/lib/peek/views/active_record.rb
@@ -5,15 +5,15 @@ module Peek
class ActiveRecord < DetailedView
DEFAULT_THRESHOLDS = {
calls: 100,
- duration: 3,
- individual_call: 1
+ duration: 3000,
+ individual_call: 1000
}.freeze
THRESHOLDS = {
production: {
calls: 100,
- duration: 15,
- individual_call: 5
+ duration: 15000,
+ individual_call: 5000
}
}.freeze
diff --git a/lib/peek/views/gitaly.rb b/lib/peek/views/gitaly.rb
index f669feae254..7dc00b16cc0 100644
--- a/lib/peek/views/gitaly.rb
+++ b/lib/peek/views/gitaly.rb
@@ -5,15 +5,15 @@ module Peek
class Gitaly < DetailedView
DEFAULT_THRESHOLDS = {
calls: 30,
- duration: 1,
- individual_call: 0.5
+ duration: 1000,
+ individual_call: 500
}.freeze
THRESHOLDS = {
production: {
calls: 30,
- duration: 1,
- individual_call: 0.5
+ duration: 1000,
+ individual_call: 500
}
}.freeze
@@ -24,7 +24,7 @@ module Peek
private
def duration
- ::Gitlab::GitalyClient.query_time
+ ::Gitlab::GitalyClient.query_time * 1000
end
def calls
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index a5619079988..629daccf006 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -1960,7 +1960,10 @@ msgstr ""
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
msgstr ""
-msgid "CICD|You must add a %{kubernetes_cluster_start}Kubernetes cluster integration%{kubernetes_cluster_end} to this project with a domain in order for your deployment strategy to work correctly."
+msgid "CICD|You must add a %{base_domain_link_start}base domain%{link_end} to your %{kubernetes_cluster_link_start}Kubernetes cluster%{link_end} in order for your deployment strategy to work."
+msgstr ""
+
+msgid "CICD|You must add a %{kubernetes_cluster_link_start}Kubernetes cluster integration%{link_end} to this project with a domain in order for your deployment strategy to work correctly."
msgstr ""
msgid "CICD|group enabled"
@@ -10879,6 +10882,9 @@ msgstr ""
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
+msgid "Star labels to start sorting by priority"
+msgstr ""
+
msgid "Star toggle failed. Try again later."
msgstr ""
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
index fc5b57451de..a9549171b54 100755
--- a/scripts/review_apps/review-apps.sh
+++ b/scripts/review_apps/review-apps.sh
@@ -36,7 +36,7 @@ function previous_deploy_failed() {
return $status
}
-function delete() {
+function delete_release() {
if [ -z "$CI_ENVIRONMENT_SLUG" ]; then
echoerr "No release given, aborting the delete!"
return
@@ -164,7 +164,7 @@ function create_application_secret() {
function download_chart() {
echoinfo "Downloading the GitLab chart..." true
- curl -o gitlab.tar.bz2 "https://gitlab.com/gitlab-org/charts/gitlab/-/archive/${GITLAB_HELM_CHART_REF}/gitlab-${GITLAB_HELM_CHART_REF}.tar.bz2"
+ curl --location -o gitlab.tar.bz2 "https://gitlab.com/gitlab-org/charts/gitlab/-/archive/${GITLAB_HELM_CHART_REF}/gitlab-${GITLAB_HELM_CHART_REF}.tar.bz2"
tar -xjf gitlab.tar.bz2
cd "gitlab-${GITLAB_HELM_CHART_REF}"
@@ -193,7 +193,8 @@ function deploy() {
HELM_CMD=$(cat << EOF
helm upgrade --install \
- --atomic \
+ --force \
+ --wait \
--timeout 900 \
--set releaseOverride="$CI_ENVIRONMENT_SLUG" \
--set global.appConfig.enableUsagePing=false \
diff --git a/spec/javascripts/boards/issue_spec.js b/spec/javascripts/boards/issue_spec.js
index bb7abe52eae..05e6ea1394d 100644
--- a/spec/javascripts/boards/issue_spec.js
+++ b/spec/javascripts/boards/issue_spec.js
@@ -1,6 +1,6 @@
/* global ListIssue */
-import Vue from 'vue';
+import axios from '~/lib/utils/axios_utils';
import '~/boards/models/label';
import '~/boards/models/assignee';
import '~/boards/models/issue';
@@ -175,7 +175,7 @@ describe('Issue model', () => {
describe('update', () => {
it('passes assignee ids when there are assignees', done => {
- spyOn(Vue.http, 'patch').and.callFake((url, data) => {
+ spyOn(axios, 'patch').and.callFake((url, data) => {
expect(data.issue.assignee_ids).toEqual([1]);
done();
return Promise.resolve();
@@ -185,7 +185,7 @@ describe('Issue model', () => {
});
it('passes assignee ids of [0] when there are no assignees', done => {
- spyOn(Vue.http, 'patch').and.callFake((url, data) => {
+ spyOn(axios, 'patch').and.callFake((url, data) => {
expect(data.issue.assignee_ids).toEqual([0]);
done();
return Promise.resolve();
diff --git a/spec/javascripts/groups/components/app_spec.js b/spec/javascripts/groups/components/app_spec.js
index 31873311e16..23b2564d3f9 100644
--- a/spec/javascripts/groups/components/app_spec.js
+++ b/spec/javascripts/groups/components/app_spec.js
@@ -1,3 +1,4 @@
+import '~/flash';
import $ from 'jquery';
import Vue from 'vue';
@@ -333,7 +334,7 @@ describe('AppComponent', () => {
it('hides modal confirmation leave group and remove group item from tree', done => {
const notice = `You left the "${childGroupItem.fullName}" group.`;
- spyOn(vm.service, 'leaveGroup').and.returnValue(returnServicePromise({ notice }));
+ spyOn(vm.service, 'leaveGroup').and.returnValue(Promise.resolve({ data: { notice } }));
spyOn(vm.store, 'removeGroup').and.callThrough();
spyOn(window, 'Flash');
spyOn($, 'scrollTo');
diff --git a/spec/javascripts/groups/service/groups_service_spec.js b/spec/javascripts/groups/service/groups_service_spec.js
index 339e5131615..45db962a1ef 100644
--- a/spec/javascripts/groups/service/groups_service_spec.js
+++ b/spec/javascripts/groups/service/groups_service_spec.js
@@ -1,11 +1,8 @@
-import Vue from 'vue';
-import VueResource from 'vue-resource';
+import axios from '~/lib/utils/axios_utils';
import GroupsService from '~/groups/service/groups_service';
import { mockEndpoint, mockParentGroupItem } from '../mock_data';
-Vue.use(VueResource);
-
describe('GroupsService', () => {
let service;
@@ -15,8 +12,8 @@ describe('GroupsService', () => {
describe('getGroups', () => {
it('should return promise for `GET` request on provided endpoint', () => {
- spyOn(service.groups, 'get').and.stub();
- const queryParams = {
+ spyOn(axios, 'get').and.stub();
+ const params = {
page: 2,
filter: 'git',
sort: 'created_asc',
@@ -25,21 +22,21 @@ describe('GroupsService', () => {
service.getGroups(55, 2, 'git', 'created_asc', true);
- expect(service.groups.get).toHaveBeenCalledWith({ parent_id: 55 });
+ expect(axios.get).toHaveBeenCalledWith(mockEndpoint, { params: { parent_id: 55 } });
service.getGroups(null, 2, 'git', 'created_asc', true);
- expect(service.groups.get).toHaveBeenCalledWith(queryParams);
+ expect(axios.get).toHaveBeenCalledWith(mockEndpoint, { params });
});
});
describe('leaveGroup', () => {
it('should return promise for `DELETE` request on provided endpoint', () => {
- spyOn(Vue.http, 'delete').and.stub();
+ spyOn(axios, 'delete').and.stub();
service.leaveGroup(mockParentGroupItem.leavePath);
- expect(Vue.http.delete).toHaveBeenCalledWith(mockParentGroupItem.leavePath);
+ expect(axios.delete).toHaveBeenCalledWith(mockParentGroupItem.leavePath);
});
});
});
diff --git a/spec/lib/gitlab/favicon_spec.rb b/spec/lib/gitlab/favicon_spec.rb
index 23de12f12f8..63c26e29d73 100644
--- a/spec/lib/gitlab/favicon_spec.rb
+++ b/spec/lib/gitlab/favicon_spec.rb
@@ -1,14 +1,16 @@
require 'spec_helper'
RSpec.describe Gitlab::Favicon, :request_store do
+ include RailsHelpers
+
describe '.main' do
it 'defaults to favicon.png' do
- allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('production'))
+ stub_rails_env('production')
expect(described_class.main).to match_asset_path '/assets/favicon.png'
end
it 'has blue favicon for development', unless: Gitlab.ee? do
- allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('development'))
+ stub_rails_env('development')
expect(described_class.main).to match_asset_path '/assets/favicon-blue.png'
end
@@ -24,7 +26,7 @@ RSpec.describe Gitlab::Favicon, :request_store do
context 'asset host' do
before do
- allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('production'))
+ stub_rails_env('production')
end
it 'returns a relative url when the asset host is not configured' do
diff --git a/spec/lib/gitlab/git/diff_collection_spec.rb b/spec/lib/gitlab/git/diff_collection_spec.rb
index 81658874be7..be6ab0c1200 100644
--- a/spec/lib/gitlab/git/diff_collection_spec.rb
+++ b/spec/lib/gitlab/git/diff_collection_spec.rb
@@ -74,6 +74,11 @@ describe Gitlab::Git::DiffCollection, :seed_helper do
end
end
+ describe '#line_count' do
+ subject { super().line_count }
+ it { is_expected.to eq file_count * line_count }
+ end
+
context 'when limiting is disabled' do
let(:limits) { false }
@@ -100,6 +105,11 @@ describe Gitlab::Git::DiffCollection, :seed_helper do
expect(subject.size).to eq(3)
end
end
+
+ describe '#line_count' do
+ subject { super().line_count }
+ it { is_expected.to eq file_count * line_count }
+ end
end
end
@@ -120,6 +130,12 @@ describe Gitlab::Git::DiffCollection, :seed_helper do
subject { super().real_size }
it { is_expected.to eq('0+') }
end
+
+ describe '#line_count' do
+ subject { super().line_count }
+ it { is_expected.to eq 1000 }
+ end
+
it { expect(subject.size).to eq(0) }
context 'when limiting is disabled' do
@@ -139,6 +155,12 @@ describe Gitlab::Git::DiffCollection, :seed_helper do
subject { super().real_size }
it { is_expected.to eq('3') }
end
+
+ describe '#line_count' do
+ subject { super().line_count }
+ it { is_expected.to eq file_count * line_count }
+ end
+
it { expect(subject.size).to eq(3) }
end
end
@@ -164,6 +186,12 @@ describe Gitlab::Git::DiffCollection, :seed_helper do
subject { super().real_size }
it { is_expected.to eq('10+') }
end
+
+ describe '#line_count' do
+ subject { super().line_count }
+ it { is_expected.to eq 10 }
+ end
+
it { expect(subject.size).to eq(10) }
context 'when limiting is disabled' do
@@ -183,6 +211,12 @@ describe Gitlab::Git::DiffCollection, :seed_helper do
subject { super().real_size }
it { is_expected.to eq('11') }
end
+
+ describe '#line_count' do
+ subject { super().line_count }
+ it { is_expected.to eq file_count * line_count }
+ end
+
it { expect(subject.size).to eq(11) }
end
end
@@ -204,6 +238,12 @@ describe Gitlab::Git::DiffCollection, :seed_helper do
subject { super().real_size }
it { is_expected.to eq('3+') }
end
+
+ describe '#line_count' do
+ subject { super().line_count }
+ it { is_expected.to eq 120 }
+ end
+
it { expect(subject.size).to eq(3) }
context 'when limiting is disabled' do
@@ -223,6 +263,12 @@ describe Gitlab::Git::DiffCollection, :seed_helper do
subject { super().real_size }
it { is_expected.to eq('11') }
end
+
+ describe '#line_count' do
+ subject { super().line_count }
+ it { is_expected.to eq file_count * line_count }
+ end
+
it { expect(subject.size).to eq(11) }
end
end
@@ -248,6 +294,12 @@ describe Gitlab::Git::DiffCollection, :seed_helper do
subject { super().real_size }
it { is_expected.to eq('10') }
end
+
+ describe '#line_count' do
+ subject { super().line_count }
+ it { is_expected.to eq file_count * line_count }
+ end
+
it { expect(subject.size).to eq(10) }
end
end
@@ -270,6 +322,12 @@ describe Gitlab::Git::DiffCollection, :seed_helper do
subject { super().real_size }
it { is_expected.to eq('9+') }
end
+
+ describe '#line_count' do
+ subject { super().line_count }
+ it { is_expected.to eq file_count * line_count }
+ end
+
it { expect(subject.size).to eq(9) }
context 'when limiting is disabled' do
@@ -289,6 +347,12 @@ describe Gitlab::Git::DiffCollection, :seed_helper do
subject { super().real_size }
it { is_expected.to eq('10') }
end
+
+ describe '#line_count' do
+ subject { super().line_count }
+ it { is_expected.to eq file_count * line_count }
+ end
+
it { expect(subject.size).to eq(10) }
end
end
@@ -316,6 +380,11 @@ describe Gitlab::Git::DiffCollection, :seed_helper do
subject { super().real_size }
it { is_expected.to eq('0')}
end
+
+ describe '#line_count' do
+ subject { super().line_count }
+ it { is_expected.to eq 0 }
+ end
end
describe '#each' do
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index c6aa4a2482c..47ba7eff8ed 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -26,6 +26,7 @@ issues:
events:
- author
- project
+- group
- target
- push_event_payload
notes:
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index f0545176a90..516e62c4728 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -33,6 +33,7 @@ Event:
- target_type
- target_id
- project_id
+- group_id
- created_at
- updated_at
- action
diff --git a/spec/lib/gitlab/jwt_authenticatable_spec.rb b/spec/lib/gitlab/jwt_authenticatable_spec.rb
new file mode 100644
index 00000000000..0c1c491b308
--- /dev/null
+++ b/spec/lib/gitlab/jwt_authenticatable_spec.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::JwtAuthenticatable do
+ let(:test_class) do
+ Class.new do
+ include Gitlab::JwtAuthenticatable
+
+ def self.secret_path
+ Rails.root.join('tmp', 'tests', '.jwt_shared_secret')
+ end
+ end
+ end
+
+ before do
+ begin
+ File.delete(test_class.secret_path)
+ rescue Errno::ENOENT
+ end
+
+ test_class.write_secret
+ end
+
+ describe '.secret' do
+ subject(:secret) { test_class.secret }
+
+ it 'returns 32 bytes' do
+ expect(secret).to be_a(String)
+ expect(secret.length).to eq(32)
+ expect(secret.encoding).to eq(Encoding::ASCII_8BIT)
+ end
+
+ it 'accepts a trailing newline' do
+ File.open(test_class.secret_path, 'a') { |f| f.write "\n" }
+
+ expect(secret.length).to eq(32)
+ end
+
+ it 'raises an exception if the secret file cannot be read' do
+ File.delete(test_class.secret_path)
+
+ expect { secret }.to raise_exception(Errno::ENOENT)
+ end
+
+ it 'raises an exception if the secret file contains the wrong number of bytes' do
+ File.truncate(test_class.secret_path, 0)
+
+ expect { secret }.to raise_exception(RuntimeError)
+ end
+ end
+
+ describe '.write_secret' do
+ it 'uses mode 0600' do
+ expect(File.stat(test_class.secret_path).mode & 0777).to eq(0600)
+ end
+
+ it 'writes base64 data' do
+ bytes = Base64.strict_decode64(File.read(test_class.secret_path))
+
+ expect(bytes).not_to be_empty
+ end
+ end
+
+ describe '.decode_jwt_for_issuer' do
+ let(:payload) { { 'iss' => 'test_issuer' } }
+
+ it 'accepts a correct header' do
+ encoded_message = JWT.encode(payload, test_class.secret, 'HS256')
+
+ expect { test_class.decode_jwt_for_issuer('test_issuer', encoded_message) }.not_to raise_error
+ end
+
+ it 'raises an error when the JWT is not signed' do
+ encoded_message = JWT.encode(payload, nil, 'none')
+
+ expect { test_class.decode_jwt_for_issuer('test_issuer', encoded_message) }.to raise_error(JWT::DecodeError)
+ end
+
+ it 'raises an error when the header is signed with the wrong secret' do
+ encoded_message = JWT.encode(payload, 'wrongsecret', 'HS256')
+
+ expect { test_class.decode_jwt_for_issuer('test_issuer', encoded_message) }.to raise_error(JWT::DecodeError)
+ end
+
+ it 'raises an error when the issuer is incorrect' do
+ payload['iss'] = 'somebody else'
+ encoded_message = JWT.encode(payload, test_class.secret, 'HS256')
+
+ expect { test_class.decode_jwt_for_issuer('test_issuer', encoded_message) }.to raise_error(JWT::DecodeError)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb
index 98421cd12d3..88bc5034da5 100644
--- a/spec/lib/gitlab/workhorse_spec.rb
+++ b/spec/lib/gitlab/workhorse_spec.rb
@@ -200,57 +200,6 @@ describe Gitlab::Workhorse do
end
end
- describe ".secret" do
- subject { described_class.secret }
-
- before do
- described_class.instance_variable_set(:@secret, nil)
- described_class.write_secret
- end
-
- it 'returns 32 bytes' do
- expect(subject).to be_a(String)
- expect(subject.length).to eq(32)
- expect(subject.encoding).to eq(Encoding::ASCII_8BIT)
- end
-
- it 'accepts a trailing newline' do
- File.open(described_class.secret_path, 'a') { |f| f.write "\n" }
- expect(subject.length).to eq(32)
- end
-
- it 'raises an exception if the secret file cannot be read' do
- File.delete(described_class.secret_path)
- expect { subject }.to raise_exception(Errno::ENOENT)
- end
-
- it 'raises an exception if the secret file contains the wrong number of bytes' do
- File.truncate(described_class.secret_path, 0)
- expect { subject }.to raise_exception(RuntimeError)
- end
- end
-
- describe ".write_secret" do
- let(:secret_path) { described_class.secret_path }
- before do
- begin
- File.delete(secret_path)
- rescue Errno::ENOENT
- end
-
- described_class.write_secret
- end
-
- it 'uses mode 0600' do
- expect(File.stat(secret_path).mode & 0777).to eq(0600)
- end
-
- it 'writes base64 data' do
- bytes = Base64.strict_decode64(File.read(secret_path))
- expect(bytes).not_to be_empty
- end
- end
-
describe '#verify_api_request!' do
let(:header_key) { described_class::INTERNAL_API_REQUEST_HEADER }
let(:payload) { { 'iss' => 'gitlab-workhorse' } }
diff --git a/spec/lib/gitlab_spec.rb b/spec/lib/gitlab_spec.rb
index 1fc363460ae..74d4b12a070 100644
--- a/spec/lib/gitlab_spec.rb
+++ b/spec/lib/gitlab_spec.rb
@@ -1,10 +1,10 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
-
-require_dependency 'gitlab'
+require 'spec_helper'
describe Gitlab do
+ include RailsHelpers
+
describe '.root' do
it 'returns the root path of the app' do
expect(described_class.root).to eq(Pathname.new(File.expand_path('../..', __dir__)))
@@ -113,7 +113,7 @@ describe Gitlab do
it 'is true when dev env' do
allow(described_class).to receive_messages(com?: false, org?: false)
- allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('development'))
+ stub_rails_env('development')
expect(described_class.dev_env_org_or_com?).to eq true
end
diff --git a/spec/models/merge_request/metrics_spec.rb b/spec/models/merge_request/metrics_spec.rb
index 49573af0fed..bd97cabc11e 100644
--- a/spec/models/merge_request/metrics_spec.rb
+++ b/spec/models/merge_request/metrics_spec.rb
@@ -3,8 +3,6 @@
require 'spec_helper'
describe MergeRequest::Metrics do
- subject { described_class.new }
-
describe 'associations' do
it { is_expected.to belong_to(:merge_request) }
it { is_expected.to belong_to(:latest_closed_by).class_name('User') }
diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb
index e7dd7287a75..b86663fd7d9 100644
--- a/spec/models/merge_request_diff_spec.rb
+++ b/spec/models/merge_request_diff_spec.rb
@@ -400,6 +400,18 @@ describe MergeRequestDiff do
end
end
+ describe '#first_commit' do
+ it 'returns first commit' do
+ expect(diff_with_commits.first_commit.sha).to eq(diff_with_commits.merge_request_diff_commits.last.sha)
+ end
+ end
+
+ describe '#last_commit' do
+ it 'returns last commit' do
+ expect(diff_with_commits.last_commit.sha).to eq(diff_with_commits.merge_request_diff_commits.first.sha)
+ end
+ end
+
describe '#commits_by_shas' do
let(:commit_shas) { diff_with_commits.commit_shas }
@@ -489,7 +501,7 @@ describe MergeRequestDiff do
subject { diff_with_commits }
it 'returns sum of all changed lines count in diff files' do
- expect(subject.lines_count).to eq 109
+ expect(subject.lines_count).to eq 189
end
end
end
diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal/base_spec.rb
index c94f6d22e74..a56527073c7 100644
--- a/spec/requests/api/internal_spec.rb
+++ b/spec/requests/api/internal/base_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe API::Internal do
+describe API::Internal::Base do
set(:user) { create(:user) }
let(:key) { create(:key, user: user) }
set(:project) { create(:project, :repository, :wiki_repo) }
diff --git a/spec/support/helpers/rails_helpers.rb b/spec/support/helpers/rails_helpers.rb
new file mode 100644
index 00000000000..e1875b2fb15
--- /dev/null
+++ b/spec/support/helpers/rails_helpers.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module RailsHelpers
+ def stub_rails_env(env_name)
+ allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new(env_name))
+ end
+end
diff --git a/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb b/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb
index ff2d491539b..697e44be065 100644
--- a/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb
+++ b/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb
@@ -17,10 +17,16 @@ describe 'projects/settings/ci_cd/_autodevops_form' do
context 'when the project has an available kubernetes cluster' do
let!(:cluster) { create(:cluster, cluster_type: :project_type, projects: [project]) }
- it 'does not show a warning message' do
+ it 'does not show a warning message about Kubernetes cluster' do
render
expect(rendered).not_to have_text('You must add a Kubernetes cluster')
end
+
+ it 'shows a warning message about base domain' do
+ render
+
+ expect(rendered).to have_text('You must add a base domain to your Kubernetes cluster in order for your deployment strategy to work.')
+ end
end
end
diff --git a/yarn.lock b/yarn.lock
index 4cf3a9584f1..bd8f9014131 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4909,7 +4909,7 @@ exports-loader@^0.7.0:
express@^4.16.2, express@^4.16.3:
version "4.16.3"
- resolved "http://registry.npmjs.org/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53"
+ resolved "https://registry.npmjs.org/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53"
integrity sha1-avilAjUNsyRuzEvs9rWjTSL37VM=
dependencies:
accepts "~1.3.5"
@@ -8304,7 +8304,7 @@ mixin-deep@^1.2.0:
mkdirp@0.5.x, mkdirp@0.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1:
version "0.5.1"
- resolved "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+ resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
dependencies:
minimist "0.0.8"