summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/diffs/components/diff_file.vue6
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue8
-rw-r--r--app/assets/javascripts/diffs/components/tree_list.vue4
-rw-r--r--app/assets/javascripts/diffs/store/modules/diff_state.js1
-rw-r--r--app/assets/javascripts/diffs/store/mutations.js3
-rw-r--r--app/assets/javascripts/vue_shared/components/file_row.vue47
-rw-r--r--app/assets/stylesheets/pages/diff.scss5
-rw-r--r--app/models/project_services/teamcity_service.rb8
-rw-r--r--app/services/projects/lfs_pointers/lfs_list_service.rb4
-rw-r--r--app/workers/authorized_keys_worker.rb10
-rw-r--r--app/workers/gitlab_shell_worker.rb2
-rw-r--r--changelogs/unreleased/208923-enable-batch-counting-for-some-individual-queries-2.yml5
-rw-r--r--changelogs/unreleased/212178-fix-authorized-keys-worker.yml5
-rw-r--r--changelogs/unreleased/24629.yml5
-rw-r--r--changelogs/unreleased/29825-reactivecaching-sidekiq-queue-overloaded-teamcity.yml5
-rw-r--r--db/migrate/20200316162648_add_index_on_namespace_id_and_id_to_projects.rb19
-rw-r--r--db/migrate/20200323075043_add_max_personal_access_token_lifetime_to_namespaces.rb19
-rw-r--r--db/structure.sql9
-rw-r--r--doc/development/code_review.md35
-rw-r--r--doc/development/contributing/merge_request_workflow.md27
-rw-r--r--doc/user/project/integrations/img/panel_context_menu_v12_10.pngbin0 -> 15866 bytes
-rw-r--r--doc/user/project/integrations/img/panel_context_menu_v12_8.pngbin25884 -> 0 bytes
-rw-r--r--doc/user/project/integrations/prometheus.md2
-rw-r--r--lib/gitlab/git/lfs_changes.rb2
-rw-r--r--lib/gitlab/http.rb12
-rw-r--r--package.json2
-rw-r--r--spec/frontend/cycle_analytics/banner_spec.js (renamed from spec/javascripts/cycle_analytics/banner_spec.js)4
-rw-r--r--spec/frontend/cycle_analytics/total_time_component_spec.js (renamed from spec/javascripts/cycle_analytics/total_time_component_spec.js)2
-rw-r--r--spec/frontend/diffs/components/diff_file_header_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/file_row_spec.js13
-rw-r--r--spec/lib/gitlab/http_spec.rb123
-rw-r--r--spec/models/project_services/teamcity_service_spec.rb22
-rw-r--r--spec/services/ci/create_cross_project_pipeline_service_spec.rb2
-rw-r--r--spec/workers/authorized_keys_worker_spec.rb12
-rw-r--r--spec/workers/gitlab_shell_worker_spec.rb6
-rw-r--r--yarn.lock8
36 files changed, 358 insertions, 85 deletions
diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue
index 8babc05f1ce..e09bf1f8005 100644
--- a/app/assets/javascripts/diffs/components/diff_file.vue
+++ b/app/assets/javascripts/diffs/components/diff_file.vue
@@ -58,6 +58,9 @@ export default {
hasDiff() {
return hasDiff(this.file);
},
+ isActive() {
+ return this.currentDiffFileId === this.file.file_hash;
+ },
isFileTooLarge() {
return this.file.viewer.error === diffViewerErrors.too_large;
},
@@ -143,7 +146,7 @@ export default {
<div
:id="file.file_hash"
:class="{
- 'is-active': currentDiffFileId === file.file_hash,
+ 'is-active': isActive,
}"
class="diff-file file-holder"
>
@@ -153,6 +156,7 @@ export default {
:collapsible="true"
:expanded="!isCollapsed"
:add-merge-request-buttons="true"
+ :is-active="isActive"
class="js-file-title file-title"
@toggleFile="handleToggle"
@showForkMessage="showForkMessage"
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index d4270960f57..bad82c84601 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -55,6 +55,11 @@ export default {
type: Boolean,
required: true,
},
+ isActive: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
...mapGetters('diffs', ['diffHasExpandedDiscussions', 'diffHasDiscussions']),
@@ -158,6 +163,9 @@ export default {
<div
ref="header"
class="js-file-title file-title file-title-flex-parent"
+ :class="{
+ 'is-active': isActive,
+ }"
@click.self="handleToggleFile"
>
<div class="file-header-content">
diff --git a/app/assets/javascripts/diffs/components/tree_list.vue b/app/assets/javascripts/diffs/components/tree_list.vue
index eca9091f92f..fcf87807e75 100644
--- a/app/assets/javascripts/diffs/components/tree_list.vue
+++ b/app/assets/javascripts/diffs/components/tree_list.vue
@@ -26,7 +26,7 @@ export default {
};
},
computed: {
- ...mapState('diffs', ['tree', 'renderTreeList']),
+ ...mapState('diffs', ['tree', 'renderTreeList', 'currentDiffFileId', 'viewedDiffFileIds']),
...mapGetters('diffs', ['allBlobs']),
filteredTreeList() {
const search = this.search.toLowerCase().trim();
@@ -96,6 +96,8 @@ export default {
:level="0"
:hide-file-stats="hideFileStats"
:file-row-component="$options.DiffFileRow"
+ :active-file="currentDiffFileId"
+ :viewed-files="viewedDiffFileIds"
@toggleTreeOpen="toggleTreeOpen"
@clickFile="scrollToFile"
/>
diff --git a/app/assets/javascripts/diffs/store/modules/diff_state.js b/app/assets/javascripts/diffs/store/modules/diff_state.js
index 81f1506260c..f1bd9d8981d 100644
--- a/app/assets/javascripts/diffs/store/modules/diff_state.js
+++ b/app/assets/javascripts/diffs/store/modules/diff_state.js
@@ -26,6 +26,7 @@ export default () => ({
showTreeList: true,
currentDiffFileId: '',
projectPath: '',
+ viewedDiffFileIds: [],
commentForms: [],
highlightedRow: null,
renderTreeList: true,
diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js
index bb4c80b5759..6438dad4f7f 100644
--- a/app/assets/javascripts/diffs/store/mutations.js
+++ b/app/assets/javascripts/diffs/store/mutations.js
@@ -284,6 +284,9 @@ export default {
},
[types.UPDATE_CURRENT_DIFF_FILE_ID](state, fileId) {
state.currentDiffFileId = fileId;
+ if (!state.viewedDiffFileIds.includes(fileId)) {
+ state.viewedDiffFileIds = [fileId, ...state.viewedDiffFileIds];
+ }
},
[types.OPEN_DIFF_FILE_COMMENT_FORM](state, formData) {
state.commentForms.push({
diff --git a/app/assets/javascripts/vue_shared/components/file_row.vue b/app/assets/javascripts/vue_shared/components/file_row.vue
index 4d60cf5b1cc..5a953b351f9 100644
--- a/app/assets/javascripts/vue_shared/components/file_row.vue
+++ b/app/assets/javascripts/vue_shared/components/file_row.vue
@@ -18,6 +18,16 @@ export default {
type: Number,
required: true,
},
+ activeFile: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ viewedFiles: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
},
computed: {
isTree() {
@@ -34,8 +44,8 @@ export default {
fileClass() {
return {
'file-open': this.isBlob && this.file.opened,
- 'is-active': this.isBlob && this.file.active,
- folder: this.isTree,
+ 'is-active': this.isBlob && (this.file.active || this.activeFile === this.file.fileHash),
+ 'is-viewed': this.isBlob && this.viewedFiles.includes(this.file.fileHash),
'is-open': this.file.opened,
};
},
@@ -107,15 +117,23 @@ export default {
v-else
:class="fileClass"
:title="file.name"
- class="file-row"
+ class="file-row text-left px-1 py-2 ml-n2 d-flex align-items-center"
role="button"
@click="clickFile"
@mouseleave="$emit('mouseleave', $event)"
>
- <div class="file-row-name-container">
- <span ref="textOutput" :style="levelIndentation" class="file-row-name str-truncated">
+ <div class="file-row-name-container w-100 d-flex align-items-center">
+ <span
+ ref="textOutput"
+ :style="levelIndentation"
+ class="file-row-name str-truncated d-inline-block"
+ :class="[
+ { 'folder font-weight-normal': isTree },
+ fileClass['is-viewed'] ? 'font-weight-normal' : 'font-weight-bold',
+ ]"
+ >
<file-icon
- class="file-row-icon"
+ class="file-row-icon align-middle mr-1"
:class="{ 'text-secondary': file.type === 'tree' }"
:file-name="file.name"
:loading="file.loading"
@@ -132,14 +150,8 @@ export default {
<style>
.file-row {
- display: flex;
- align-items: center;
height: 32px;
- padding: 4px 8px;
- margin-left: -8px;
- margin-right: -8px;
border-radius: 3px;
- text-align: left;
cursor: pointer;
}
@@ -157,24 +169,15 @@ export default {
}
.file-row-name-container {
- display: flex;
- width: 100%;
- align-items: center;
overflow: visible;
}
.file-row-name {
- display: inline-block;
flex: 1;
max-width: inherit;
- height: 19px;
+ height: 20px;
line-height: 16px;
text-overflow: ellipsis;
white-space: nowrap;
}
-
-.file-row-name .file-row-icon {
- margin-right: 2px;
- vertical-align: middle;
-}
</style>
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index 0c043e4f3fb..991ee841398 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -69,6 +69,11 @@
}
}
+ .file-title.is-active,
+ .file-title-flex-parent.is-active {
+ background-color: $gray-200;
+ }
+
@media (min-width: map-get($grid-breakpoints, md)) {
&.conflict .file-title,
&.conflict .file-title-flex-parent {
diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb
index 68c07fa37f2..209b691ef98 100644
--- a/app/models/project_services/teamcity_service.rb
+++ b/app/models/project_services/teamcity_service.rb
@@ -86,7 +86,11 @@ class TeamcityService < CiService
def calculate_reactive_cache(sha, ref)
response = get_path("httpAuth/app/rest/builds/branch:unspecified:any,revision:#{sha}")
- { build_page: read_build_page(response), commit_status: read_commit_status(response) }
+ if response
+ { build_page: read_build_page(response), commit_status: read_commit_status(response) }
+ else
+ { build_page: teamcity_url, commit_status: :error }
+ end
end
def execute(data)
@@ -149,7 +153,7 @@ class TeamcityService < CiService
end
def get_path(path)
- Gitlab::HTTP.get(build_url(path), verify: false, basic_auth: basic_auth)
+ Gitlab::HTTP.try_get(build_url(path), verify: false, basic_auth: basic_auth, extra_log_info: { project_id: project_id })
end
def post_to_build_queue(data, branch)
diff --git a/app/services/projects/lfs_pointers/lfs_list_service.rb b/app/services/projects/lfs_pointers/lfs_list_service.rb
index a07fa93a279..59c86c08120 100644
--- a/app/services/projects/lfs_pointers/lfs_list_service.rb
+++ b/app/services/projects/lfs_pointers/lfs_list_service.rb
@@ -4,14 +4,12 @@
module Projects
module LfsPointers
class LfsListService < BaseService
- REV = 'HEAD'
-
# Retrieve all lfs blob pointers and returns a hash
# with the structure { lfs_file_oid => lfs_file_size }
def execute
return {} unless project&.lfs_enabled?
- Gitlab::Git::LfsChanges.new(project.repository, REV)
+ Gitlab::Git::LfsChanges.new(project.repository)
.all_pointers
.map! { |blob| [blob.lfs_oid, blob.lfs_size] }
.to_h
diff --git a/app/workers/authorized_keys_worker.rb b/app/workers/authorized_keys_worker.rb
index b2333033e56..eabfd89ba60 100644
--- a/app/workers/authorized_keys_worker.rb
+++ b/app/workers/authorized_keys_worker.rb
@@ -3,7 +3,7 @@
class AuthorizedKeysWorker
include ApplicationWorker
- PERMITTED_ACTIONS = [:add_key, :remove_key].freeze
+ PERMITTED_ACTIONS = %w[add_key remove_key].freeze
feature_category :source_code_management
urgency :high
@@ -13,11 +13,13 @@ class AuthorizedKeysWorker
def perform(action, *args)
return unless Gitlab::CurrentSettings.authorized_keys_enabled?
- case action
- when :add_key
+ case action.to_s
+ when 'add_key'
authorized_keys.add_key(*args)
- when :remove_key
+ when 'remove_key'
authorized_keys.remove_key(*args)
+ else
+ raise "Unknown action: #{action.inspect}"
end
end
diff --git a/app/workers/gitlab_shell_worker.rb b/app/workers/gitlab_shell_worker.rb
index 0db794793d4..b104d3c681e 100644
--- a/app/workers/gitlab_shell_worker.rb
+++ b/app/workers/gitlab_shell_worker.rb
@@ -13,7 +13,7 @@ class GitlabShellWorker # rubocop:disable Scalability/IdempotentWorker
# enqueued in the previous release, so handle them here.
#
# See https://gitlab.com/gitlab-org/gitlab/-/issues/25095 for more details
- if AuthorizedKeysWorker::PERMITTED_ACTIONS.include?(action)
+ if AuthorizedKeysWorker::PERMITTED_ACTIONS.include?(action.to_s)
AuthorizedKeysWorker.new.perform(action, *arg)
return
diff --git a/changelogs/unreleased/208923-enable-batch-counting-for-some-individual-queries-2.yml b/changelogs/unreleased/208923-enable-batch-counting-for-some-individual-queries-2.yml
new file mode 100644
index 00000000000..12456aa9b9b
--- /dev/null
+++ b/changelogs/unreleased/208923-enable-batch-counting-for-some-individual-queries-2.yml
@@ -0,0 +1,5 @@
+---
+title: Optimize template_repositories query by using batch counting
+merge_request: 27352
+author:
+type: performance
diff --git a/changelogs/unreleased/212178-fix-authorized-keys-worker.yml b/changelogs/unreleased/212178-fix-authorized-keys-worker.yml
new file mode 100644
index 00000000000..a95f2e0e71a
--- /dev/null
+++ b/changelogs/unreleased/212178-fix-authorized-keys-worker.yml
@@ -0,0 +1,5 @@
+---
+title: Fix updating the authorized_keys file
+merge_request: 27798
+author:
+type: fixed
diff --git a/changelogs/unreleased/24629.yml b/changelogs/unreleased/24629.yml
new file mode 100644
index 00000000000..1b39cff8d18
--- /dev/null
+++ b/changelogs/unreleased/24629.yml
@@ -0,0 +1,5 @@
+---
+title: Highlight currently focused/viewed file in file tree
+merge_request: 27703
+author:
+type: changed
diff --git a/changelogs/unreleased/29825-reactivecaching-sidekiq-queue-overloaded-teamcity.yml b/changelogs/unreleased/29825-reactivecaching-sidekiq-queue-overloaded-teamcity.yml
new file mode 100644
index 00000000000..face6ee9c40
--- /dev/null
+++ b/changelogs/unreleased/29825-reactivecaching-sidekiq-queue-overloaded-teamcity.yml
@@ -0,0 +1,5 @@
+---
+title: Set commit status to failed if the TeamCity connection is refused
+merge_request: 27395
+author:
+type: fixed
diff --git a/db/migrate/20200316162648_add_index_on_namespace_id_and_id_to_projects.rb b/db/migrate/20200316162648_add_index_on_namespace_id_and_id_to_projects.rb
new file mode 100644
index 00000000000..96fbab1e2ea
--- /dev/null
+++ b/db/migrate/20200316162648_add_index_on_namespace_id_and_id_to_projects.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddIndexOnNamespaceIdAndIdToProjects < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :projects, [:namespace_id, :id]
+ remove_concurrent_index :projects, :namespace_id
+ end
+
+ def down
+ add_concurrent_index :projects, :namespace_id
+ remove_concurrent_index :projects, [:namespace_id, :id]
+ end
+end
diff --git a/db/migrate/20200323075043_add_max_personal_access_token_lifetime_to_namespaces.rb b/db/migrate/20200323075043_add_max_personal_access_token_lifetime_to_namespaces.rb
new file mode 100644
index 00000000000..907c832ce46
--- /dev/null
+++ b/db/migrate/20200323075043_add_max_personal_access_token_lifetime_to_namespaces.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddMaxPersonalAccessTokenLifetimeToNamespaces < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_column :namespaces, :max_personal_access_token_lifetime, :integer
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :namespaces, :max_personal_access_token_lifetime
+ end
+ end
+end
diff --git a/db/structure.sql b/db/structure.sql
index 2af6dcba3fd..e5d28e499f9 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -3944,7 +3944,8 @@ CREATE TABLE public.namespaces (
max_artifacts_size integer,
mentions_disabled boolean,
default_branch_protection smallint,
- unlock_membership_to_ldap boolean
+ unlock_membership_to_ldap boolean,
+ max_personal_access_token_lifetime integer
);
CREATE SEQUENCE public.namespaces_id_seq
@@ -9656,7 +9657,7 @@ CREATE INDEX index_projects_on_name_and_id ON public.projects USING btree (name,
CREATE INDEX index_projects_on_name_trigram ON public.projects USING gin (name public.gin_trgm_ops);
-CREATE INDEX index_projects_on_namespace_id ON public.projects USING btree (namespace_id);
+CREATE INDEX index_projects_on_namespace_id_and_id ON public.projects USING btree (namespace_id, id);
CREATE INDEX index_projects_on_path_and_id ON public.projects USING btree (path, id);
@@ -12701,6 +12702,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20200313101649'),
('20200313123934'),
('20200316111759'),
+('20200316162648'),
('20200316173312'),
('20200317142110'),
('20200318152134'),
@@ -12708,5 +12710,6 @@ INSERT INTO "schema_migrations" (version) VALUES
('20200318163148'),
('20200318164448'),
('20200318165448'),
-('20200319203901');
+('20200319203901'),
+('20200323075043');
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index 471dcba4c2a..830c3d3b3d2 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -73,6 +73,9 @@ from teams other than your own.
**approved by a [UX lead](https://about.gitlab.com/company/team/)**.
1. If your merge request includes a new dependency or a filesystem change, it must be
**approved by a [Distribution team member](https://about.gitlab.com/company/team/)**. See how to work with the [Distribution team](https://about.gitlab.com/handbook/engineering/development/enablement/distribution/#how-to-work-with-distribution) for more details.
+1. If your merge request includes documentation changes, it must be **approved
+ by a [Technical writer](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers)**, based on
+ the appropriate [product category](https://about.gitlab.com/handbook/product/categories/).
#### Security requirements
@@ -84,12 +87,17 @@ The responsibility to find the best solution and implement it lies with the
merge request author.
Before assigning a merge request to a maintainer for approval and merge, they
-should be confident that it actually solves the problem it was meant to solve,
-that it does so in the most appropriate way, that it satisfies all requirements,
-and that there are no remaining bugs, logical problems, uncovered edge cases,
-or known vulnerabilities. The best way to do this, and to avoid unnecessary
-back-and-forth with reviewers, is to perform a self-review of your own merge
-request, following the [Code Review](#reviewing-a-merge-request) guidelines.
+should be confident that:
+
+- It actually solves the problem it was meant to solve.
+- It does so in the most appropriate way.
+- It satisfies all requirements.
+- There are no remaining bugs, logical problems, uncovered edge cases,
+ or known vulnerabilities.
+
+The best way to do this, and to avoid unnecessary back-and-forth with reviewers,
+is to perform a self-review of your own merge request, following the
+[Code Review](#reviewing-a-merge-request) guidelines.
To reach the required level of confidence in their solution, an author is expected
to involve other people in the investigation and implementation processes as
@@ -110,11 +118,11 @@ request diff alerting the reviewer to anything important as well as for anything
that demands further explanation or attention. Examples of content that may
warrant a comment could be:
-- The addition of a linting rule (Rubocop, JS etc)
-- The addition of a library (Ruby gem, JS lib etc)
-- Where not obvious, a link to the parent class or method
-- Any benchmarking performed to complement the change
-- Potentially insecure code
+- The addition of a linting rule (Rubocop, JS etc).
+- The addition of a library (Ruby gem, JS lib etc).
+- Where not obvious, a link to the parent class or method.
+- Any benchmarking performed to complement the change.
+- Potentially insecure code.
Avoid:
@@ -233,6 +241,11 @@ first time.
addressed. If there's an open reply, an open thread, a suggestion,
a question, or anything else, the thread should be left to be resolved
by the reviewer.
+- It should not be assumed that all feedback requires their recommended changes
+ to be incorporated into the MR before it is merged. It is a judgment call by
+ the MR author and the reviewer as to if this is required, or if a follow-up
+ issue should be created to address the feedback in the future after the MR in
+ question is merged.
- Push commits based on earlier rounds of feedback as isolated commits to the
branch. Do not squash until the branch is ready to merge. Reviewers should be
able to read individual updates based on their earlier feedback.
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index 030cced8c2b..0ac08ec2eae 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -48,13 +48,8 @@ request is as follows:
but do not change the commit history if you're working on shared branches though.
1. Push the commit(s) to your working branch in your fork.
1. Submit a merge request (MR) to the `master` branch in the main GitLab project.
- 1. Your merge request needs at least 1 approval, but feel free to require more.
- For instance if you're touching both backend and frontend code, it's a good idea
- to require 2 approvals: 1 from a backend maintainer and 1 from a frontend
- maintainer.
- 1. If you're submitting changes to documentation, you'll need approval from a technical
- writer, based on the appropriate [product category](https://about.gitlab.com/handbook/product/categories/).
- Only assign the MR to them when it's ready for docs review.
+ 1. Your merge request needs at least 1 approval, but depending on your changes
+ you might need additional approvals. Refer to the [Approval guidelines](../code_review.md#approval-guidelines).
1. You don't have to select any specific approvers, but you can if you really want
specific people to approve your merge request.
1. The MR title should describe the change you want to make.
@@ -66,18 +61,12 @@ request is as follows:
1. Mention the issue(s) your merge request solves, using the `Solves #XXX` or
`Closes #XXX` syntax to [auto-close](../../user/project/issues/managing_issues.md#closing-issues-automatically)
the issue(s) once the merge request is merged.
-1. If you're allowed to (Core team members, for example), set a relevant milestone
- and [labels](issue_workflow.md).
-1. If the MR changes the UI, you'll need approval from a Product Designer (UX), based on the appropriate [product category](https://about.gitlab.com/handbook/product/categories/). UI changes should use available components from the GitLab Design System, [Pajamas](https://design.gitlab.com/). The MR must include *Before* and *After* screenshots.
+1. If you're allowed to, set a relevant milestone and [labels](issue_workflow.md).
+1. UI changes should use available components from the GitLab Design System,
+ [Pajamas](https://design.gitlab.com/). The MR must include *Before* and
+ *After* screenshots.
1. If the MR changes CSS classes, please include the list of affected pages, which
can be found by running `grep css-class ./app -R`.
-1. Be prepared to answer questions and incorporate feedback into your MR with new
- commits. Once you have fully addressed a suggestion from a reviewer, click the
- "Resolve thread" button beneath it to mark it resolved.
- 1. The merge request author resolves only the threads they have fully addressed.
- If there's an open reply or thread, a suggestion, a question, or anything else,
- the thread should be left to be resolved by the reviewer.
- 1. It should not be assumed that all feedback requires their recommended changes to be incorporated into the MR before it is merged. It is a judgment call by the MR author and the reviewer as to if this is required, or if a follow-up issue should be created to address the feedback in the future after the MR in question is merged.
1. If your MR touches code that executes shell commands, reads or opens files, or
handles paths to files on disk, make sure it adheres to the
[shell command guidelines](../shell_commands.md)
@@ -98,6 +87,10 @@ request is as follows:
`doc/update/upgrading_from_source.md` in the same merge request. If these
instructions are specific to a version, add them to the "Version specific
upgrading instructions" section.
+1. Read and adhere to
+ [The responsibility of the merge request author](../code_review.md#the-responsibility-of-the-merge-request-author).
+1. Read and follow
+ [Having your merge request reviewed](../code_review.md#having-your-merge-request-reviewed).
If you would like quick feedback on your merge request feel free to mention someone
from the [core team](https://about.gitlab.com/community/core-team/) or one of the
diff --git a/doc/user/project/integrations/img/panel_context_menu_v12_10.png b/doc/user/project/integrations/img/panel_context_menu_v12_10.png
new file mode 100644
index 00000000000..e6b0f75406d
--- /dev/null
+++ b/doc/user/project/integrations/img/panel_context_menu_v12_10.png
Binary files differ
diff --git a/doc/user/project/integrations/img/panel_context_menu_v12_8.png b/doc/user/project/integrations/img/panel_context_menu_v12_8.png
deleted file mode 100644
index 86d2b26b713..00000000000
--- a/doc/user/project/integrations/img/panel_context_menu_v12_8.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
index c64077c00f1..502e0f95dd2 100644
--- a/doc/user/project/integrations/prometheus.md
+++ b/doc/user/project/integrations/prometheus.md
@@ -589,7 +589,7 @@ When viewing a custom dashboard of a project, you can view the original
From each of the panels in the dashboard, you can access the context menu by clicking the **{ellipsis_v}** **More actions** dropdown box above the upper right corner of the panel to take actions related to the chart's data.
-![Context Menu](img/panel_context_menu_v12_8.png)
+![Context Menu](img/panel_context_menu_v12_10.png)
The options are:
diff --git a/lib/gitlab/git/lfs_changes.rb b/lib/gitlab/git/lfs_changes.rb
index 8e2a925dfea..a0fab67e450 100644
--- a/lib/gitlab/git/lfs_changes.rb
+++ b/lib/gitlab/git/lfs_changes.rb
@@ -3,7 +3,7 @@
module Gitlab
module Git
class LfsChanges
- def initialize(repository, newrev)
+ def initialize(repository, newrev = nil)
@repository = repository
@newrev = newrev
end
diff --git a/lib/gitlab/http.rb b/lib/gitlab/http.rb
index 58bce613a98..911b71c3734 100644
--- a/lib/gitlab/http.rb
+++ b/lib/gitlab/http.rb
@@ -25,5 +25,17 @@ module Gitlab
rescue HTTParty::RedirectionTooDeep
raise RedirectionTooDeep
end
+
+ def self.try_get(path, options = {}, &block)
+ log_info = options.delete(:extra_log_info)
+ self.get(path, options, &block)
+
+ rescue *HTTP_ERRORS => e
+ extra_info = log_info || {}
+ extra_info = log_info.call(e, path, options) if log_info.respond_to?(:call)
+
+ Gitlab::ErrorTracking.log_exception(e, extra_info)
+ nil
+ end
end
end
diff --git a/package.json b/package.json
index abf790f00fc..48c14db4e57 100644
--- a/package.json
+++ b/package.json
@@ -43,7 +43,7 @@
"@gitlab/ui": "^9.31.1",
"@gitlab/visual-review-tools": "1.5.1",
"@sentry/browser": "^5.10.2",
- "@sourcegraph/code-host-integration": "0.0.31",
+ "@sourcegraph/code-host-integration": "0.0.33",
"apollo-cache-inmemory": "^1.6.3",
"apollo-client": "^2.6.4",
"apollo-link": "^1.2.11",
diff --git a/spec/javascripts/cycle_analytics/banner_spec.js b/spec/frontend/cycle_analytics/banner_spec.js
index 06fbaa68ffc..f0b8cb18a90 100644
--- a/spec/javascripts/cycle_analytics/banner_spec.js
+++ b/spec/frontend/cycle_analytics/banner_spec.js
@@ -1,5 +1,5 @@
import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import mountComponent from 'helpers/vue_mount_component_helper';
import banner from '~/cycle_analytics/components/banner.vue';
describe('Cycle analytics banner', () => {
@@ -36,7 +36,7 @@ describe('Cycle analytics banner', () => {
});
it('should emit an event when close button is clicked', () => {
- spyOn(vm, '$emit');
+ jest.spyOn(vm, '$emit').mockImplementation(() => {});
vm.$el.querySelector('.js-ca-dismiss-button').click();
diff --git a/spec/javascripts/cycle_analytics/total_time_component_spec.js b/spec/frontend/cycle_analytics/total_time_component_spec.js
index 0269fc1b002..0f7f2628aca 100644
--- a/spec/javascripts/cycle_analytics/total_time_component_spec.js
+++ b/spec/frontend/cycle_analytics/total_time_component_spec.js
@@ -1,5 +1,5 @@
import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import mountComponent from 'helpers/vue_mount_component_helper';
import component from '~/cycle_analytics/components/total_time_component.vue';
describe('Total time component', () => {
diff --git a/spec/frontend/diffs/components/diff_file_header_spec.js b/spec/frontend/diffs/components/diff_file_header_spec.js
index e0b7e0bc0f3..8e6a5576015 100644
--- a/spec/frontend/diffs/components/diff_file_header_spec.js
+++ b/spec/frontend/diffs/components/diff_file_header_spec.js
@@ -61,6 +61,7 @@ describe('DiffFileHeader component', () => {
const findTitleLink = () => wrapper.find({ ref: 'titleWrapper' });
const findExpandButton = () => wrapper.find({ ref: 'expandDiffToFullFileButton' });
const findFileActions = () => wrapper.find('.file-actions');
+ const findActiveHeader = () => wrapper.find('.is-active');
const findModeChangedLine = () => wrapper.find({ ref: 'fileMode' });
const findLfsLabel = () => wrapper.find('.label-lfs');
const findToggleDiscussionsButton = () => wrapper.find({ ref: 'toggleDiscussionsButton' });
@@ -143,6 +144,11 @@ describe('DiffFileHeader component', () => {
expect(wrapper.find(ClipboardButton).exists()).toBe(true);
});
+ it('contains a active header class if this is the active file header', () => {
+ createComponent({ isActive: true });
+ expect(findActiveHeader().exists()).toBe(true);
+ });
+
describe('for submodule', () => {
const submoduleDiffFile = {
...diffFile,
diff --git a/spec/frontend/vue_shared/components/file_row_spec.js b/spec/frontend/vue_shared/components/file_row_spec.js
index b3ced84ddb5..75d1ce9cc5b 100644
--- a/spec/frontend/vue_shared/components/file_row_spec.js
+++ b/spec/frontend/vue_shared/components/file_row_spec.js
@@ -72,6 +72,19 @@ describe('File row component', () => {
});
});
+ it('is marked as viewed if clicked', () => {
+ createComponent({
+ file: {
+ ...file(),
+ type: 'blob',
+ fileHash: '#123456789',
+ },
+ level: 0,
+ viewedFiles: ['#123456789'],
+ });
+ expect(wrapper.classes()).toContain('is-viewed');
+ });
+
it('indents row based on level', () => {
createComponent({
file: file('t4'),
diff --git a/spec/lib/gitlab/http_spec.rb b/spec/lib/gitlab/http_spec.rb
index 192816ad057..85cfc8e2852 100644
--- a/spec/lib/gitlab/http_spec.rb
+++ b/spec/lib/gitlab/http_spec.rb
@@ -100,4 +100,127 @@ describe Gitlab::HTTP do
expect { described_class.head('http://example.org') }.to raise_error(Gitlab::HTTP::RedirectionTooDeep)
end
end
+
+ describe '.try_get' do
+ let(:path) { 'http://example.org' }
+
+ let(:extra_log_info_proc) do
+ proc do |error, url, options|
+ { klass: error.class, url: url, options: options }
+ end
+ end
+
+ let(:request_options) do
+ {
+ verify: false,
+ basic_auth: { username: 'user', password: 'pass' }
+ }
+ end
+
+ described_class::HTTP_ERRORS.each do |exception_class|
+ context "with #{exception_class}" do
+ let(:klass) { exception_class }
+
+ context 'with path' do
+ before do
+ expect(described_class).to receive(:get)
+ .with(path, {})
+ .and_raise(klass)
+ end
+
+ it 'handles requests without extra_log_info' do
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(instance_of(klass), {})
+
+ expect(described_class.try_get(path)).to be_nil
+ end
+
+ it 'handles requests with extra_log_info as hash' do
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(instance_of(klass), { a: :b })
+
+ expect(described_class.try_get(path, extra_log_info: { a: :b })).to be_nil
+ end
+
+ it 'handles requests with extra_log_info as proc' do
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(instance_of(klass), { url: path, klass: klass, options: {} })
+
+ expect(described_class.try_get(path, extra_log_info: extra_log_info_proc)).to be_nil
+ end
+ end
+
+ context 'with path and options' do
+ before do
+ expect(described_class).to receive(:get)
+ .with(path, request_options)
+ .and_raise(klass)
+ end
+
+ it 'handles requests without extra_log_info' do
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(instance_of(klass), {})
+
+ expect(described_class.try_get(path, request_options)).to be_nil
+ end
+
+ it 'handles requests with extra_log_info as hash' do
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(instance_of(klass), { a: :b })
+
+ expect(described_class.try_get(path, **request_options, extra_log_info: { a: :b })).to be_nil
+ end
+
+ it 'handles requests with extra_log_info as proc' do
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(instance_of(klass), { klass: klass, url: path, options: request_options })
+
+ expect(described_class.try_get(path, **request_options, extra_log_info: extra_log_info_proc)).to be_nil
+ end
+ end
+
+ context 'with path, options, and block' do
+ let(:block) do
+ proc {}
+ end
+
+ before do
+ expect(described_class).to receive(:get)
+ .with(path, request_options, &block)
+ .and_raise(klass)
+ end
+
+ it 'handles requests without extra_log_info' do
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(instance_of(klass), {})
+
+ expect(described_class.try_get(path, request_options, &block)).to be_nil
+ end
+
+ it 'handles requests with extra_log_info as hash' do
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(instance_of(klass), { a: :b })
+
+ expect(described_class.try_get(path, **request_options, extra_log_info: { a: :b }, &block)).to be_nil
+ end
+
+ it 'handles requests with extra_log_info as proc' do
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(instance_of(klass), { klass: klass, url: path, options: request_options })
+
+ expect(described_class.try_get(path, **request_options, extra_log_info: extra_log_info_proc, &block)).to be_nil
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/project_services/teamcity_service_spec.rb b/spec/models/project_services/teamcity_service_spec.rb
index 3d875bc49e7..0dd77b68588 100644
--- a/spec/models/project_services/teamcity_service_spec.rb
+++ b/spec/models/project_services/teamcity_service_spec.rb
@@ -7,6 +7,7 @@ describe TeamcityService, :use_clean_rails_memory_store_caching do
include StubRequests
let(:teamcity_url) { 'http://gitlab.com/teamcity' }
+ let(:teamcity_full_url) { 'http://gitlab.com/teamcity/httpAuth/app/rest/builds/branch:unspecified:any,revision:123' }
let(:project) { create(:project) }
subject(:service) do
@@ -165,6 +166,16 @@ describe TeamcityService, :use_clean_rails_memory_store_caching do
is_expected.to eq('http://gitlab.com/teamcity/viewLog.html?buildId=666&buildTypeId=foo')
end
end
+
+ it 'returns the teamcity_url when teamcity is unreachable' do
+ stub_full_request(teamcity_full_url).to_raise(Errno::ECONNREFUSED)
+
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(instance_of(Errno::ECONNREFUSED), project_id: project.id)
+
+ is_expected.to eq(teamcity_url)
+ end
end
context 'commit_status' do
@@ -205,6 +216,16 @@ describe TeamcityService, :use_clean_rails_memory_store_caching do
is_expected.to eq(:error)
end
+
+ it 'sets commit status to :error when teamcity is unreachable' do
+ stub_full_request(teamcity_full_url).to_raise(Errno::ECONNREFUSED)
+
+ expect(Gitlab::ErrorTracking)
+ .to receive(:log_exception)
+ .with(instance_of(Errno::ECONNREFUSED), project_id: project.id)
+
+ is_expected.to eq(:error)
+ end
end
end
@@ -300,7 +321,6 @@ describe TeamcityService, :use_clean_rails_memory_store_caching do
end
def stub_request(status: 200, body: nil, build_status: 'success')
- teamcity_full_url = 'http://gitlab.com/teamcity/httpAuth/app/rest/builds/branch:unspecified:any,revision:123'
auth = %w(mic password)
body ||= %Q({"build":{"status":"#{build_status}","id":"666"}})
diff --git a/spec/services/ci/create_cross_project_pipeline_service_spec.rb b/spec/services/ci/create_cross_project_pipeline_service_spec.rb
index 99c44c3aa17..a411244e57f 100644
--- a/spec/services/ci/create_cross_project_pipeline_service_spec.rb
+++ b/spec/services/ci/create_cross_project_pipeline_service_spec.rb
@@ -215,7 +215,7 @@ describe Ci::CreateCrossProjectPipelineService, '#execute' do
pipeline = service.execute(bridge)
pipeline.reload
- expect(pipeline.builds.map(&:name)).to eq %w[rspec echo]
+ expect(pipeline.builds.map(&:name)).to match_array(%w[rspec echo])
expect(pipeline.user).to eq bridge.user
expect(pipeline.project).to eq bridge.project
expect(bridge.sourced_pipelines.first.pipeline).to eq pipeline
diff --git a/spec/workers/authorized_keys_worker_spec.rb b/spec/workers/authorized_keys_worker_spec.rb
index 2aaa6fb2ddf..4f1dde0bfc0 100644
--- a/spec/workers/authorized_keys_worker_spec.rb
+++ b/spec/workers/authorized_keys_worker_spec.rb
@@ -17,7 +17,7 @@ describe AuthorizedKeysWorker do
expect(instance).to receive(:add_key).with('foo', 'bar')
end
- worker.perform(:add_key, 'foo', 'bar')
+ worker.perform('add_key', 'foo', 'bar')
end
end
@@ -27,15 +27,17 @@ describe AuthorizedKeysWorker do
expect(instance).to receive(:remove_key).with('foo', 'bar')
end
- worker.perform(:remove_key, 'foo', 'bar')
+ worker.perform('remove_key', 'foo', 'bar')
end
end
describe 'all other commands' do
- it 'does nothing' do
+ it 'raises an error' do
expect(Gitlab::AuthorizedKeys).not_to receive(:new)
- worker.perform(:foo, 'bar', 'baz')
+ expect do
+ worker.perform('foo', 'bar', 'baz')
+ end.to raise_error('Unknown action: "foo"')
end
end
end
@@ -48,7 +50,7 @@ describe AuthorizedKeysWorker do
it 'does nothing' do
expect(Gitlab::AuthorizedKeys).not_to receive(:new)
- worker.perform(:add_key, 'foo', 'bar')
+ worker.perform('add_key', 'foo', 'bar')
end
end
end
diff --git a/spec/workers/gitlab_shell_worker_spec.rb b/spec/workers/gitlab_shell_worker_spec.rb
index f5884e5e8f8..0e63f48d3e8 100644
--- a/spec/workers/gitlab_shell_worker_spec.rb
+++ b/spec/workers/gitlab_shell_worker_spec.rb
@@ -12,7 +12,7 @@ describe GitlabShellWorker do
expect(instance).to receive(:add_key).with('foo', 'bar')
end
- worker.perform(:add_key, 'foo', 'bar')
+ worker.perform('add_key', 'foo', 'bar')
end
end
@@ -22,7 +22,7 @@ describe GitlabShellWorker do
expect(instance).to receive(:remove_key).with('foo', 'bar')
end
- worker.perform(:remove_key, 'foo', 'bar')
+ worker.perform('remove_key', 'foo', 'bar')
end
end
@@ -32,7 +32,7 @@ describe GitlabShellWorker do
expect(instance).to receive(:foo).with('bar', 'baz')
end
- worker.perform(:foo, 'bar', 'baz')
+ worker.perform('foo', 'bar', 'baz')
end
end
end
diff --git a/yarn.lock b/yarn.lock
index 7b3a0c5042f..8fc3c01afd7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1036,10 +1036,10 @@
"@sentry/types" "5.10.0"
tslib "^1.9.3"
-"@sourcegraph/code-host-integration@0.0.31":
- version "0.0.31"
- resolved "https://registry.yarnpkg.com/@sourcegraph/code-host-integration/-/code-host-integration-0.0.31.tgz#c4d6c7adaaf937e4b8a143c206020e110ba73e25"
- integrity sha512-b0WQ1CKlEx9S+IHRs1YNRO7CcwW06ulQU6D+W9cQlfjJu+qQVTAvkyv1xjySkfrCNK8IcfVd8WZzWIhP16VVfw==
+"@sourcegraph/code-host-integration@0.0.33":
+ version "0.0.33"
+ resolved "https://registry.yarnpkg.com/@sourcegraph/code-host-integration/-/code-host-integration-0.0.33.tgz#133f11535be0cc937fbadc6a6951ee9fd21fbe1d"
+ integrity sha512-J49ljHsSIe8KD5+ke9C3ugGO9T6R2M96miiGEZFRHJQ7FXyKi/zP5N4BFVweHjE+b15BLSicoaAnnyg4nhIBIw==
"@types/anymatch@*":
version "1.3.0"