From e549a7fb1f364395c20522e5395e22a2bf434ed0 Mon Sep 17 00:00:00 2001 From: Takuya Noguchi Date: Mon, 1 Jul 2019 18:49:53 +0900 Subject: Update mixin-deep to 1.3.2 To address a Prototype Pollution vulnerability, which exists in `mixin-deep` package, versions `>=2.0.0 <2.0.1 || <1.3.2` (CVE-2019-10746). - Diff: https://github.com/jonschlinkert/mixin-deep/compare/1.3.1...1.3.2 - Synk ID: https://app.snyk.io/vuln/SNYK-JS-MIXINDEEP-450212 Signed-off-by: Takuya Noguchi --- changelogs/unreleased/63945-update-mixin-deep-to-1-3-2.yml | 5 +++++ yarn.lock | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 changelogs/unreleased/63945-update-mixin-deep-to-1-3-2.yml diff --git a/changelogs/unreleased/63945-update-mixin-deep-to-1-3-2.yml b/changelogs/unreleased/63945-update-mixin-deep-to-1-3-2.yml new file mode 100644 index 00000000000..a0ef34f3700 --- /dev/null +++ b/changelogs/unreleased/63945-update-mixin-deep-to-1-3-2.yml @@ -0,0 +1,5 @@ +--- +title: Update mixin-deep to 1.3.2 +merge_request: 30223 +author: Takuya Noguchi +type: other diff --git a/yarn.lock b/yarn.lock index 07b4e20fc5f..901f7fbd6fb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7534,9 +7534,9 @@ mississippi@^3.0.0: through2 "^2.0.0" mixin-deep@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" - integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ== + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== dependencies: for-in "^1.0.2" is-extendable "^1.0.1" -- cgit v1.2.1 From 8f27b0b1109b84bacd482a75b9b7092ee5fd3660 Mon Sep 17 00:00:00 2001 From: Sarah Daily Date: Mon, 1 Jul 2019 20:09:07 +0000 Subject: Add relevant webcast to drive traffic and MQLs --- doc/user/project/clusters/index.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md index c6ee168bad0..581fa66d58c 100644 --- a/doc/user/project/clusters/index.md +++ b/doc/user/project/clusters/index.md @@ -5,6 +5,9 @@ Connect your project to Google Kubernetes Engine (GKE) or an existing Kubernetes cluster in a few steps. +NOTE: **Scalable app deployment with GitLab and Google Cloud Platform** +[Watch the webcast](https://about.gitlab.com/webcast/scalable-app-deploy/) and learn how to spin up a Kubernetes cluster managed by Google Cloud Platform (GCP) in a few clicks. + ## Overview With one or more Kubernetes clusters associated to your project, you can use -- cgit v1.2.1 From 4d02fb67ad942ccd910db80d57d015ec9a81a7d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jarka=20Ko=C5=A1anov=C3=A1?= Date: Fri, 28 Jun 2019 19:09:31 +0200 Subject: Update label note to support scoped labels notes - port of EE change --- app/models/label_note.rb | 18 +++++++++++++----- app/models/resource_label_event.rb | 7 +++++-- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/app/models/label_note.rb b/app/models/label_note.rb index d6814f4a948..ba5f1f82a81 100644 --- a/app/models/label_note.rb +++ b/app/models/label_note.rb @@ -62,19 +62,27 @@ class LabelNote < Note end def note_text(html: false) - added = labels_str('added', label_refs_by_action('add', html)) - removed = labels_str('removed', label_refs_by_action('remove', html)) + added = labels_str(label_refs_by_action('add', html), prefix: 'added', suffix: added_suffix) + removed = labels_str(label_refs_by_action('remove', html), prefix: removed_prefix) [added, removed].compact.join(' and ') end + def removed_prefix + 'removed' + end + + def added_suffix + '' + end + # returns string containing added/removed labels including # count of deleted labels: # # added ~1 ~2 + 1 deleted label # added 3 deleted labels # added ~1 ~2 labels - def labels_str(prefix, label_refs) + def labels_str(label_refs, prefix: '', suffix: '') existing_refs = label_refs.select { |ref| ref.present? }.sort refs_str = existing_refs.empty? ? nil : existing_refs.join(' ') @@ -84,9 +92,9 @@ class LabelNote < Note return unless refs_str || deleted_str label_list_str = [refs_str, deleted_str].compact.join(' + ') - suffix = 'label'.pluralize(deleted > 0 ? deleted : existing_refs.count) + suffix += ' label'.pluralize(deleted > 0 ? deleted : existing_refs.count) - "#{prefix} #{label_list_str} #{suffix}" + "#{prefix} #{label_list_str} #{suffix.squish}" end def label_refs_by_action(action, html) diff --git a/app/models/resource_label_event.rb b/app/models/resource_label_event.rb index f2c7cb6a65d..ad08f4763ae 100644 --- a/app/models/resource_label_event.rb +++ b/app/models/resource_label_event.rb @@ -36,10 +36,9 @@ class ResourceLabelEvent < ApplicationRecord issue || merge_request end - # create same discussion id for all actions with the same user and time def discussion_id(resource = nil) strong_memoize(:discussion_id) do - Digest::SHA1.hexdigest([self.class.name, created_at, user_id].join("-")) + Digest::SHA1.hexdigest(discussion_id_key.join("-")) end end @@ -121,4 +120,8 @@ class ResourceLabelEvent < ApplicationRecord def resource_parent issuable.project || issuable.group end + + def discussion_id_key + [self.class.name, created_at, user_id] + end end -- cgit v1.2.1 From 93182f4f06fa35d83a8b1467a846aa123ad82e3e Mon Sep 17 00:00:00 2001 From: Sanad Liaquat Date: Wed, 3 Jul 2019 15:12:53 +0500 Subject: Raise error on api call failure --- qa/qa/tools/generate_perf_testdata.rb | 63 ++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/qa/qa/tools/generate_perf_testdata.rb b/qa/qa/tools/generate_perf_testdata.rb index b0477951967..1b053622f1b 100644 --- a/qa/qa/tools/generate_perf_testdata.rb +++ b/qa/qa/tools/generate_perf_testdata.rb @@ -196,6 +196,7 @@ module QA project_path = "#{@group_name}%2F#{@project_name}" branch_name = "branch_with_many_commits-#{SecureRandom.hex(8)}" file_name = "file_for_many_commits.txt" + create_a_branch_api_req(branch_name, project_path) create_a_new_file_api_req(file_name, branch_name, project_path, "Initial commit for new file", "Initial file content") create_mr_response = create_a_merge_request_api_req(project_path, branch_name, "master", "MR with many commits-#{SecureRandom.hex(8)}") @@ -203,7 +204,7 @@ module QA 100.times do |i| update_file_api_req(file_name, branch_name, project_path, Faker::Lorem.sentences(5).join(" "), Faker::Lorem.sentences(500).join("\n")) end - STDOUT.puts "Created an MR with many commits: #{@urls[:mr_with_many_commits]}" + STDOUT.puts "Using branch: #{branch_name}, created an MR with many commits: #{@urls[:mr_with_many_commits]}" end private @@ -211,56 +212,88 @@ module QA # API Requests def create_a_discussion_on_issue_api_req(project_path_or_id, issue_id, body) - post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/issues/#{issue_id}/discussions").url, "body=\"#{body}\"" + call_api(expected_response_code: 201) do + post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/issues/#{issue_id}/discussions").url, "body=\"#{body}\"" + end end def update_a_discussion_on_issue_api_req(project_path_or_id, mr_iid, discussion_id, resolved_status) - put Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/merge_requests/#{mr_iid}/discussions/#{discussion_id}").url, "resolved=#{resolved_status}" + call_api(expected_response_code: 200) do + put Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/merge_requests/#{mr_iid}/discussions/#{discussion_id}").url, "resolved=#{resolved_status}" + end end def create_a_discussion_on_mr_api_req(project_path_or_id, mr_iid, body) - post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/merge_requests/#{mr_iid}/discussions").url, - "body=\"#{body}\"" + call_api(expected_response_code: 201) do + post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/merge_requests/#{mr_iid}/discussions").url, "body=\"#{body}\"" + end end def create_a_label_api_req(project_path_or_id, name, color) - post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/labels").url, "name=#{name}&color=#{color}" + call_api(expected_response_code: 201) do + post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/labels").url, "name=#{name}&color=#{color}" + end end def create_a_todo_api_req(project_path_or_id, issue_id) - post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/issues/#{issue_id}/todo").url, nil + call_api(expected_response_code: 201) do + post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/issues/#{issue_id}/todo").url, nil + end end def create_an_issue_api_req(project_path_or_id, title, description) - post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/issues").url, "title=#{title}&description=#{description}" + call_api(expected_response_code: 201) do + post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/issues").url, "title=#{title}&description=#{description}" + end end def update_an_issue_api_req(project_path_or_id, issue_id, description, labels_list) - put Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/issues/#{issue_id}").url, "description=#{description}&labels=#{labels_list}" + call_api(expected_response_code: 200) do + put Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/issues/#{issue_id}").url, "description=#{description}&labels=#{labels_list}" + end end def create_a_project_api_req(project_name, group_id, visibility) - post Runtime::API::Request.new(@api_client, "/projects").url, "name=#{project_name}&namespace_id=#{group_id}&visibility=#{visibility}" + call_api(expected_response_code: 201) do + post Runtime::API::Request.new(@api_client, "/projects").url, "name=#{project_name}&namespace_id=#{group_id}&visibility=#{visibility}" + end end def create_a_group_api_req(group_name, visibility) - post Runtime::API::Request.new(@api_client, "/groups").url, "name=#{group_name}&path=#{group_name}&visibility=#{visibility}" + call_api(expected_response_code: 201) do + post Runtime::API::Request.new(@api_client, "/groups").url, "name=#{group_name}&path=#{group_name}&visibility=#{visibility}" + end end def create_a_branch_api_req(branch_name, project_path_or_id) - post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/repository/branches").url, "branch=#{branch_name}&ref=master" + call_api(expected_response_code: 201) do + post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/repository/branches").url, "branch=#{branch_name}&ref=master" + end end def create_a_new_file_api_req(file_path, branch_name, project_path_or_id, commit_message, content) - post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/repository/files/#{file_path}").url, "branch=#{branch_name}&commit_message=\"#{commit_message}\"&content=\"#{content}\"" + call_api(expected_response_code: 201) do + post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/repository/files/#{file_path}").url, "branch=#{branch_name}&commit_message=\"#{commit_message}\"&content=\"#{content}\"" + end end def create_a_merge_request_api_req(project_path_or_id, source_branch, target_branch, mr_title) - post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/merge_requests").url, "source_branch=#{source_branch}&target_branch=#{target_branch}&title=#{mr_title}" + call_api(expected_response_code: 201) do + post Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/merge_requests").url, "source_branch=#{source_branch}&target_branch=#{target_branch}&title=#{mr_title}" + end end def update_file_api_req(file_path, branch_name, project_path_or_id, commit_message, content) - put Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/repository/files/#{file_path}").url, "branch=#{branch_name}&commit_message=\"#{commit_message}\"&content=\"#{content}\"" + call_api(expected_response_code: 200) do + put Runtime::API::Request.new(@api_client, "/projects/#{project_path_or_id}/repository/files/#{file_path}").url, "branch=#{branch_name}&commit_message=\"#{commit_message}\"&content=\"#{content}\"" + end + end + + def call_api(expected_response_code: 200) + response = yield + raise "API call failed with response code: #{response.code} and body: #{response.body}" unless response.code == expected_response_code + + response end end end -- cgit v1.2.1 From 1e225340190187c96960e138ab218504165cb351 Mon Sep 17 00:00:00 2001 From: Sanad Liaquat Date: Wed, 3 Jul 2019 18:22:55 +0500 Subject: Return created group id --- qa/qa/tools/generate_perf_testdata.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qa/qa/tools/generate_perf_testdata.rb b/qa/qa/tools/generate_perf_testdata.rb index 1b053622f1b..26bcb2fe958 100644 --- a/qa/qa/tools/generate_perf_testdata.rb +++ b/qa/qa/tools/generate_perf_testdata.rb @@ -59,8 +59,8 @@ module QA group_search_response = create_a_group_api_req(@group_name, @visibility) group = JSON.parse(group_search_response.body) @urls[:group_page] = group["web_url"] - group["id"] STDOUT.puts "Created a group: #{@urls[:group_page]}" + group["id"] end def create_project(group_id) -- cgit v1.2.1 From 26b7b475586b67c9e9aee7ec7311cca712901dbc Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Wed, 15 May 2019 13:19:16 +0200 Subject: Add *_access_level to project API - issues_access_level - repository_access_level - merge_requests_access_level - builds_access_level - wiki_access_level - snippets_access_level --- .../concerns/project_features_compatibility.rb | 54 ++++++++++++++++++---- app/models/project_feature.rb | 18 ++++++++ doc/api/projects.md | 48 +++++++++++++------ lib/api/entities.rb | 8 ++++ lib/api/helpers/projects_helpers.rb | 33 ++++++++++--- .../project_features_compatibility_spec.rb | 18 ++++++-- spec/requests/api/projects_spec.rb | 16 +++++++ 7 files changed, 160 insertions(+), 35 deletions(-) diff --git a/app/models/concerns/project_features_compatibility.rb b/app/models/concerns/project_features_compatibility.rb index f268a842db4..551a2e56ecf 100644 --- a/app/models/concerns/project_features_compatibility.rb +++ b/app/models/concerns/project_features_compatibility.rb @@ -9,32 +9,70 @@ require 'gitlab/utils' module ProjectFeaturesCompatibility extend ActiveSupport::Concern + # TODO: remove in API v5, replaced by *_access_level def wiki_enabled=(value) - write_feature_attribute(:wiki_access_level, value) + write_feature_attribute_boolean(:wiki_access_level, value) end + # TODO: remove in API v5, replaced by *_access_level def builds_enabled=(value) - write_feature_attribute(:builds_access_level, value) + write_feature_attribute_boolean(:builds_access_level, value) end + # TODO: remove in API v5, replaced by *_access_level def merge_requests_enabled=(value) - write_feature_attribute(:merge_requests_access_level, value) + write_feature_attribute_boolean(:merge_requests_access_level, value) end + # TODO: remove in API v5, replaced by *_access_level def issues_enabled=(value) - write_feature_attribute(:issues_access_level, value) + write_feature_attribute_boolean(:issues_access_level, value) end + # TODO: remove in API v5, replaced by *_access_level def snippets_enabled=(value) - write_feature_attribute(:snippets_access_level, value) + write_feature_attribute_boolean(:snippets_access_level, value) + end + + def repository_access_level=(value) + write_feature_attribute_string(:repository_access_level, value) + end + + def wiki_access_level=(value) + write_feature_attribute_string(:wiki_access_level, value) + end + + def builds_access_level=(value) + write_feature_attribute_string(:builds_access_level, value) + end + + def merge_requests_access_level=(value) + write_feature_attribute_string(:merge_requests_access_level, value) + end + + def issues_access_level=(value) + write_feature_attribute_string(:issues_access_level, value) + end + + def snippets_access_level=(value) + write_feature_attribute_string(:snippets_access_level, value) end private - def write_feature_attribute(field, value) + def write_feature_attribute_boolean(field, value) + access_level = Gitlab::Utils.to_boolean(value) ? ProjectFeature::ENABLED : ProjectFeature::DISABLED + write_feature_attribute_raw(field, access_level) + end + + def write_feature_attribute_string(field, value) + access_level = ProjectFeature.access_level_from_str(value) + write_feature_attribute_raw(field, access_level) + end + + def write_feature_attribute_raw(field, value) build_project_feature unless project_feature - access_level = Gitlab::Utils.to_boolean(value) ? ProjectFeature::ENABLED : ProjectFeature::DISABLED - project_feature.__send__(:write_attribute, field, access_level) # rubocop:disable GitlabSecurity/PublicSend + project_feature.__send__(:write_attribute, field, value) # rubocop:disable GitlabSecurity/PublicSend end end diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb index 0542581c6e0..7ff06655de0 100644 --- a/app/models/project_feature.rb +++ b/app/models/project_feature.rb @@ -24,6 +24,12 @@ class ProjectFeature < ApplicationRecord FEATURES = %i(issues merge_requests wiki snippets builds repository pages).freeze PRIVATE_FEATURES_MIN_ACCESS_LEVEL = { merge_requests: Gitlab::Access::REPORTER }.freeze + STRING_OPTIONS = HashWithIndifferentAccess.new({ + 'disabled' => DISABLED, + 'private' => PRIVATE, + 'enabled' => ENABLED, + 'public' => PUBLIC + }).freeze class << self def access_level_attribute(feature) @@ -45,6 +51,14 @@ class ProjectFeature < ApplicationRecord PRIVATE_FEATURES_MIN_ACCESS_LEVEL.fetch(feature, Gitlab::Access::GUEST) end + def access_level_from_str(level) + STRING_OPTIONS.fetch(level) + end + + def str_from_access_level(level) + STRING_OPTIONS.key(level) + end + private def ensure_feature!(feature) @@ -83,6 +97,10 @@ class ProjectFeature < ApplicationRecord public_send(ProjectFeature.access_level_attribute(feature)) # rubocop:disable GitlabSecurity/PublicSend end + def string_access_level(feature) + ProjectFeature.str_from_access_level(access_level(feature)) + end + def builds_enabled? builds_access_level > DISABLED end diff --git a/doc/api/projects.md b/doc/api/projects.md index b8ccf25581e..702a89c3bba 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -708,11 +708,17 @@ POST /projects | `namespace_id` | integer | no | Namespace for the new project (defaults to the current user's namespace) | | `default_branch` | string | no | `master` by default | | `description` | string | no | Short project description | -| `issues_enabled` | boolean | no | Enable issues for this project | -| `merge_requests_enabled` | boolean | no | Enable merge requests for this project | -| `jobs_enabled` | boolean | no | Enable jobs for this project | -| `wiki_enabled` | boolean | no | Enable wiki for this project | -| `snippets_enabled` | boolean | no | Enable snippets for this project | +| `issues_enabled` | boolean | no | (deprecated) Enable issues for this project. Use `issues_access_level` instead | +| `merge_requests_enabled` | boolean | no | (deprecated) Enable merge requests for this project. Use `merge_requests_access_level` instead | +| `jobs_enabled` | boolean | no | (deprecated) Enable jobs for this project. Use `builds_access_level` instead | +| `wiki_enabled` | boolean | no | (deprecated) Enable wiki for this project. Use `wiki_access_level` instead | +| `snippets_enabled` | boolean | no | (deprecated) Enable snippets for this project. Use `snippets_access_level` instead | +| `issues_access_level` | string | no | One of `disabled`, `private` or `enabled` | +| `repository_access_level` | string | no | One of `disabled`, `private` or `enabled` | +| `merge_requests_access_level` | string | no | One of `disabled`, `private` or `enabled` | +| `builds_access_level` | string | no | One of `disabled`, `private` or `enabled` | +| `wiki_access_level` | string | no | One of `disabled`, `private` or `enabled` | +| `snippets_access_level` | string | no | One of `disabled`, `private` or `enabled` | | `resolve_outdated_diff_discussions` | boolean | no | Automatically resolve merge request diffs discussions on lines changed with a push | | `container_registry_enabled` | boolean | no | Enable container registry for this project | | `shared_runners_enabled` | boolean | no | Enable shared runners for this project | @@ -753,11 +759,17 @@ POST /projects/user/:user_id | `path` | string | no | Custom repository name for new project. By default generated based on name | | `namespace_id` | integer | no | Namespace for the new project (defaults to the current user's namespace) | | `description` | string | no | Short project description | -| `issues_enabled` | boolean | no | Enable issues for this project | -| `merge_requests_enabled` | boolean | no | Enable merge requests for this project | -| `jobs_enabled` | boolean | no | Enable jobs for this project | -| `wiki_enabled` | boolean | no | Enable wiki for this project | -| `snippets_enabled` | boolean | no | Enable snippets for this project | +| `issues_enabled` | boolean | no | (deprecated) Enable issues for this project. Use `issues_access_level` instead | +| `merge_requests_enabled` | boolean | no | (deprecated) Enable merge requests for this project. Use `merge_requests_access_level` instead | +| `jobs_enabled` | boolean | no | (deprecated) Enable jobs for this project. Use `builds_access_level` instead | +| `wiki_enabled` | boolean | no | (deprecated) Enable wiki for this project. Use `wiki_access_level` instead | +| `snippets_enabled` | boolean | no | (deprecated) Enable snippets for this project. Use `snippets_access_level` instead | +| `issues_access_level` | string | no | One of `disabled`, `private` or `enabled` | +| `repository_access_level` | string | no | One of `disabled`, `private` or `enabled` | +| `merge_requests_access_level` | string | no | One of `disabled`, `private` or `enabled` | +| `builds_access_level` | string | no | One of `disabled`, `private` or `enabled` | +| `wiki_access_level` | string | no | One of `disabled`, `private` or `enabled` | +| `snippets_access_level` | string | no | One of `disabled`, `private` or `enabled` | | `resolve_outdated_diff_discussions` | boolean | no | Automatically resolve merge request diffs discussions on lines changed with a push | | `container_registry_enabled` | boolean | no | Enable container registry for this project | | `shared_runners_enabled` | boolean | no | Enable shared runners for this project | @@ -798,11 +810,17 @@ PUT /projects/:id | `path` | string | no | Custom repository name for the project. By default generated based on name | | `default_branch` | string | no | `master` by default | | `description` | string | no | Short project description | -| `issues_enabled` | boolean | no | Enable issues for this project | -| `merge_requests_enabled` | boolean | no | Enable merge requests for this project | -| `jobs_enabled` | boolean | no | Enable jobs for this project | -| `wiki_enabled` | boolean | no | Enable wiki for this project | -| `snippets_enabled` | boolean | no | Enable snippets for this project | +| `issues_enabled` | boolean | no | (deprecated) Enable issues for this project. Use `issues_access_level` instead | +| `merge_requests_enabled` | boolean | no | (deprecated) Enable merge requests for this project. Use `merge_requests_access_level` instead | +| `jobs_enabled` | boolean | no | (deprecated) Enable jobs for this project. Use `builds_access_level` instead | +| `wiki_enabled` | boolean | no | (deprecated) Enable wiki for this project. Use `wiki_access_level` instead | +| `snippets_enabled` | boolean | no | (deprecated) Enable snippets for this project. Use `snippets_access_level` instead | +| `issues_access_level` | string | no | One of `disabled`, `private` or `enabled` | +| `repository_access_level` | string | no | One of `disabled`, `private` or `enabled` | +| `merge_requests_access_level` | string | no | One of `disabled`, `private` or `enabled` | +| `builds_access_level` | string | no | One of `disabled`, `private` or `enabled` | +| `wiki_access_level` | string | no | One of `disabled`, `private` or `enabled` | +| `snippets_access_level` | string | no | One of `disabled`, `private` or `enabled` | | `resolve_outdated_diff_discussions` | boolean | no | Automatically resolve merge request diffs discussions on lines changed with a push | | `container_registry_enabled` | boolean | no | Enable container registry for this project | | `shared_runners_enabled` | boolean | no | Enable shared runners for this project | diff --git a/lib/api/entities.rb b/lib/api/entities.rb index b9aa387ba61..4bd4442a76e 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -247,12 +247,20 @@ module API expose :container_registry_enabled # Expose old field names with the new permissions methods to keep API compatible + # TODO: remove in API v5, replaced by *_access_level expose(:issues_enabled) { |project, options| project.feature_available?(:issues, options[:current_user]) } expose(:merge_requests_enabled) { |project, options| project.feature_available?(:merge_requests, options[:current_user]) } expose(:wiki_enabled) { |project, options| project.feature_available?(:wiki, options[:current_user]) } expose(:jobs_enabled) { |project, options| project.feature_available?(:builds, options[:current_user]) } expose(:snippets_enabled) { |project, options| project.feature_available?(:snippets, options[:current_user]) } + expose(:issues_access_level) { |project, options| project.project_feature.string_access_level(:issues) } + expose(:repository_access_level) { |project, options| project.project_feature.string_access_level(:repository) } + expose(:merge_requests_access_level) { |project, options| project.project_feature.string_access_level(:merge_requests) } + expose(:wiki_access_level) { |project, options| project.project_feature.string_access_level(:wiki) } + expose(:builds_access_level) { |project, options| project.project_feature.string_access_level(:builds) } + expose(:snippets_access_level) { |project, options| project.project_feature.string_access_level(:snippets) } + expose :shared_runners_enabled expose :lfs_enabled?, as: :lfs_enabled expose :creator_id diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb index f242f1fea0e..36d93d9457f 100644 --- a/lib/api/helpers/projects_helpers.rb +++ b/lib/api/helpers/projects_helpers.rb @@ -9,11 +9,21 @@ module API params :optional_project_params_ce do optional :description, type: String, desc: 'The description of the project' optional :ci_config_path, type: String, desc: 'The path to CI config file. Defaults to `.gitlab-ci.yml`' + + # TODO: remove in API v5, replaced by *_access_level optional :issues_enabled, type: Boolean, desc: 'Flag indication if the issue tracker is enabled' optional :merge_requests_enabled, type: Boolean, desc: 'Flag indication if merge requests are enabled' optional :wiki_enabled, type: Boolean, desc: 'Flag indication if the wiki is enabled' optional :jobs_enabled, type: Boolean, desc: 'Flag indication if jobs are enabled' optional :snippets_enabled, type: Boolean, desc: 'Flag indication if snippets are enabled' + + optional :issues_access_level, type: String, values: %w(disabled private enabled), desc: 'Issues access level. One of `disabled`, `private` or `enabled`' + optional :repository_access_level, type: String, values: %w(disabled private enabled), desc: 'Repository access level. One of `disabled`, `private` or `enabled`' + optional :merge_requests_access_level, type: String, values: %w(disabled private enabled), desc: 'Merge requests access level. One of `disabled`, `private` or `enabled`' + optional :wiki_access_level, type: String, values: %w(disabled private enabled), desc: 'Wiki access level. One of `disabled`, `private` or `enabled`' + optional :builds_access_level, type: String, values: %w(disabled private enabled), desc: 'Builds access level. One of `disabled`, `private` or `enabled`' + optional :snippets_access_level, type: String, values: %w(disabled private enabled), desc: 'Snippets access level. One of `disabled`, `private` or `enabled`' + optional :shared_runners_enabled, type: Boolean, desc: 'Flag indication if shared runners are enabled for that project' optional :resolve_outdated_diff_discussions, type: Boolean, desc: 'Automatically resolve merge request diffs discussions on lines changed with a push' optional :container_registry_enabled, type: Boolean, desc: 'Flag indication if the container registry is enabled for that project' @@ -48,15 +58,14 @@ module API def self.update_params_at_least_one_of [ - :jobs_enabled, - :resolve_outdated_diff_discussions, + :builds_access_level, :ci_config_path, :container_registry_enabled, :default_branch, :description, - :issues_enabled, + :issues_access_level, :lfs_enabled, - :merge_requests_enabled, + :merge_requests_access_level, :merge_method, :name, :only_allow_merge_if_all_discussions_are_resolved, @@ -64,14 +73,24 @@ module API :path, :printing_merge_request_link_enabled, :public_builds, + :repository_access_level, :request_access_enabled, + :resolve_outdated_diff_discussions, :shared_runners_enabled, - :snippets_enabled, + :snippets_access_level, :tag_list, :visibility, - :wiki_enabled, + :wiki_access_level, :avatar, - :external_authorization_classification_label + :external_authorization_classification_label, + + # TODO: remove in API v5, replaced by *_access_level + :issues_enabled, + :jobs_enabled, + :merge_requests_enabled, + :wiki_enabled, + :jobs_enabled, + :snippets_enabled ] end end diff --git a/spec/models/concerns/project_features_compatibility_spec.rb b/spec/models/concerns/project_features_compatibility_spec.rb index 5aa43b58217..1fe176ab5af 100644 --- a/spec/models/concerns/project_features_compatibility_spec.rb +++ b/spec/models/concerns/project_features_compatibility_spec.rb @@ -4,7 +4,8 @@ require 'spec_helper' describe ProjectFeaturesCompatibility do let(:project) { create(:project) } - let(:features) { %w(issues wiki builds merge_requests snippets) } + let(:features_except_repository) { %w(issues wiki builds merge_requests snippets) } + let(:features) { features_except_repository + ['repository'] } # We had issues_enabled, snippets_enabled, builds_enabled, merge_requests_enabled and issues_enabled fields on projects table # All those fields got moved to a new table called project_feature and are now integers instead of booleans @@ -12,30 +13,37 @@ describe ProjectFeaturesCompatibility do # So we can keep it compatible it "converts fields from 'true' to ProjectFeature::ENABLED" do - features.each do |feature| + features_except_repository.each do |feature| project.update_attribute("#{feature}_enabled".to_sym, "true") expect(project.project_feature.public_send("#{feature}_access_level")).to eq(ProjectFeature::ENABLED) end end it "converts fields from 'false' to ProjectFeature::DISABLED" do - features.each do |feature| + features_except_repository.each do |feature| project.update_attribute("#{feature}_enabled".to_sym, "false") expect(project.project_feature.public_send("#{feature}_access_level")).to eq(ProjectFeature::DISABLED) end end it "converts fields from true to ProjectFeature::ENABLED" do - features.each do |feature| + features_except_repository.each do |feature| project.update_attribute("#{feature}_enabled".to_sym, true) expect(project.project_feature.public_send("#{feature}_access_level")).to eq(ProjectFeature::ENABLED) end end it "converts fields from false to ProjectFeature::DISABLED" do - features.each do |feature| + features_except_repository.each do |feature| project.update_attribute("#{feature}_enabled".to_sym, false) expect(project.project_feature.public_send("#{feature}_access_level")).to eq(ProjectFeature::DISABLED) end end + + it "accepts private as ProjectFeature::PRIVATE" do + features.each do |feature| + project.update!("#{feature}_access_level".to_sym => 'private') + expect(project.project_feature.public_send("#{feature}_access_level")).to eq(ProjectFeature::PRIVATE) + end + end end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 5f7d2fa6d9c..978e5fffc73 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -1102,6 +1102,12 @@ describe API::Projects do expect(json_response['wiki_enabled']).to be_present expect(json_response['jobs_enabled']).to be_present expect(json_response['snippets_enabled']).to be_present + expect(json_response['snippets_access_level']).to be_present + expect(json_response['repository_access_level']).to be_present + expect(json_response['issues_access_level']).to be_present + expect(json_response['merge_requests_access_level']).to be_present + expect(json_response['wiki_access_level']).to be_present + expect(json_response['builds_access_level']).to be_present expect(json_response['resolve_outdated_diff_discussions']).to eq(project.resolve_outdated_diff_discussions) expect(json_response['container_registry_enabled']).to be_present expect(json_response['created_at']).to be_present @@ -1913,6 +1919,16 @@ describe API::Projects do end end + it 'updates builds_access_level' do + project_param = { builds_access_level: 'private' } + + put api("/projects/#{project3.id}", user), params: project_param + + expect(response).to have_gitlab_http_status(200) + + expect(json_response['builds_access_level']).to eq('private') + end + it 'updates merge_method' do project_param = { merge_method: 'ff' } -- cgit v1.2.1 From 353e68772c8b57ef4a98be094f2674d28a2dedcd Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Wed, 15 May 2019 14:35:55 +0200 Subject: Add build_git_strategy attribute to project API We map the boolean to the string 'fetch' or 'clone', to be more explicit. --- app/models/concerns/project_api_compatibility.rb | 10 ++++++++++ app/models/project.rb | 1 + doc/api/projects.md | 3 +++ lib/api/entities.rb | 3 +++ lib/api/helpers/projects_helpers.rb | 2 ++ spec/models/concerns/project_api_compatibility_spec.rb | 17 +++++++++++++++++ spec/requests/api/projects_spec.rb | 18 ++++++++++++++++++ 7 files changed, 54 insertions(+) create mode 100644 app/models/concerns/project_api_compatibility.rb create mode 100644 spec/models/concerns/project_api_compatibility_spec.rb diff --git a/app/models/concerns/project_api_compatibility.rb b/app/models/concerns/project_api_compatibility.rb new file mode 100644 index 00000000000..9a0202c211c --- /dev/null +++ b/app/models/concerns/project_api_compatibility.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +# Add methods used by the projects API +module ProjectAPICompatibility + extend ActiveSupport::Concern + + def build_git_strategy=(value) + write_attribute(:build_allow_git_fetch, value == 'fetch') + end +end diff --git a/app/models/project.rb b/app/models/project.rb index 0f4fba5d0b6..822def0f936 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -15,6 +15,7 @@ class Project < ApplicationRecord include CaseSensitivity include TokenAuthenticatable include ValidAttribute + include ProjectAPICompatibility include ProjectFeaturesCompatibility include SelectForProjectAuthorization include Presentable diff --git a/doc/api/projects.md b/doc/api/projects.md index 702a89c3bba..88fa45cc6fa 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -733,6 +733,7 @@ POST /projects | `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project | | `avatar` | mixed | no | Image file for avatar of the project | | `printing_merge_request_link_enabled` | boolean | no | Show link to create/view merge request when pushing from the command line | +| `build_git_strategy` | string | no | The Git strategy. Defaults to `fetch` | | `ci_config_path` | string | no | The path to CI config file | | `repository_storage` | string | no | Which storage shard the repository is on. Available only to admins | | `approvals_before_merge` | integer | no | **[STARTER]** How many approvers should approve merge requests by default | @@ -784,6 +785,7 @@ POST /projects/user/:user_id | `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project | | `avatar` | mixed | no | Image file for avatar of the project | | `printing_merge_request_link_enabled` | boolean | no | Show link to create/view merge request when pushing from the command line | +| `build_git_strategy` | string | no | The Git strategy. Defaults to `fetch` | | `ci_config_path` | string | no | The path to CI config file | | `repository_storage` | string | no | Which storage shard the repository is on. Available only to admins | | `approvals_before_merge` | integer | no | **[STARTER]** How many approvers should approve merge requests by default | @@ -834,6 +836,7 @@ PUT /projects/:id | `request_access_enabled` | boolean | no | Allow users to request member access | | `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project | | `avatar` | mixed | no | Image file for avatar of the project | +| `build_git_strategy` | string | no | The Git strategy. Defaults to `fetch` | | `ci_config_path` | string | no | The path to CI config file | | `ci_default_git_depth` | integer | no | Default number of revisions for [shallow cloning](../user/project/pipelines/settings.md#git-shallow-clone) | | `repository_storage` | string | no | Which storage shard the repository is on. Available only to admins | diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 4bd4442a76e..0389ff0e045 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -275,6 +275,9 @@ module API expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] } expose :ci_default_git_depth expose :public_builds, as: :public_jobs + expose :build_git_strategy, if: lambda { |project, options| options[:user_can_admin_project] } do |project, options| + project.build_allow_git_fetch ? 'fetch' : 'clone' + end expose :ci_config_path, if: -> (project, options) { Ability.allowed?(options[:current_user], :download_code, project) } expose :shared_with_groups do |project, options| SharedGroup.represent(project.project_group_links, options) diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb index 36d93d9457f..bc847968c25 100644 --- a/lib/api/helpers/projects_helpers.rb +++ b/lib/api/helpers/projects_helpers.rb @@ -8,6 +8,7 @@ module API params :optional_project_params_ce do optional :description, type: String, desc: 'The description of the project' + optional :build_git_strategy, type: String, values: %w(fetch clone), desc: 'The Git strategy. Defaults to `fetch`' optional :ci_config_path, type: String, desc: 'The path to CI config file. Defaults to `.gitlab-ci.yml`' # TODO: remove in API v5, replaced by *_access_level @@ -58,6 +59,7 @@ module API def self.update_params_at_least_one_of [ + :build_git_strategy, :builds_access_level, :ci_config_path, :container_registry_enabled, diff --git a/spec/models/concerns/project_api_compatibility_spec.rb b/spec/models/concerns/project_api_compatibility_spec.rb new file mode 100644 index 00000000000..a999f60a1f3 --- /dev/null +++ b/spec/models/concerns/project_api_compatibility_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe ProjectAPICompatibility do + let(:project) { create(:project) } + + it "converts build_git_strategy=fetch to build_allow_git_fetch=true" do + project.update!(:build_git_strategy, 'fetch') + expect(project.build_allow_git_fetch).to eq(true) + end + + it "converts build_git_strategy=clone to build_allow_git_fetch=false" do + project.update!(:build_git_strategy, 'clone') + expect(project.build_allow_git_fetch).to eq(false) + end +end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 978e5fffc73..2fc257a1a06 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -1929,6 +1929,24 @@ describe API::Projects do expect(json_response['builds_access_level']).to eq('private') end + it 'updates build_git_strategy' do + project_param = { build_git_strategy: 'clone' } + + put api("/projects/#{project3.id}", user), params: project_param + + expect(response).to have_gitlab_http_status(200) + + expect(json_response['build_git_strategy']).to eq('clone') + end + + it 'rejects to update build_git_strategy when build_git_strategy is invalid' do + project_param = { build_git_strategy: 'invalid' } + + put api("/projects/#{project3.id}", user), params: project_param + + expect(response).to have_gitlab_http_status(400) + end + it 'updates merge_method' do project_param = { merge_method: 'ff' } -- cgit v1.2.1 From a7892e71714ad0f425547db12f205771dc270da5 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Wed, 15 May 2019 15:32:18 +0200 Subject: Add build_timeout to project API --- doc/api/projects.md | 3 +++ lib/api/entities.rb | 1 + lib/api/helpers/projects_helpers.rb | 2 ++ 3 files changed, 6 insertions(+) diff --git a/doc/api/projects.md b/doc/api/projects.md index 88fa45cc6fa..3c31cfb98b8 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -734,6 +734,7 @@ POST /projects | `avatar` | mixed | no | Image file for avatar of the project | | `printing_merge_request_link_enabled` | boolean | no | Show link to create/view merge request when pushing from the command line | | `build_git_strategy` | string | no | The Git strategy. Defaults to `fetch` | +| `build_timeout` | integer | no | The maximum amount of time in minutes that a job is able run (in seconds) | | `ci_config_path` | string | no | The path to CI config file | | `repository_storage` | string | no | Which storage shard the repository is on. Available only to admins | | `approvals_before_merge` | integer | no | **[STARTER]** How many approvers should approve merge requests by default | @@ -786,6 +787,7 @@ POST /projects/user/:user_id | `avatar` | mixed | no | Image file for avatar of the project | | `printing_merge_request_link_enabled` | boolean | no | Show link to create/view merge request when pushing from the command line | | `build_git_strategy` | string | no | The Git strategy. Defaults to `fetch` | +| `build_timeout` | integer | no | The maximum amount of time in minutes that a job is able run (in seconds) | | `ci_config_path` | string | no | The path to CI config file | | `repository_storage` | string | no | Which storage shard the repository is on. Available only to admins | | `approvals_before_merge` | integer | no | **[STARTER]** How many approvers should approve merge requests by default | @@ -837,6 +839,7 @@ PUT /projects/:id | `tag_list` | array | no | The list of tags for a project; put array of tags, that should be finally assigned to a project | | `avatar` | mixed | no | Image file for avatar of the project | | `build_git_strategy` | string | no | The Git strategy. Defaults to `fetch` | +| `build_timeout` | integer | no | The maximum amount of time in minutes that a job is able run (in seconds) | | `ci_config_path` | string | no | The path to CI config file | | `ci_default_git_depth` | integer | no | Default number of revisions for [shallow cloning](../user/project/pipelines/settings.md#git-shallow-clone) | | `repository_storage` | string | no | Which storage shard the repository is on. Available only to admins | diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 0389ff0e045..3bfaf63d912 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -278,6 +278,7 @@ module API expose :build_git_strategy, if: lambda { |project, options| options[:user_can_admin_project] } do |project, options| project.build_allow_git_fetch ? 'fetch' : 'clone' end + expose :build_timeout expose :ci_config_path, if: -> (project, options) { Ability.allowed?(options[:current_user], :download_code, project) } expose :shared_with_groups do |project, options| SharedGroup.represent(project.project_group_links, options) diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb index bc847968c25..7a806839856 100644 --- a/lib/api/helpers/projects_helpers.rb +++ b/lib/api/helpers/projects_helpers.rb @@ -9,6 +9,7 @@ module API params :optional_project_params_ce do optional :description, type: String, desc: 'The description of the project' optional :build_git_strategy, type: String, values: %w(fetch clone), desc: 'The Git strategy. Defaults to `fetch`' + optional :build_timeout, type: Integer, desc: 'Build timeout' optional :ci_config_path, type: String, desc: 'The path to CI config file. Defaults to `.gitlab-ci.yml`' # TODO: remove in API v5, replaced by *_access_level @@ -60,6 +61,7 @@ module API def self.update_params_at_least_one_of [ :build_git_strategy, + :build_timeout, :builds_access_level, :ci_config_path, :container_registry_enabled, -- cgit v1.2.1 From 5f04d24934770e9aa366aac1400a302232eefd89 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Wed, 15 May 2019 15:36:17 +0200 Subject: Add build_coverage_regex to project API --- doc/api/projects.md | 3 +++ lib/api/entities.rb | 1 + lib/api/helpers/projects_helpers.rb | 2 ++ 3 files changed, 6 insertions(+) diff --git a/doc/api/projects.md b/doc/api/projects.md index 3c31cfb98b8..316a1fb56ed 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -735,6 +735,7 @@ POST /projects | `printing_merge_request_link_enabled` | boolean | no | Show link to create/view merge request when pushing from the command line | | `build_git_strategy` | string | no | The Git strategy. Defaults to `fetch` | | `build_timeout` | integer | no | The maximum amount of time in minutes that a job is able run (in seconds) | +| `build_coverage_regex` | string | no | Test coverage parsing | | `ci_config_path` | string | no | The path to CI config file | | `repository_storage` | string | no | Which storage shard the repository is on. Available only to admins | | `approvals_before_merge` | integer | no | **[STARTER]** How many approvers should approve merge requests by default | @@ -788,6 +789,7 @@ POST /projects/user/:user_id | `printing_merge_request_link_enabled` | boolean | no | Show link to create/view merge request when pushing from the command line | | `build_git_strategy` | string | no | The Git strategy. Defaults to `fetch` | | `build_timeout` | integer | no | The maximum amount of time in minutes that a job is able run (in seconds) | +| `build_coverage_regex` | string | no | Test coverage parsing | | `ci_config_path` | string | no | The path to CI config file | | `repository_storage` | string | no | Which storage shard the repository is on. Available only to admins | | `approvals_before_merge` | integer | no | **[STARTER]** How many approvers should approve merge requests by default | @@ -840,6 +842,7 @@ PUT /projects/:id | `avatar` | mixed | no | Image file for avatar of the project | | `build_git_strategy` | string | no | The Git strategy. Defaults to `fetch` | | `build_timeout` | integer | no | The maximum amount of time in minutes that a job is able run (in seconds) | +| `build_coverage_regex` | string | no | Test coverage parsing | | `ci_config_path` | string | no | The path to CI config file | | `ci_default_git_depth` | integer | no | Default number of revisions for [shallow cloning](../user/project/pipelines/settings.md#git-shallow-clone) | | `repository_storage` | string | no | Which storage shard the repository is on. Available only to admins | diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 3bfaf63d912..3eb2d19c624 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -279,6 +279,7 @@ module API project.build_allow_git_fetch ? 'fetch' : 'clone' end expose :build_timeout + expose :build_coverage_regex expose :ci_config_path, if: -> (project, options) { Ability.allowed?(options[:current_user], :download_code, project) } expose :shared_with_groups do |project, options| SharedGroup.represent(project.project_group_links, options) diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb index 7a806839856..956158b39a6 100644 --- a/lib/api/helpers/projects_helpers.rb +++ b/lib/api/helpers/projects_helpers.rb @@ -10,6 +10,7 @@ module API optional :description, type: String, desc: 'The description of the project' optional :build_git_strategy, type: String, values: %w(fetch clone), desc: 'The Git strategy. Defaults to `fetch`' optional :build_timeout, type: Integer, desc: 'Build timeout' + optional :build_coverage_regex, type: String, desc: 'Test coverage parsing' optional :ci_config_path, type: String, desc: 'The path to CI config file. Defaults to `.gitlab-ci.yml`' # TODO: remove in API v5, replaced by *_access_level @@ -60,6 +61,7 @@ module API def self.update_params_at_least_one_of [ + :build_coverage_regex, :build_git_strategy, :build_timeout, :builds_access_level, -- cgit v1.2.1 From 5028f5d73d8fa69f72ac8d2b1cc493d82cf6f3e4 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Wed, 15 May 2019 16:17:25 +0200 Subject: Add auto_cancel_pending_pipelines to project API --- doc/api/projects.md | 3 +++ lib/api/entities.rb | 1 + lib/api/helpers/projects_helpers.rb | 2 ++ 3 files changed, 6 insertions(+) diff --git a/doc/api/projects.md b/doc/api/projects.md index 316a1fb56ed..02b3faf2d0c 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -735,6 +735,7 @@ POST /projects | `printing_merge_request_link_enabled` | boolean | no | Show link to create/view merge request when pushing from the command line | | `build_git_strategy` | string | no | The Git strategy. Defaults to `fetch` | | `build_timeout` | integer | no | The maximum amount of time in minutes that a job is able run (in seconds) | +| `auto_cancel_pending_pipelines` | string | no | Auto-cancel pending pipelines (Note: this is not a boolean, but enabled/disabled | | `build_coverage_regex` | string | no | Test coverage parsing | | `ci_config_path` | string | no | The path to CI config file | | `repository_storage` | string | no | Which storage shard the repository is on. Available only to admins | @@ -789,6 +790,7 @@ POST /projects/user/:user_id | `printing_merge_request_link_enabled` | boolean | no | Show link to create/view merge request when pushing from the command line | | `build_git_strategy` | string | no | The Git strategy. Defaults to `fetch` | | `build_timeout` | integer | no | The maximum amount of time in minutes that a job is able run (in seconds) | +| `auto_cancel_pending_pipelines` | string | no | Auto-cancel pending pipelines (Note: this is not a boolean, but enabled/disabled | | `build_coverage_regex` | string | no | Test coverage parsing | | `ci_config_path` | string | no | The path to CI config file | | `repository_storage` | string | no | Which storage shard the repository is on. Available only to admins | @@ -842,6 +844,7 @@ PUT /projects/:id | `avatar` | mixed | no | Image file for avatar of the project | | `build_git_strategy` | string | no | The Git strategy. Defaults to `fetch` | | `build_timeout` | integer | no | The maximum amount of time in minutes that a job is able run (in seconds) | +| `auto_cancel_pending_pipelines` | string | no | Auto-cancel pending pipelines (Note: this is not a boolean, but enabled/disabled | | `build_coverage_regex` | string | no | Test coverage parsing | | `ci_config_path` | string | no | The path to CI config file | | `ci_default_git_depth` | integer | no | Default number of revisions for [shallow cloning](../user/project/pipelines/settings.md#git-shallow-clone) | diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 3eb2d19c624..c6c7023042f 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -279,6 +279,7 @@ module API project.build_allow_git_fetch ? 'fetch' : 'clone' end expose :build_timeout + expose :auto_cancel_pending_pipelines expose :build_coverage_regex expose :ci_config_path, if: -> (project, options) { Ability.allowed?(options[:current_user], :download_code, project) } expose :shared_with_groups do |project, options| diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb index 956158b39a6..390c694e21b 100644 --- a/lib/api/helpers/projects_helpers.rb +++ b/lib/api/helpers/projects_helpers.rb @@ -10,6 +10,7 @@ module API optional :description, type: String, desc: 'The description of the project' optional :build_git_strategy, type: String, values: %w(fetch clone), desc: 'The Git strategy. Defaults to `fetch`' optional :build_timeout, type: Integer, desc: 'Build timeout' + optional :auto_cancel_pending_pipelines, type: String, values: %w(disabled enabled), desc: 'Auto-cancel pending pipelines' optional :build_coverage_regex, type: String, desc: 'Test coverage parsing' optional :ci_config_path, type: String, desc: 'The path to CI config file. Defaults to `.gitlab-ci.yml`' @@ -61,6 +62,7 @@ module API def self.update_params_at_least_one_of [ + :auto_cancel_pending_pipelines, :build_coverage_regex, :build_git_strategy, :build_timeout, -- cgit v1.2.1 From e44167004dd44cf727829d0fc9df59fe3404bb49 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Wed, 15 May 2019 16:27:54 +0200 Subject: Add auto_devops_* to project API The auto_devops object sometimes doesn't exists. We may need to create it. --- app/models/concerns/project_api_compatibility.rb | 10 +++++++++ doc/api/projects.md | 6 ++++++ lib/api/entities.rb | 4 ++++ lib/api/helpers/projects_helpers.rb | 4 ++++ .../concerns/project_api_compatibility_spec.rb | 25 ++++++++++++++++++++-- spec/requests/api/projects_spec.rb | 20 +++++++++++++++++ 6 files changed, 67 insertions(+), 2 deletions(-) diff --git a/app/models/concerns/project_api_compatibility.rb b/app/models/concerns/project_api_compatibility.rb index 9a0202c211c..cb00efb06df 100644 --- a/app/models/concerns/project_api_compatibility.rb +++ b/app/models/concerns/project_api_compatibility.rb @@ -7,4 +7,14 @@ module ProjectAPICompatibility def build_git_strategy=(value) write_attribute(:build_allow_git_fetch, value == 'fetch') end + + def auto_devops_enabled=(value) + self.build_auto_devops if self.auto_devops&.enabled.nil? + self.auto_devops.update! enabled: value + end + + def auto_devops_deploy_strategy=(value) + self.build_auto_devops if self.auto_devops&.enabled.nil? + self.auto_devops.update! deploy_strategy: value + end end diff --git a/doc/api/projects.md b/doc/api/projects.md index 02b3faf2d0c..c3e9fc69dd2 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -738,6 +738,8 @@ POST /projects | `auto_cancel_pending_pipelines` | string | no | Auto-cancel pending pipelines (Note: this is not a boolean, but enabled/disabled | | `build_coverage_regex` | string | no | Test coverage parsing | | `ci_config_path` | string | no | The path to CI config file | +| `auto_devops_enabled` | boolean | no | Enable Auto DevOps for this project | +| `auto_devops_deploy_strategy` | string | no | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`) | | `repository_storage` | string | no | Which storage shard the repository is on. Available only to admins | | `approvals_before_merge` | integer | no | **[STARTER]** How many approvers should approve merge requests by default | | `mirror` | boolean | no | **[STARTER]** Enables pull mirroring in a project | @@ -793,6 +795,8 @@ POST /projects/user/:user_id | `auto_cancel_pending_pipelines` | string | no | Auto-cancel pending pipelines (Note: this is not a boolean, but enabled/disabled | | `build_coverage_regex` | string | no | Test coverage parsing | | `ci_config_path` | string | no | The path to CI config file | +| `auto_devops_enabled` | boolean | no | Enable Auto DevOps for this project | +| `auto_devops_deploy_strategy` | string | no | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`) | | `repository_storage` | string | no | Which storage shard the repository is on. Available only to admins | | `approvals_before_merge` | integer | no | **[STARTER]** How many approvers should approve merge requests by default | | `external_authorization_classification_label` | string | no | **[CORE ONLY]** The classification label for the project | @@ -848,6 +852,8 @@ PUT /projects/:id | `build_coverage_regex` | string | no | Test coverage parsing | | `ci_config_path` | string | no | The path to CI config file | | `ci_default_git_depth` | integer | no | Default number of revisions for [shallow cloning](../user/project/pipelines/settings.md#git-shallow-clone) | +| `auto_devops_enabled` | boolean | no | Enable Auto DevOps for this project | +| `auto_devops_deploy_strategy` | string | no | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`) | | `repository_storage` | string | no | Which storage shard the repository is on. Available only to admins | | `approvals_before_merge` | integer | no | **[STARTER]** How many approvers should approve merge request by default | | `external_authorization_classification_label` | string | no | **[CORE ONLY]** The classification label for the project | diff --git a/lib/api/entities.rb b/lib/api/entities.rb index c6c7023042f..7bf66589616 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -294,6 +294,10 @@ module API options[:statistics] && Ability.allowed?(options[:current_user], :read_statistics, project) } expose :external_authorization_classification_label + expose :auto_devops_enabled?, as: :auto_devops_enabled + expose :auto_devops_deploy_strategy do |project, options| + project.auto_devops.nil? ? 'continuous' : project.auto_devops.deploy_strategy + end # rubocop: disable CodeReuse/ActiveRecord def self.preload_relation(projects_relation, options = {}) diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb index 390c694e21b..0e21a7a66fd 100644 --- a/lib/api/helpers/projects_helpers.rb +++ b/lib/api/helpers/projects_helpers.rb @@ -44,6 +44,8 @@ module API optional :initialize_with_readme, type: Boolean, desc: "Initialize a project with a README.md" optional :external_authorization_classification_label, type: String, desc: 'The classification label for the project' optional :ci_default_git_depth, type: Integer, desc: 'Default number of revisions for shallow cloning' + optional :auto_devops_enabled, type: Boolean, desc: 'Flag indication if Auto DevOps is enabled' + optional :auto_devops_deploy_strategy, type: String, values: %w(continuous manual timed_incremental), desc: 'Auto Deploy strategy' end params :optional_project_params_ee do @@ -62,6 +64,8 @@ module API def self.update_params_at_least_one_of [ + :auto_devops_enabled, + :auto_devops_deploy_strategy, :auto_cancel_pending_pipelines, :build_coverage_regex, :build_git_strategy, diff --git a/spec/models/concerns/project_api_compatibility_spec.rb b/spec/models/concerns/project_api_compatibility_spec.rb index a999f60a1f3..8cecd4fe7bc 100644 --- a/spec/models/concerns/project_api_compatibility_spec.rb +++ b/spec/models/concerns/project_api_compatibility_spec.rb @@ -5,13 +5,34 @@ require 'spec_helper' describe ProjectAPICompatibility do let(:project) { create(:project) } + # git_strategy it "converts build_git_strategy=fetch to build_allow_git_fetch=true" do - project.update!(:build_git_strategy, 'fetch') + project.update!(build_git_strategy: 'fetch') expect(project.build_allow_git_fetch).to eq(true) end it "converts build_git_strategy=clone to build_allow_git_fetch=false" do - project.update!(:build_git_strategy, 'clone') + project.update!(build_git_strategy: 'clone') expect(project.build_allow_git_fetch).to eq(false) end + + # auto_devops_enabled + it "converts auto_devops_enabled=false to auto_devops_enabled?=false" do + expect(project.auto_devops_enabled?).to eq(true) + project.update!(auto_devops_enabled: false) + expect(project.auto_devops_enabled?).to eq(false) + end + + it "converts auto_devops_enabled=true to auto_devops_enabled?=true" do + expect(project.auto_devops_enabled?).to eq(true) + project.update!(auto_devops_enabled: true) + expect(project.auto_devops_enabled?).to eq(true) + end + + # auto_devops_deploy_strategy + it "converts auto_devops_deploy_strategy=timed_incremental to auto_devops.deploy_strategy=timed_incremental" do + expect(project.auto_devops).to be_nil + project.update!(auto_devops_deploy_strategy: 'timed_incremental') + expect(project.auto_devops.deploy_strategy).to eq('timed_incremental') + end end diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 2fc257a1a06..df4758f362b 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -1980,6 +1980,26 @@ describe API::Projects do '-/system/project/avatar/'\ "#{project3.id}/banana_sample.gif") end + + it 'updates auto_devops_deploy_strategy' do + project_param = { auto_devops_deploy_strategy: 'timed_incremental' } + + put api("/projects/#{project3.id}", user), params: project_param + + expect(response).to have_gitlab_http_status(200) + + expect(json_response['auto_devops_deploy_strategy']).to eq('timed_incremental') + end + + it 'updates auto_devops_enabled' do + project_param = { auto_devops_enabled: false } + + put api("/projects/#{project3.id}", user), params: project_param + + expect(response).to have_gitlab_http_status(200) + + expect(json_response['auto_devops_enabled']).to eq(false) + end end context 'when authenticated as project maintainer' do -- cgit v1.2.1 From 4abb68f8d6b94a97aa670d7511c6ed976f9ce2a6 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Wed, 15 May 2019 16:48:37 +0200 Subject: Add changelog entry --- changelogs/unreleased/project_api.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelogs/unreleased/project_api.yml diff --git a/changelogs/unreleased/project_api.yml b/changelogs/unreleased/project_api.yml new file mode 100644 index 00000000000..a04f9bb5608 --- /dev/null +++ b/changelogs/unreleased/project_api.yml @@ -0,0 +1,5 @@ +--- +title: Improve Project API +merge_request: 28327 +author: Mathieu Parent +type: added -- cgit v1.2.1 From 32bbb52c19cf804c94a15e34d69a036d08acd35a Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Tue, 28 May 2019 18:09:02 +0200 Subject: Fix API performance problem of auto_devops query --- lib/api/entities.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 7bf66589616..5eae87fea02 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -201,6 +201,7 @@ module API # MR describing the solution: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20555 projects_relation.preload(:project_feature, :route) .preload(:import_state, :tags) + .preload(:auto_devops) .preload(namespace: [:route, :owner]) end # rubocop: enable CodeReuse/ActiveRecord @@ -307,6 +308,7 @@ module API # MR describing the solution: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20555 super(projects_relation).preload(:group) .preload(:ci_cd_settings) + .preload(:auto_devops) .preload(project_group_links: { group: :route }, fork_network: :root_project, fork_network_member: :forked_from_project, -- cgit v1.2.1 From d529c8f6227eb79d1adb0d2bfece2ac59c578114 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Thu, 27 Jun 2019 14:39:46 +0200 Subject: Update json for "Get single project" doc --- doc/api/projects.md | 131 +++++++++++++++++++++++++--------------------------- 1 file changed, 62 insertions(+), 69 deletions(-) diff --git a/doc/api/projects.md b/doc/api/projects.md index c3e9fc69dd2..68f5d7f0edb 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -483,95 +483,88 @@ GET /projects/:id ```json { - "id": 3, - "description": null, + "id": 26, + "description": "My amazing project", + "name": "myproject", + "name_with_namespace": "mygroup / myproject", + "path": "myproject", + "path_with_namespace": "mygroup/myproject", + "created_at": "2019-06-27T12:32:51.444Z", "default_branch": "master", - "visibility": "private", - "ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git", - "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", - "web_url": "http://example.com/diaspora/diaspora-project-site", - "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", "tag_list": [ - "example", - "disapora project" + "topic1", + "topic2" ], - "owner": { - "id": 3, - "name": "Diaspora", - "created_at": "2013-09-30T13:46:02Z" - }, - "name": "Diaspora Project Site", - "name_with_namespace": "Diaspora / Diaspora Project Site", - "path": "diaspora-project-site", - "path_with_namespace": "diaspora/diaspora-project-site", - "issues_enabled": true, - "open_issues_count": 1, - "merge_requests_enabled": true, - "jobs_enabled": true, - "wiki_enabled": true, - "snippets_enabled": false, - "resolve_outdated_diff_discussions": false, - "container_registry_enabled": false, - "created_at": "2013-09-30T13:46:02Z", - "last_activity_at": "2013-09-30T13:46:02Z", - "creator_id": 3, + "ssh_url_to_repo": "git@gitlab.example.com:mygroup/myproject.git", + "http_url_to_repo": "http://gitlab.example.com/mygroup/myproject.git", + "web_url": "http://gitlab.example.com/mygroup/myproject", + "readme_url": "http://gitlab.example.com/mygroup/myproject/blob/master/README.md", + "avatar_url": null, + "star_count": 0, + "forks_count": 0, + "last_activity_at": "2019-06-27T12:32:51.444Z", "namespace": { - "id": 3, - "name": "Diaspora", - "path": "diaspora", + "id": 23, + "name": "mygroup", + "path": "mygroup", "kind": "group", - "full_path": "diaspora", - "avatar_url": "http://localhost:3000/uploads/group/avatar/3/foo.jpg", - "web_url": "http://localhost:3000/groups/diaspora" + "full_path": "mygroup", + "parent_id": null, + "avatar_url": null, + "web_url": "http://gitlab.example.com/groups/mygroup" }, - "import_status": "none", - "import_error": null, - "permissions": { - "project_access": { - "access_level": 10, - "notification_level": 3 - }, - "group_access": { - "access_level": 50, - "notification_level": 3 - } + "_links": { + "self": "http://gitlab.example.com/api/v4/projects/26", + "issues": "http://gitlab.example.com/api/v4/projects/26/issues", + "merge_requests": "http://gitlab.example.com/api/v4/projects/26/merge_requests", + "repo_branches": "http://gitlab.example.com/api/v4/projects/26/repository/branches", + "labels": "http://gitlab.example.com/api/v4/projects/26/labels", + "events": "http://gitlab.example.com/api/v4/projects/26/events", + "members": "http://gitlab.example.com/api/v4/projects/26/members" }, + "empty_repo": false, "archived": false, - "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", - "license_url": "http://example.com/diaspora/diaspora-client/blob/master/LICENSE", - "license": { - "key": "lgpl-3.0", - "name": "GNU Lesser General Public License v3.0", - "nickname": "GNU LGPLv3", - "html_url": "http://choosealicense.com/licenses/lgpl-3.0/", - "source_url": "http://www.gnu.org/licenses/lgpl-3.0.txt" - }, + "visibility": "private", + "resolve_outdated_diff_discussions": false, + "container_registry_enabled": true, + "issues_enabled": true, + "merge_requests_enabled": true, + "wiki_enabled": true, + "jobs_enabled": true, + "snippets_enabled": true, "shared_runners_enabled": true, - "forks_count": 0, - "star_count": 0, - "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b", + "lfs_enabled": true, + "creator_id": 1, + "import_status": "none", + "import_error": null, + "open_issues_count": 0, + "runners_token": "sQewQBDHAMkqnMFVXzuW", "ci_default_git_depth": 50, "public_jobs": true, + "ci_config_path": null, "shared_with_groups": [ - { - "group_id": 4, - "group_name": "Twitter", - "group_full_path": "twitter", - "group_access_level": 30 - }, { "group_id": 3, - "group_name": "Gitlab Org", - "group_full_path": "gitlab-org", - "group_access_level": 10 + "group_name": "test", + "group_full_path": "test", + "group_access_level": 30, + "expires_at": null } ], "repository_storage": "default", "only_allow_merge_if_pipeline_succeeds": false, - "only_allow_merge_if_all_discussions_are_resolved": false, - "printing_merge_requests_link_enabled": true, "request_access_enabled": false, + "only_allow_merge_if_all_discussions_are_resolved": false, + "printing_merge_request_link_enabled": true, "merge_method": "merge", + "external_authorization_classification_label": null, + "permissions": { + "project_access": null, + "group_access": { + "access_level": 50, + "notification_level": 3 + } + }, "statistics": { "commit_count": 37, "storage_size": 1038090, -- cgit v1.2.1 From 152a100a188a7b7abfdaba27ceec8d3156fb6ab5 Mon Sep 17 00:00:00 2001 From: Pirate Praveen Date: Thu, 4 Jul 2019 09:06:06 +0200 Subject: Update net-ssh gem to ~> 5.2 --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 1264d75eac6..a37b65f459c 100644 --- a/Gemfile +++ b/Gemfile @@ -419,7 +419,7 @@ gem 'vmstat', '~> 2.3.0' gem 'sys-filesystem', '~> 1.1.6' # SSH host key support -gem 'net-ssh', '~> 5.0' +gem 'net-ssh', '~> 5.2' gem 'sshkey', '~> 2.0' # Required for ED25519 SSH host key support diff --git a/Gemfile.lock b/Gemfile.lock index 5b648d43137..8b548c08f92 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -515,7 +515,7 @@ GEM mysql2 (0.4.10) nakayoshi_fork (0.0.4) net-ldap (0.16.0) - net-ssh (5.0.1) + net-ssh (5.2.0) netrc (0.11.0) nio4r (2.3.1) nokogiri (1.10.3) @@ -1142,7 +1142,7 @@ DEPENDENCIES mysql2 (~> 0.4.10) nakayoshi_fork (~> 0.0.4) net-ldap - net-ssh (~> 5.0) + net-ssh (~> 5.2) nokogiri (~> 1.10.3) oauth2 (~> 1.4) octokit (~> 4.9) -- cgit v1.2.1 From 203ef336392befd907c335a4a851ec0794d5e91a Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Thu, 4 Jul 2019 09:08:35 +0100 Subject: Reduce changes to doc/api/projects.md --- doc/api/projects.md | 131 +++++++++++++++++++++++++++------------------------- 1 file changed, 69 insertions(+), 62 deletions(-) diff --git a/doc/api/projects.md b/doc/api/projects.md index 68f5d7f0edb..c3e9fc69dd2 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -483,88 +483,95 @@ GET /projects/:id ```json { - "id": 26, - "description": "My amazing project", - "name": "myproject", - "name_with_namespace": "mygroup / myproject", - "path": "myproject", - "path_with_namespace": "mygroup/myproject", - "created_at": "2019-06-27T12:32:51.444Z", + "id": 3, + "description": null, "default_branch": "master", + "visibility": "private", + "ssh_url_to_repo": "git@example.com:diaspora/diaspora-project-site.git", + "http_url_to_repo": "http://example.com/diaspora/diaspora-project-site.git", + "web_url": "http://example.com/diaspora/diaspora-project-site", + "readme_url": "http://example.com/diaspora/diaspora-project-site/blob/master/README.md", "tag_list": [ - "topic1", - "topic2" + "example", + "disapora project" ], - "ssh_url_to_repo": "git@gitlab.example.com:mygroup/myproject.git", - "http_url_to_repo": "http://gitlab.example.com/mygroup/myproject.git", - "web_url": "http://gitlab.example.com/mygroup/myproject", - "readme_url": "http://gitlab.example.com/mygroup/myproject/blob/master/README.md", - "avatar_url": null, - "star_count": 0, - "forks_count": 0, - "last_activity_at": "2019-06-27T12:32:51.444Z", - "namespace": { - "id": 23, - "name": "mygroup", - "path": "mygroup", - "kind": "group", - "full_path": "mygroup", - "parent_id": null, - "avatar_url": null, - "web_url": "http://gitlab.example.com/groups/mygroup" - }, - "_links": { - "self": "http://gitlab.example.com/api/v4/projects/26", - "issues": "http://gitlab.example.com/api/v4/projects/26/issues", - "merge_requests": "http://gitlab.example.com/api/v4/projects/26/merge_requests", - "repo_branches": "http://gitlab.example.com/api/v4/projects/26/repository/branches", - "labels": "http://gitlab.example.com/api/v4/projects/26/labels", - "events": "http://gitlab.example.com/api/v4/projects/26/events", - "members": "http://gitlab.example.com/api/v4/projects/26/members" + "owner": { + "id": 3, + "name": "Diaspora", + "created_at": "2013-09-30T13:46:02Z" }, - "empty_repo": false, - "archived": false, - "visibility": "private", - "resolve_outdated_diff_discussions": false, - "container_registry_enabled": true, + "name": "Diaspora Project Site", + "name_with_namespace": "Diaspora / Diaspora Project Site", + "path": "diaspora-project-site", + "path_with_namespace": "diaspora/diaspora-project-site", "issues_enabled": true, + "open_issues_count": 1, "merge_requests_enabled": true, - "wiki_enabled": true, "jobs_enabled": true, - "snippets_enabled": true, - "shared_runners_enabled": true, - "lfs_enabled": true, - "creator_id": 1, + "wiki_enabled": true, + "snippets_enabled": false, + "resolve_outdated_diff_discussions": false, + "container_registry_enabled": false, + "created_at": "2013-09-30T13:46:02Z", + "last_activity_at": "2013-09-30T13:46:02Z", + "creator_id": 3, + "namespace": { + "id": 3, + "name": "Diaspora", + "path": "diaspora", + "kind": "group", + "full_path": "diaspora", + "avatar_url": "http://localhost:3000/uploads/group/avatar/3/foo.jpg", + "web_url": "http://localhost:3000/groups/diaspora" + }, "import_status": "none", "import_error": null, - "open_issues_count": 0, - "runners_token": "sQewQBDHAMkqnMFVXzuW", + "permissions": { + "project_access": { + "access_level": 10, + "notification_level": 3 + }, + "group_access": { + "access_level": 50, + "notification_level": 3 + } + }, + "archived": false, + "avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png", + "license_url": "http://example.com/diaspora/diaspora-client/blob/master/LICENSE", + "license": { + "key": "lgpl-3.0", + "name": "GNU Lesser General Public License v3.0", + "nickname": "GNU LGPLv3", + "html_url": "http://choosealicense.com/licenses/lgpl-3.0/", + "source_url": "http://www.gnu.org/licenses/lgpl-3.0.txt" + }, + "shared_runners_enabled": true, + "forks_count": 0, + "star_count": 0, + "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b", "ci_default_git_depth": 50, "public_jobs": true, - "ci_config_path": null, "shared_with_groups": [ + { + "group_id": 4, + "group_name": "Twitter", + "group_full_path": "twitter", + "group_access_level": 30 + }, { "group_id": 3, - "group_name": "test", - "group_full_path": "test", - "group_access_level": 30, - "expires_at": null + "group_name": "Gitlab Org", + "group_full_path": "gitlab-org", + "group_access_level": 10 } ], "repository_storage": "default", "only_allow_merge_if_pipeline_succeeds": false, - "request_access_enabled": false, "only_allow_merge_if_all_discussions_are_resolved": false, - "printing_merge_request_link_enabled": true, + "printing_merge_requests_link_enabled": true, + "request_access_enabled": false, "merge_method": "merge", - "external_authorization_classification_label": null, - "permissions": { - "project_access": null, - "group_access": { - "access_level": 50, - "notification_level": 3 - } - }, "statistics": { "commit_count": 37, "storage_size": 1038090, -- cgit v1.2.1 From 4f04c4c90b2db8ddcf5f3e28a9bbefd20c8bbda0 Mon Sep 17 00:00:00 2001 From: Mario de la Ossa Date: Wed, 12 Jun 2019 18:08:44 -0600 Subject: Ignore min_chars_for_partial_matching unles trigrm If we're not using a trigram index, then ignore the min_chars_for_partial_matching setting --- app/finders/issuable_finder.rb | 2 +- app/models/concerns/issuable.rb | 4 ++-- .../unreleased/40379-CJK-search-min-chars.yml | 5 +++++ lib/gitlab/sql/pattern.rb | 24 +++++++++++++--------- spec/lib/gitlab/sql/pattern_spec.rb | 12 +++++++++++ spec/models/concerns/issuable_spec.rb | 10 +++++++++ 6 files changed, 44 insertions(+), 13 deletions(-) create mode 100644 changelogs/unreleased/40379-CJK-search-min-chars.yml diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb index 3592505a977..f4fbeacfaba 100644 --- a/app/finders/issuable_finder.rb +++ b/app/finders/issuable_finder.rb @@ -429,7 +429,7 @@ class IssuableFinder items = klass.with(cte.to_arel).from(klass.table_name) end - items.full_search(search, matched_columns: params[:in]) + items.full_search(search, matched_columns: params[:in], use_minimum_char_limit: !use_cte_for_search?) end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 299e413321d..952de92cae1 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -168,7 +168,7 @@ module Issuable # matched_columns - Modify the scope of the query. 'title', 'description' or joining them with a comma. # # Returns an ActiveRecord::Relation. - def full_search(query, matched_columns: 'title,description') + def full_search(query, matched_columns: 'title,description', use_minimum_char_limit: true) allowed_columns = [:title, :description] matched_columns = matched_columns.to_s.split(',').map(&:to_sym) matched_columns &= allowed_columns @@ -176,7 +176,7 @@ module Issuable # Matching title or description if the matched_columns did not contain any allowed columns. matched_columns = [:title, :description] if matched_columns.empty? - fuzzy_search(query, matched_columns) + fuzzy_search(query, matched_columns, use_minimum_char_limit: use_minimum_char_limit) end def simple_sorts diff --git a/changelogs/unreleased/40379-CJK-search-min-chars.yml b/changelogs/unreleased/40379-CJK-search-min-chars.yml new file mode 100644 index 00000000000..6f6c4df464f --- /dev/null +++ b/changelogs/unreleased/40379-CJK-search-min-chars.yml @@ -0,0 +1,5 @@ +--- +title: Remove minimum character limits for fuzzy searches when using a CTE +merge_request: 29810 +author: +type: fixed diff --git a/lib/gitlab/sql/pattern.rb b/lib/gitlab/sql/pattern.rb index fd108b4c124..f6edbfced7f 100644 --- a/lib/gitlab/sql/pattern.rb +++ b/lib/gitlab/sql/pattern.rb @@ -9,14 +9,16 @@ module Gitlab REGEX_QUOTED_WORD = /(?<=\A| )"[^"]+"(?= |\z)/.freeze class_methods do - def fuzzy_search(query, columns) - matches = columns.map { |col| fuzzy_arel_match(col, query) }.compact.reduce(:or) + def fuzzy_search(query, columns, use_minimum_char_limit: true) + matches = columns.map do |col| + fuzzy_arel_match(col, query, use_minimum_char_limit: use_minimum_char_limit) + end.compact.reduce(:or) where(matches) end - def to_pattern(query) - if partial_matching?(query) + def to_pattern(query, use_minimum_char_limit: true) + if partial_matching?(query, use_minimum_char_limit: use_minimum_char_limit) "%#{sanitize_sql_like(query)}%" else sanitize_sql_like(query) @@ -27,7 +29,9 @@ module Gitlab MIN_CHARS_FOR_PARTIAL_MATCHING end - def partial_matching?(query) + def partial_matching?(query, use_minimum_char_limit: true) + return true unless use_minimum_char_limit + query.length >= min_chars_for_partial_matching end @@ -35,14 +39,14 @@ module Gitlab # query - The text to search for. # lower_exact_match - When set to `true` we'll fall back to using # `LOWER(column) = query` instead of using `ILIKE`. - def fuzzy_arel_match(column, query, lower_exact_match: false) + def fuzzy_arel_match(column, query, lower_exact_match: false, use_minimum_char_limit: true) query = query.squish return unless query.present? - words = select_fuzzy_words(query) + words = select_fuzzy_words(query, use_minimum_char_limit: use_minimum_char_limit) if words.any? - words.map { |word| arel_table[column].matches(to_pattern(word)) }.reduce(:and) + words.map { |word| arel_table[column].matches(to_pattern(word, use_minimum_char_limit: use_minimum_char_limit)) }.reduce(:and) else # No words of at least 3 chars, but we can search for an exact # case insensitive match with the query as a whole @@ -56,7 +60,7 @@ module Gitlab end end - def select_fuzzy_words(query) + def select_fuzzy_words(query, use_minimum_char_limit: true) quoted_words = query.scan(REGEX_QUOTED_WORD) query = quoted_words.reduce(query) { |q, quoted_word| q.sub(quoted_word, '') } @@ -67,7 +71,7 @@ module Gitlab words.concat(quoted_words) - words.select { |word| partial_matching?(word) } + words.select { |word| partial_matching?(word, use_minimum_char_limit: use_minimum_char_limit) } end end end diff --git a/spec/lib/gitlab/sql/pattern_spec.rb b/spec/lib/gitlab/sql/pattern_spec.rb index 5b5052de372..98838712eae 100644 --- a/spec/lib/gitlab/sql/pattern_spec.rb +++ b/spec/lib/gitlab/sql/pattern_spec.rb @@ -10,6 +10,12 @@ describe Gitlab::SQL::Pattern do it 'returns exact matching pattern' do expect(to_pattern).to eq('12') end + + context 'and ignore_minimum_char_limit is true' do + it 'returns partial matching pattern' do + expect(User.to_pattern(query, use_minimum_char_limit: false)).to eq('%12%') + end + end end context 'when a query with a escape character is shorter than 3 chars' do @@ -18,6 +24,12 @@ describe Gitlab::SQL::Pattern do it 'returns sanitized exact matching pattern' do expect(to_pattern).to eq('\_2') end + + context 'and ignore_minimum_char_limit is true' do + it 'returns sanitized partial matching pattern' do + expect(User.to_pattern(query, use_minimum_char_limit: false)).to eq('%\_2%') + end + end end context 'when a query is equal to 3 chars' do diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index 64f02978d79..68224a56515 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -223,6 +223,16 @@ describe Issuable do expect(issuable_class.full_search(searchable_issue2.description.downcase)).to eq([searchable_issue2]) end + it 'returns issues with a fuzzy matching description for a query shorter than 3 chars if told to do so' do + search = searchable_issue2.description.downcase.scan(/\w+/).sample[-1] + + expect(issuable_class.full_search(search, use_minimum_char_limit: false)).to include(searchable_issue2) + end + + it 'returns issues with a fuzzy matching title for a query shorter than 3 chars if told to do so' do + expect(issuable_class.full_search('i', use_minimum_char_limit: false)).to include(searchable_issue) + end + context 'when matching columns is "title"' do it 'returns issues with a matching title' do expect(issuable_class.full_search(searchable_issue.title, matched_columns: 'title')) -- cgit v1.2.1 From f198c522cfd3625ca8ee5ff12b6343686f1f1564 Mon Sep 17 00:00:00 2001 From: nathanbietz Date: Thu, 4 Jul 2019 20:11:30 +0000 Subject: Update index.md.... add instructions on how to add a `values.yaml` override file to the default auto-deploy-app helm chart by setting `HELM_UPGRADE_EXTRA_ARGS` to `--values my-values.yaml` (or `-f my-values.yaml`). --- doc/topics/autodevops/index.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md index bd788cb138c..49524dda394 100644 --- a/doc/topics/autodevops/index.md +++ b/doc/topics/autodevops/index.md @@ -316,7 +316,7 @@ If a project's repository contains a `Dockerfile`, Auto Build will use If you are also using Auto Review Apps and Auto Deploy and choose to provide your own `Dockerfile`, make sure you expose your application to port `5000` as this is the port assumed by the -[default Helm chart](https://gitlab.com/gitlab-org/charts/auto-deploy-app). +[default Helm chart](https://gitlab.com/gitlab-org/charts/auto-deploy-app). Alternatively you can override the default values by [customizing the Auto Deploy helm chart](https://docs.gitlab.com/ee/topics/autodevops/index.html#custom-helm-chart) #### Auto Build using Heroku buildpacks @@ -452,7 +452,7 @@ be deleted. Review apps are deployed using the [auto-deploy-app](https://gitlab.com/gitlab-org/charts/auto-deploy-app) chart with -Helm. The app will be deployed into the [Kubernetes +Helm, which can be [customized](https://docs.gitlab.com/ee/topics/autodevops/index.html#custom-helm-chart). The app will be deployed into the [Kubernetes namespace](../../user/project/clusters/index.md#deployment-variables) for the environment. @@ -514,7 +514,7 @@ Auto Deploy doesn't include deployments to staging or canary by default, but the enable them. You can make use of [environment variables](#environment-variables) to automatically -scale your pod replicas. +scale your pod replicas and to apply custom arguments to the helm deploy command. This is an easy way to [customize the Auto Deploy helm chart](https://docs.gitlab.com/ee/topics/autodevops/index.html#custom-helm-chart). Apps are deployed using the [auto-deploy-app](https://gitlab.com/gitlab-org/charts/auto-deploy-app) chart with @@ -655,6 +655,9 @@ repo or by specifying a project variable: - **Project variable** - Create a [project variable](../../ci/variables/README.md#gitlab-cicd-environment-variables) `AUTO_DEVOPS_CHART` with the URL of a custom chart to use or create two project variables `AUTO_DEVOPS_CHART_REPOSITORY` with the URL of a custom chart repository and `AUTO_DEVOPS_CHART` with the path to the chart. +You can also make use of the `HELM_UPGRADE_EXTRA_ARGS` environment variable to ovrride the default values in the `values.yaml` file in the [default Helm chart](https://gitlab.com/gitlab-org/charts/auto-deploy-app). +To apply your own `values.yaml` file to all Helm upgrade commands in Auto Deploy set `HELM_UPGRADE_EXTRA_ARGS` to `--values my-values.yaml` (or `-f my-values.yaml`). + ### Custom Helm chart per environment **[PREMIUM]** You can specify the use of a custom Helm chart per environment by scoping the environment variable @@ -761,7 +764,7 @@ also be customized, and you can easily use a [custom buildpack](#custom-buildpac | `KUBE_INGRESS_BASE_DOMAIN` | From GitLab 11.8, this variable can be used to set a domain per cluster. See [cluster domains](../../user/project/clusters/index.md#base-domain) for more information. | | `ROLLOUT_RESOURCE_TYPE` | From GitLab 11.9, this variable allows specification of the resource type being deployed when using a custom helm chart. Default value is `deployment`. | | `ROLLOUT_STATUS_DISABLED` | From GitLab 12.0, this variable allows to disable rollout status check because it doesn't support all resource types, for example, `cronjob`. | -| `HELM_UPGRADE_EXTRA_ARGS` | From GitLab 11.11, this variable allows extra arguments in `helm` commands when deploying the application. Note that using quotes will not prevent word splitting. | +| `HELM_UPGRADE_EXTRA_ARGS` | From GitLab 11.11, this variable allows extra arguments in `helm` commands when deploying the application. Note that using quotes will not prevent word splitting. **Tip:** you can use this variable to [customize the Auto Deploy helm chart](https://docs.gitlab.com/ee/topics/autodevops/index.html#custom-helm-chart) by applying custom override values with `--values my-values.yml` (or `-f my-values.yaml`). | TIP: **Tip:** Set up the replica variables using a -- cgit v1.2.1 From c7f7f81c20b84c47af9da22a4e5dc306dc0f00da Mon Sep 17 00:00:00 2001 From: nathanbietz Date: Thu, 4 Jul 2019 21:02:26 +0000 Subject: Update index.md.... change "helm deploy" to "helm upgrade" --- doc/topics/autodevops/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md index 49524dda394..2810523d081 100644 --- a/doc/topics/autodevops/index.md +++ b/doc/topics/autodevops/index.md @@ -514,7 +514,7 @@ Auto Deploy doesn't include deployments to staging or canary by default, but the enable them. You can make use of [environment variables](#environment-variables) to automatically -scale your pod replicas and to apply custom arguments to the helm deploy command. This is an easy way to [customize the Auto Deploy helm chart](https://docs.gitlab.com/ee/topics/autodevops/index.html#custom-helm-chart). +scale your pod replicas and to apply custom arguments to the Auto DevOps `helm upgrade` commands. This is an easy way to [customize the Auto Deploy helm chart](https://docs.gitlab.com/ee/topics/autodevops/index.html#custom-helm-chart). Apps are deployed using the [auto-deploy-app](https://gitlab.com/gitlab-org/charts/auto-deploy-app) chart with -- cgit v1.2.1 From 2ecad462a087958433cc886c08830e0a36964cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C5=82gorzata=20Ksionek?= Date: Mon, 1 Jul 2019 13:27:47 +0200 Subject: Add where condition to count in median class --- lib/gitlab/database/median.rb | 2 +- spec/lib/gitlab/cycle_analytics/test_stage_spec.rb | 34 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/lib/gitlab/database/median.rb b/lib/gitlab/database/median.rb index 1455e410d4b..b8d895dee7d 100644 --- a/lib/gitlab/database/median.rb +++ b/lib/gitlab/database/median.rb @@ -158,7 +158,7 @@ module Gitlab Arel::Nodes::Window.new.order(arel_table[column_sym]) ).as('row_id') - count = arel_table.project("COUNT(1)").as('ct') + count = arel_table.where(arel_table[column_sym].gteq(zero_interval)).project("COUNT(1)").as('ct') [column_row, row_id, count] end diff --git a/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb index eacde22cd56..1d4ad1b319d 100644 --- a/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb @@ -3,6 +3,40 @@ require 'lib/gitlab/cycle_analytics/shared_stage_spec' describe Gitlab::CycleAnalytics::TestStage do let(:stage_name) { :test } + let(:project) { create(:project) } + let!(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) } + let!(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) } + let!(:issue_3) { create(:issue, project: project, created_at: 60.minutes.ago) } + let!(:mr_1) { create(:merge_request, :closed, source_project: project, created_at: 60.minutes.ago) } + let!(:mr_2) { create(:merge_request, :closed, source_project: project, created_at: 40.minutes.ago, source_branch: 'A') } + let!(:mr_3) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'B') } + let!(:mr_4) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'C') } + let!(:mr_5) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'D') } + let(:stage) { described_class.new(project: project, options: { from: 2.days.ago, current_user: project.creator }) } + + before do + mr_1.metrics.update!(latest_build_started_at: 32.minutes.ago, latest_build_finished_at: 2.minutes.ago) + mr_2.metrics.update!(latest_build_started_at: 62.minutes.ago, latest_build_finished_at: 32.minute.ago) + mr_3.metrics.update!(latest_build_started_at: nil, latest_build_finished_at: nil) + mr_4.metrics.update!(latest_build_started_at: nil, latest_build_finished_at: nil) + mr_5.metrics.update!(latest_build_started_at: nil, latest_build_finished_at: nil) + + create(:merge_requests_closing_issues, merge_request: mr_1, issue: issue_1) + create(:merge_requests_closing_issues, merge_request: mr_2, issue: issue_2) + create(:merge_requests_closing_issues, merge_request: mr_3, issue: issue_3) + create(:merge_requests_closing_issues, merge_request: mr_4, issue: issue_3) + create(:merge_requests_closing_issues, merge_request: mr_5, issue: issue_3) + end it_behaves_like 'base stage' + + describe '#median' do + around do |example| + Timecop.freeze { example.run } + end + + it 'counts median from issues with metrics' do + expect(stage.median).to eq(ISSUES_MEDIAN) + end + end end -- cgit v1.2.1 From f47956f0fd3b73eb1bc6ab352b076b937753a549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C5=82gorzata=20Ksionek?= Date: Mon, 1 Jul 2019 15:27:15 +0200 Subject: Add changelog entry --- changelogs/unreleased/fix-median-counting-for-cycle-analytics.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelogs/unreleased/fix-median-counting-for-cycle-analytics.yml diff --git a/changelogs/unreleased/fix-median-counting-for-cycle-analytics.yml b/changelogs/unreleased/fix-median-counting-for-cycle-analytics.yml new file mode 100644 index 00000000000..6ae6db08ba1 --- /dev/null +++ b/changelogs/unreleased/fix-median-counting-for-cycle-analytics.yml @@ -0,0 +1,5 @@ +--- +title: Fix median counting for cycle analytics +merge_request: 30229 +author: +type: fixed -- cgit v1.2.1 From d26f2708a2abe439f57101c2b359cd6dce33e90a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C5=82gorzata=20Ksionek?= Date: Mon, 1 Jul 2019 22:06:27 +0200 Subject: Fix rubocop offence --- spec/lib/gitlab/cycle_analytics/test_stage_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb index 1d4ad1b319d..0692f8145b9 100644 --- a/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb @@ -16,7 +16,7 @@ describe Gitlab::CycleAnalytics::TestStage do before do mr_1.metrics.update!(latest_build_started_at: 32.minutes.ago, latest_build_finished_at: 2.minutes.ago) - mr_2.metrics.update!(latest_build_started_at: 62.minutes.ago, latest_build_finished_at: 32.minute.ago) + mr_2.metrics.update!(latest_build_started_at: 62.minutes.ago, latest_build_finished_at: 32.minutes.ago) mr_3.metrics.update!(latest_build_started_at: nil, latest_build_finished_at: nil) mr_4.metrics.update!(latest_build_started_at: nil, latest_build_finished_at: nil) mr_5.metrics.update!(latest_build_started_at: nil, latest_build_finished_at: nil) -- cgit v1.2.1 From 23aad1279762136dbfbcb01c01b30d1929db1bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C5=82gorzata=20Ksionek?= Date: Tue, 2 Jul 2019 12:25:02 +0200 Subject: Rearrange spec for readability --- spec/lib/gitlab/cycle_analytics/test_stage_spec.rb | 45 +++++++++++----------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb index 0692f8145b9..7881fbe589a 100644 --- a/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb @@ -4,33 +4,34 @@ require 'lib/gitlab/cycle_analytics/shared_stage_spec' describe Gitlab::CycleAnalytics::TestStage do let(:stage_name) { :test } let(:project) { create(:project) } - let!(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) } - let!(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) } - let!(:issue_3) { create(:issue, project: project, created_at: 60.minutes.ago) } - let!(:mr_1) { create(:merge_request, :closed, source_project: project, created_at: 60.minutes.ago) } - let!(:mr_2) { create(:merge_request, :closed, source_project: project, created_at: 40.minutes.ago, source_branch: 'A') } - let!(:mr_3) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'B') } - let!(:mr_4) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'C') } - let!(:mr_5) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'D') } let(:stage) { described_class.new(project: project, options: { from: 2.days.ago, current_user: project.creator }) } - before do - mr_1.metrics.update!(latest_build_started_at: 32.minutes.ago, latest_build_finished_at: 2.minutes.ago) - mr_2.metrics.update!(latest_build_started_at: 62.minutes.ago, latest_build_finished_at: 32.minutes.ago) - mr_3.metrics.update!(latest_build_started_at: nil, latest_build_finished_at: nil) - mr_4.metrics.update!(latest_build_started_at: nil, latest_build_finished_at: nil) - mr_5.metrics.update!(latest_build_started_at: nil, latest_build_finished_at: nil) - - create(:merge_requests_closing_issues, merge_request: mr_1, issue: issue_1) - create(:merge_requests_closing_issues, merge_request: mr_2, issue: issue_2) - create(:merge_requests_closing_issues, merge_request: mr_3, issue: issue_3) - create(:merge_requests_closing_issues, merge_request: mr_4, issue: issue_3) - create(:merge_requests_closing_issues, merge_request: mr_5, issue: issue_3) - end - it_behaves_like 'base stage' describe '#median' do + let!(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) } + let!(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) } + let!(:issue_3) { create(:issue, project: project, created_at: 60.minutes.ago) } + let!(:mr_1) { create(:merge_request, :closed, source_project: project, created_at: 60.minutes.ago) } + let!(:mr_2) { create(:merge_request, :closed, source_project: project, created_at: 40.minutes.ago, source_branch: 'A') } + let!(:mr_3) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'B') } + let!(:mr_4) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'C') } + let!(:mr_5) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'D') } + + before do + mr_1.metrics.update!(latest_build_started_at: 32.minutes.ago, latest_build_finished_at: 2.minutes.ago) + mr_2.metrics.update!(latest_build_started_at: 62.minutes.ago, latest_build_finished_at: 32.minutes.ago) + mr_3.metrics.update!(latest_build_started_at: nil, latest_build_finished_at: nil) + mr_4.metrics.update!(latest_build_started_at: nil, latest_build_finished_at: nil) + mr_5.metrics.update!(latest_build_started_at: nil, latest_build_finished_at: nil) + + create(:merge_requests_closing_issues, merge_request: mr_1, issue: issue_1) + create(:merge_requests_closing_issues, merge_request: mr_2, issue: issue_2) + create(:merge_requests_closing_issues, merge_request: mr_3, issue: issue_3) + create(:merge_requests_closing_issues, merge_request: mr_4, issue: issue_3) + create(:merge_requests_closing_issues, merge_request: mr_5, issue: issue_3) + end + around do |example| Timecop.freeze { example.run } end -- cgit v1.2.1 From 9d2747a6a18561c3186567908323db1ea2d43ff7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C5=82gorzata=20Ksionek?= Date: Thu, 4 Jul 2019 11:13:29 +0200 Subject: Modify specs according to review --- spec/lib/gitlab/cycle_analytics/test_stage_spec.rb | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb b/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb index 7881fbe589a..8633a63849f 100644 --- a/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb +++ b/spec/lib/gitlab/cycle_analytics/test_stage_spec.rb @@ -9,16 +9,15 @@ describe Gitlab::CycleAnalytics::TestStage do it_behaves_like 'base stage' describe '#median' do - let!(:issue_1) { create(:issue, project: project, created_at: 90.minutes.ago) } - let!(:issue_2) { create(:issue, project: project, created_at: 60.minutes.ago) } - let!(:issue_3) { create(:issue, project: project, created_at: 60.minutes.ago) } - let!(:mr_1) { create(:merge_request, :closed, source_project: project, created_at: 60.minutes.ago) } - let!(:mr_2) { create(:merge_request, :closed, source_project: project, created_at: 40.minutes.ago, source_branch: 'A') } - let!(:mr_3) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'B') } - let!(:mr_4) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'C') } - let!(:mr_5) { create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'D') } - before do + issue_1 = create(:issue, project: project, created_at: 90.minutes.ago) + issue_2 = create(:issue, project: project, created_at: 60.minutes.ago) + issue_3 = create(:issue, project: project, created_at: 60.minutes.ago) + mr_1 = create(:merge_request, :closed, source_project: project, created_at: 60.minutes.ago) + mr_2 = create(:merge_request, :closed, source_project: project, created_at: 40.minutes.ago, source_branch: 'A') + mr_3 = create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'B') + mr_4 = create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'C') + mr_5 = create(:merge_request, source_project: project, created_at: 10.minutes.ago, source_branch: 'D') mr_1.metrics.update!(latest_build_started_at: 32.minutes.ago, latest_build_finished_at: 2.minutes.ago) mr_2.metrics.update!(latest_build_started_at: 62.minutes.ago, latest_build_finished_at: 32.minutes.ago) mr_3.metrics.update!(latest_build_started_at: nil, latest_build_finished_at: nil) -- cgit v1.2.1 From d23a654fc5fa1a3c36538b8f0206e34a549689aa Mon Sep 17 00:00:00 2001 From: Mark Lapierre Date: Fri, 5 Jul 2019 09:13:29 +1000 Subject: Initialize Issue labels This provides a valid default value when labels are not specified explicitly. --- qa/qa/resource/issue.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/qa/qa/resource/issue.rb b/qa/qa/resource/issue.rb index 9c57a0f5afb..51b2af8b4ef 100644 --- a/qa/qa/resource/issue.rb +++ b/qa/qa/resource/issue.rb @@ -16,6 +16,10 @@ module QA attribute :labels attribute :title + def initialize + @labels = [] + end + def fabricate! project.visit! @@ -38,7 +42,7 @@ module QA def api_post_body { - labels: [labels], + labels: labels, title: title } end -- cgit v1.2.1 From 6e552981248a551e8c70c8d2866a401a8d1090b5 Mon Sep 17 00:00:00 2001 From: Thong Kuah Date: Fri, 5 Jul 2019 07:07:46 +0000 Subject: Remove obsolete comment --- lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml index dcf8254ef94..108f0119ae1 100644 --- a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml @@ -246,7 +246,6 @@ rollout 100%: auto_database_url=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${CI_ENVIRONMENT_SLUG}-postgres:5432/${POSTGRES_DB} export DATABASE_URL=${DATABASE_URL-$auto_database_url} export TILLER_NAMESPACE=$KUBE_NAMESPACE - # Extract "MAJOR.MINOR" from CI_SERVER_VERSION and generate "MAJOR-MINOR-stable" for Security Products function get_replicas() { track="${1:-stable}" -- cgit v1.2.1 From 4c954a5c9e54e768aaca0eb787d8d9d2f63ebcae Mon Sep 17 00:00:00 2001 From: Denys Mishunov Date: Wed, 3 Jul 2019 10:19:32 +0200 Subject: Mark images as binary on init --- app/assets/javascripts/ide/lib/files.js | 5 +++-- .../vue_shared/components/content_viewer/lib/viewer_utils.js | 1 + spec/frontend/ide/lib/files_spec.js | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/ide/lib/files.js b/app/assets/javascripts/ide/lib/files.js index b8abaa41f23..51278640b5b 100644 --- a/app/assets/javascripts/ide/lib/files.js +++ b/app/assets/javascripts/ide/lib/files.js @@ -77,6 +77,7 @@ export const decorateFiles = ({ const fileFolder = parent && insertParent(parent); if (name) { + const previewMode = viewerInformationForPath(name); parentPath = fileFolder && fileFolder.path; file = decorateData({ @@ -92,9 +93,9 @@ export const decorateFiles = ({ changed: tempFile, content, base64, - binary, + binary: (previewMode && previewMode.binary) || binary, rawPath, - previewMode: viewerInformationForPath(name), + previewMode, parentPath, }); diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/lib/viewer_utils.js b/app/assets/javascripts/vue_shared/components/content_viewer/lib/viewer_utils.js index ba63683f5c0..da0b45110e2 100644 --- a/app/assets/javascripts/vue_shared/components/content_viewer/lib/viewer_utils.js +++ b/app/assets/javascripts/vue_shared/components/content_viewer/lib/viewer_utils.js @@ -3,6 +3,7 @@ import { __ } from '~/locale'; const viewers = { image: { id: 'image', + binary: true, }, markdown: { id: 'markdown', diff --git a/spec/frontend/ide/lib/files_spec.js b/spec/frontend/ide/lib/files_spec.js index aa1fa0373db..08a31318544 100644 --- a/spec/frontend/ide/lib/files_spec.js +++ b/spec/frontend/ide/lib/files_spec.js @@ -12,6 +12,7 @@ const createEntries = paths => { const { name, parent } = splitParent(path); const parentEntry = acc[parent]; + const previewMode = viewerInformationForPath(name); acc[path] = { ...decorateData({ @@ -22,7 +23,8 @@ const createEntries = paths => { path, url: createUrl(`/${TEST_PROJECT_ID}/${type}/${TEST_BRANCH_ID}/-/${escapeFileUrl(path)}`), type, - previewMode: viewerInformationForPath(path), + previewMode, + binary: (previewMode && previewMode.binary) || false, parentPath: parent, parentTreeUrl: parentEntry ? parentEntry.url -- cgit v1.2.1 From 352d535849e31e7defd0ce0e70fe3543f7282a17 Mon Sep 17 00:00:00 2001 From: Denys Mishunov Date: Fri, 5 Jul 2019 00:30:34 +0200 Subject: Fixed back navigation for projects filter Filterable list now sends request to filter the projects list explicitly with `json` extension to avoid breakage when navigating back from a project to the filtered project's list. --- app/assets/javascripts/filterable_list.js | 6 ++- .../projects/projects_filterable_list.js | 7 +++ app/assets/javascripts/projects_list.js | 4 +- changelogs/unreleased/62088-search-back.yml | 5 ++ spec/frontend/filterable_list_spec.js | 53 ++++++++++++++++++++++ .../projects/projects_filterable_list_spec.js | 31 +++++++++++++ 6 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 app/assets/javascripts/projects/projects_filterable_list.js create mode 100644 changelogs/unreleased/62088-search-back.yml create mode 100644 spec/frontend/filterable_list_spec.js create mode 100644 spec/frontend/projects/projects_filterable_list_spec.js diff --git a/app/assets/javascripts/filterable_list.js b/app/assets/javascripts/filterable_list.js index 64b09c8b62c..77080691dcb 100644 --- a/app/assets/javascripts/filterable_list.js +++ b/app/assets/javascripts/filterable_list.js @@ -17,11 +17,13 @@ export default class FilterableList { } getFilterEndpoint() { - return `${this.filterForm.getAttribute('action')}?${$(this.filterForm).serialize()}`; + return this.getPagePath(); } getPagePath() { - return this.getFilterEndpoint(); + const action = this.filterForm.getAttribute('action'); + const params = $(this.filterForm).serialize(); + return `${action}${action.indexOf('?') > 0 ? '&' : '?'}${params}`; } initSearch() { diff --git a/app/assets/javascripts/projects/projects_filterable_list.js b/app/assets/javascripts/projects/projects_filterable_list.js new file mode 100644 index 00000000000..433c894e668 --- /dev/null +++ b/app/assets/javascripts/projects/projects_filterable_list.js @@ -0,0 +1,7 @@ +import FilterableList from '~/filterable_list'; + +export default class ProjectsFilterableList extends FilterableList { + getFilterEndpoint() { + return this.getPagePath().replace('/projects?', '/projects.json?'); + } +} diff --git a/app/assets/javascripts/projects_list.js b/app/assets/javascripts/projects_list.js index c67d59d2be5..913b62ba26d 100644 --- a/app/assets/javascripts/projects_list.js +++ b/app/assets/javascripts/projects_list.js @@ -1,4 +1,4 @@ -import FilterableList from './filterable_list'; +import ProjectsFilterableList from './projects/projects_filterable_list'; /** * Makes search request for projects when user types a value in the search input. @@ -11,7 +11,7 @@ export default class ProjectsList { const holder = document.querySelector('.js-projects-list-holder'); if (form && filter && holder) { - const list = new FilterableList(form, filter, holder); + const list = new ProjectsFilterableList(form, filter, holder); list.initSearch(); } } diff --git a/changelogs/unreleased/62088-search-back.yml b/changelogs/unreleased/62088-search-back.yml new file mode 100644 index 00000000000..4758e927880 --- /dev/null +++ b/changelogs/unreleased/62088-search-back.yml @@ -0,0 +1,5 @@ +--- +title: Fixed back navigation for projects filter +merge_request: 30373 +author: +type: fixed diff --git a/spec/frontend/filterable_list_spec.js b/spec/frontend/filterable_list_spec.js new file mode 100644 index 00000000000..67d18611661 --- /dev/null +++ b/spec/frontend/filterable_list_spec.js @@ -0,0 +1,53 @@ +import FilterableList from '~/filterable_list'; +import { getJSONFixture, setHTMLFixture } from './helpers/fixtures'; + +describe('FilterableList', () => { + let List; + let form; + let filter; + let holder; + + beforeEach(() => { + setHTMLFixture(` +
+ + +
+ `); + getJSONFixture('static/projects.json'); + form = document.querySelector('form#project-filter-form'); + filter = document.querySelector('.js-projects-list-filter'); + holder = document.querySelector('.js-projects-list-holder'); + List = new FilterableList(form, filter, holder); + }); + + it('processes input parameters', () => { + expect(List.filterForm).toEqual(form); + expect(List.listFilterElement).toEqual(filter); + expect(List.listHolderElement).toEqual(holder); + }); + + describe('getPagePath', () => { + it('returns properly constructed base endpoint', () => { + List.filterForm.action = '/foo/bar/'; + List.listFilterElement.value = 'blah'; + + expect(List.getPagePath()).toEqual('/foo/bar/?name=blah'); + }); + + it('properly appends custom parameters to existing URL', () => { + List.filterForm.action = '/foo/bar?alpha=beta'; + List.listFilterElement.value = 'blah'; + + expect(List.getPagePath()).toEqual('/foo/bar?alpha=beta&name=blah'); + }); + }); + + describe('getFilterEndpoint', () => { + it('returns getPagePath by default', () => { + jest.spyOn(List, 'getPagePath').mockReturnValue('blah/blah/foo'); + + expect(List.getFilterEndpoint()).toEqual(List.getPagePath()); + }); + }); +}); diff --git a/spec/frontend/projects/projects_filterable_list_spec.js b/spec/frontend/projects/projects_filterable_list_spec.js new file mode 100644 index 00000000000..e756fb3ab56 --- /dev/null +++ b/spec/frontend/projects/projects_filterable_list_spec.js @@ -0,0 +1,31 @@ +import ProjectsFilterableList from '~/projects/projects_filterable_list'; +import { getJSONFixture, setHTMLFixture } from '../helpers/fixtures'; + +describe('ProjectsFilterableList', () => { + let List; + let form; + let filter; + let holder; + + beforeEach(() => { + setHTMLFixture(` + + + +
+ `); + getJSONFixture('static/projects.json'); + form = document.querySelector('form#project-filter-form'); + filter = document.querySelector('.js-projects-list-filter'); + holder = document.querySelector('.js-projects-list-holder'); + List = new ProjectsFilterableList(form, filter, holder); + }); + + describe('getFilterEndpoint', () => { + it('updates converts getPagePath for projects', () => { + jest.spyOn(List, 'getPagePath').mockReturnValue('blah/projects?'); + + expect(List.getFilterEndpoint()).toEqual('blah/projects.json?'); + }); + }); +}); -- cgit v1.2.1 From 3b725491a311c762a86c9e5b35014374c13fbe98 Mon Sep 17 00:00:00 2001 From: Lukas Eipert Date: Fri, 5 Jul 2019 11:35:37 +0000 Subject: Update dependency @gitlab/svgs to ^1.67.0 --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 47e7dd9c9c9..5b255f55e33 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "@babel/plugin-syntax-import-meta": "^7.2.0", "@babel/preset-env": "^7.4.4", "@gitlab/csslab": "^1.9.0", - "@gitlab/svgs": "^1.66.0", + "@gitlab/svgs": "^1.67.0", "@gitlab/ui": "^5.3.2", "apollo-cache-inmemory": "^1.5.1", "apollo-client": "^2.5.1", diff --git a/yarn.lock b/yarn.lock index b76eba830b1..825a1785c3e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -700,10 +700,10 @@ dependencies: requireindex "~1.1.0" -"@gitlab/svgs@^1.66.0": - version "1.66.0" - resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.66.0.tgz#3c02da455421ea241f32e915671842435df027ff" - integrity sha512-nxOoQPnofMs3BjRr3SVzQcclM0G6QFrLM8L4nnUCN+8Gxq2u8ukfSU5FCrkivXz+FP9Qo/FYilWV7CY8kDkt6A== +"@gitlab/svgs@^1.67.0": + version "1.67.0" + resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.67.0.tgz#c7b94eca13b99fd3aaa737fb6dcc0abc41d3c579" + integrity sha512-hJOmWEs6RkjzyKkb1vc9wwKGZIBIP0coHkxu/KgOoxhBVudpGk4CH7xJ6UuB2TKpb0SEh5CC1CzRZfBYaFhsaA== "@gitlab/ui@^5.3.2": version "5.3.2" -- cgit v1.2.1 From 031e91beebfe6d9de469a3635ba898e434da9d31 Mon Sep 17 00:00:00 2001 From: Zeger-Jan van de Weg Date: Thu, 27 Jun 2019 14:10:05 +0200 Subject: Remove high cardinality Prometheus metric The metric was used to correlate Gitaly requests to the Rails controller and action combination. However, Kibana provides better observability in this specific metric, and can handle hig cardinality much better. There's no dashboard in Grafana that currently depends on this metric being exposed. --- lib/gitlab/gitaly_client.rb | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb index 47976389af6..9e3de910e3c 100644 --- a/lib/gitlab/gitaly_client.rb +++ b/lib/gitlab/gitaly_client.rb @@ -33,11 +33,6 @@ module Gitlab MUTEX = Mutex.new - define_histogram :gitaly_controller_action_duration_seconds do - docstring "Gitaly endpoint histogram by controller and action combination" - base_labels Gitlab::Metrics::Transaction::BASE_LABELS.merge(gitaly_service: nil, rpc: nil) - end - def self.stub(name, storage) MUTEX.synchronize do @stubs ||= {} @@ -161,10 +156,6 @@ module Gitlab # Keep track, separately, for the performance bar self.query_time += duration - gitaly_controller_action_duration_seconds.observe( - current_transaction_labels.merge(gitaly_service: service.to_s, rpc: rpc.to_s), - duration) - if peek_enabled? add_call_details(feature: "#{service}##{rpc}", duration: duration, request: request_hash, rpc: rpc, backtrace: Gitlab::Profiler.clean_backtrace(caller)) -- cgit v1.2.1 From 88a7e93caa958ae1b42f46ca1eae312e4338564d Mon Sep 17 00:00:00 2001 From: Filipa Lacerda Date: Fri, 5 Jul 2019 13:51:35 +0100 Subject: Removes EE differences --- app/views/admin/users/show.html.haml | 2 +- changelogs/unreleased/12533-shared-runners-warning.yml | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 changelogs/unreleased/12533-shared-runners-warning.yml diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml index 5c6131db37d..a988f746ced 100644 --- a/app/views/admin/users/show.html.haml +++ b/app/views/admin/users/show.html.haml @@ -139,7 +139,7 @@ %strong = link_to @user.created_by.name, [:admin, @user.created_by] - = render_if_exists partial: "namespaces/shared_runner_status", locals: { namespace: @user.namespace } + = render_if_exists 'namespaces/shared_runner_status', namespace: @user.namespace .col-md-6 - unless @user == current_user diff --git a/changelogs/unreleased/12533-shared-runners-warning.yml b/changelogs/unreleased/12533-shared-runners-warning.yml new file mode 100644 index 00000000000..b2b526cc2e4 --- /dev/null +++ b/changelogs/unreleased/12533-shared-runners-warning.yml @@ -0,0 +1,5 @@ +--- +title: Removes EE differences for app/views/admin/users/show.html.haml +merge_request: +author: +type: other -- cgit v1.2.1 From ff1a4a4241f1628491a1aec05b440ff650ba66ad Mon Sep 17 00:00:00 2001 From: Denys Mishunov Date: Wed, 3 Jul 2019 14:14:44 +0200 Subject: Initiate editor for any file without content Important to get file data for any file that has no content set yet: we need this information in order to build a previe for changed/staged files if they were not yet opened in the editor --- .../javascripts/ide/components/repo_editor.vue | 4 ++- .../javascripts/ide/stores/mutations/file.js | 26 +++++++------- .../unreleased/60856-deleting-binary-file.yml | 5 +++ .../javascripts/ide/components/repo_editor_spec.js | 40 ++++++++++++++++++++++ spec/javascripts/ide/stores/mutations/file_spec.js | 20 +++++++++++ 5 files changed, 81 insertions(+), 14 deletions(-) create mode 100644 changelogs/unreleased/60856-deleting-binary-file.yml diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue index 5fcb11a232e..03756a634d5 100644 --- a/app/assets/javascripts/ide/components/repo_editor.vue +++ b/app/assets/javascripts/ide/components/repo_editor.vue @@ -144,7 +144,9 @@ export default { 'triggerFilesChange', ]), initEditor() { - if (this.shouldHideEditor) return; + if (this.shouldHideEditor && (this.file.content || this.file.raw)) { + return; + } this.editor.clearEditor(); diff --git a/app/assets/javascripts/ide/stores/mutations/file.js b/app/assets/javascripts/ide/stores/mutations/file.js index c88244492e0..a52f1e235ed 100644 --- a/app/assets/javascripts/ide/stores/mutations/file.js +++ b/app/assets/javascripts/ide/stores/mutations/file.js @@ -1,6 +1,7 @@ import * as types from '../mutation_types'; import { sortTree } from '../utils'; import { diffModes } from '../../constants'; +import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; export default { [types.SET_FILE_ACTIVE](state, { path, active }) { @@ -35,19 +36,18 @@ export default { } }, [types.SET_FILE_DATA](state, { data, file }) { - Object.assign(state.entries[file.path], { - id: data.id, - blamePath: data.blame_path, - commitsPath: data.commits_path, - permalink: data.permalink, - rawPath: data.raw_path, - binary: data.binary, - renderError: data.render_error, - raw: (state.entries[file.path] && state.entries[file.path].raw) || null, - baseRaw: null, - html: data.html, - size: data.size, - lastCommitSha: data.last_commit_sha, + const stateEntry = state.entries[file.path]; + const stagedFile = state.stagedFiles.find(f => f.path === file.path); + const openFile = state.openFiles.find(f => f.path === file.path); + const changedFile = state.changedFiles.find(f => f.path === file.path); + + [stateEntry, stagedFile, openFile, changedFile].forEach(f => { + if (f) { + Object.assign(f, convertObjectPropsToCamelCase(data, { dropKeys: ['raw', 'baseRaw'] }), { + raw: (stateEntry && stateEntry.raw) || null, + baseRaw: null, + }); + } }); }, [types.SET_FILE_RAW_DATA](state, { file, raw }) { diff --git a/changelogs/unreleased/60856-deleting-binary-file.yml b/changelogs/unreleased/60856-deleting-binary-file.yml new file mode 100644 index 00000000000..9b587ed591b --- /dev/null +++ b/changelogs/unreleased/60856-deleting-binary-file.yml @@ -0,0 +1,5 @@ +--- +title: Removing an image should not output binary data +merge_request: 30314 +author: +type: fixed diff --git a/spec/javascripts/ide/components/repo_editor_spec.js b/spec/javascripts/ide/components/repo_editor_spec.js index f832096701f..7dc5cb24981 100644 --- a/spec/javascripts/ide/components/repo_editor_spec.js +++ b/spec/javascripts/ide/components/repo_editor_spec.js @@ -30,6 +30,7 @@ describe('RepoEditor', () => { Vue.set(vm.$store.state.entries, f.path, f); spyOn(vm, 'getFileData').and.returnValue(Promise.resolve()); + spyOn(vm, 'getRawFileData').and.returnValue(Promise.resolve()); vm.$mount(); @@ -407,6 +408,44 @@ describe('RepoEditor', () => { }); }); + describe('initEditor', () => { + beforeEach(() => { + spyOn(vm.editor, 'createInstance'); + spyOnProperty(vm, 'shouldHideEditor').and.returnValue(true); + }); + + it('is being initialised for files without content even if shouldHideEditor is `true`', done => { + vm.file.content = ''; + vm.file.raw = ''; + + vm.initEditor(); + vm.$nextTick() + .then(() => { + expect(vm.getFileData).toHaveBeenCalled(); + expect(vm.getRawFileData).toHaveBeenCalled(); + }) + .then(done) + .catch(done.fail); + }); + + it('does not initialize editor for files already with content', done => { + expect(vm.getFileData.calls.count()).toEqual(1); + expect(vm.getRawFileData.calls.count()).toEqual(1); + + vm.file.content = 'foo'; + + vm.initEditor(); + vm.$nextTick() + .then(() => { + expect(vm.getFileData.calls.count()).toEqual(1); + expect(vm.getRawFileData.calls.count()).toEqual(1); + expect(vm.editor.createInstance).not.toHaveBeenCalled(); + }) + .then(done) + .catch(done.fail); + }); + }); + it('calls removePendingTab when old file is pending', done => { spyOnProperty(vm, 'shouldHideEditor').and.returnValue(true); spyOn(vm, 'removePendingTab'); @@ -416,6 +455,7 @@ describe('RepoEditor', () => { vm.$nextTick() .then(() => { vm.file = file('testing'); + vm.file.content = 'foo'; // need to prevent full cycle of initEditor return vm.$nextTick(); }) diff --git a/spec/javascripts/ide/stores/mutations/file_spec.js b/spec/javascripts/ide/stores/mutations/file_spec.js index 18ee4330f69..7714f66c9a4 100644 --- a/spec/javascripts/ide/stores/mutations/file_spec.js +++ b/spec/javascripts/ide/stores/mutations/file_spec.js @@ -83,6 +83,26 @@ describe('IDE store file mutations', () => { expect(localFile.raw).toBeNull(); expect(localFile.baseRaw).toBeNull(); }); + + it('sets extra file data to all arrays concerned', () => { + localState.stagedFiles = [localFile]; + localState.changedFiles = [localFile]; + localState.openFiles = [localFile]; + + const rawPath = 'foo/bar/blah.md'; + + mutations.SET_FILE_DATA(localState, { + data: { + raw_path: rawPath, + }, + file: localFile, + }); + + expect(localState.stagedFiles[0].rawPath).toEqual(rawPath); + expect(localState.changedFiles[0].rawPath).toEqual(rawPath); + expect(localState.openFiles[0].rawPath).toEqual(rawPath); + expect(localFile.rawPath).toEqual(rawPath); + }); }); describe('SET_FILE_RAW_DATA', () => { -- cgit v1.2.1 From 7ca77203c0622697123e2fdb6f377d87e3de901b Mon Sep 17 00:00:00 2001 From: Lukas Eipert Date: Thu, 4 Jul 2019 13:36:49 +0200 Subject: Replace runtime isEE check with compile time one This has the benefit that CE bundles will remove dead code in CE only builds. We have a follow-up issue to get rid of this completely: https://gitlab.com/gitlab-org/gitlab-ce/issues/64173 --- .eslintrc.yml | 1 + app/assets/javascripts/boards/filtered_search_boards.js | 3 +-- app/assets/javascripts/boards/models/issue.js | 6 +++--- app/assets/javascripts/boards/models/list.js | 8 ++++---- app/assets/javascripts/boards/models/milestone.js | 4 +--- app/assets/javascripts/event_tracking/notes.js | 1 + app/assets/javascripts/labels_select.js | 4 ++-- app/assets/javascripts/lib/utils/common_utils.js | 8 -------- app/assets/javascripts/monitoring/components/dashboard.vue | 11 ++++++++--- app/assets/javascripts/notes/index.js | 5 +---- app/assets/javascripts/vue_shared/mixins/is_ee.js | 10 ---------- config/webpack.config.js | 3 +++ spec/javascripts/test_bundle.js | 2 -- 13 files changed, 25 insertions(+), 41 deletions(-) delete mode 100644 app/assets/javascripts/vue_shared/mixins/is_ee.js diff --git a/.eslintrc.yml b/.eslintrc.yml index 2b881d5f201..2612fd3371d 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -5,6 +5,7 @@ globals: gl: false gon: false localStorage: false + IS_EE: false plugins: - import - html diff --git a/app/assets/javascripts/boards/filtered_search_boards.js b/app/assets/javascripts/boards/filtered_search_boards.js index 6b54e8baefb..b1b4b1c5508 100644 --- a/app/assets/javascripts/boards/filtered_search_boards.js +++ b/app/assets/javascripts/boards/filtered_search_boards.js @@ -2,7 +2,6 @@ import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable import FilteredSearchContainer from '../filtered_search/container'; import FilteredSearchManager from '../filtered_search/filtered_search_manager'; import boardsStore from './stores/boards_store'; -import { isEE } from '~/lib/utils/common_utils'; export default class FilteredSearchBoards extends FilteredSearchManager { constructor(store, updateUrl = false, cantEdit = []) { @@ -10,7 +9,7 @@ export default class FilteredSearchBoards extends FilteredSearchManager { page: 'boards', isGroupDecendent: true, stateFiltersSelector: '.issues-state-filters', - isGroup: isEE(), + isGroup: IS_EE, filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys, }); diff --git a/app/assets/javascripts/boards/models/issue.js b/app/assets/javascripts/boards/models/issue.js index f858b162c6b..9069b35db9a 100644 --- a/app/assets/javascripts/boards/models/issue.js +++ b/app/assets/javascripts/boards/models/issue.js @@ -5,7 +5,7 @@ import Vue from 'vue'; import './label'; -import { isEE, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; +import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import IssueProject from './project'; import boardsStore from '../stores/boards_store'; @@ -91,13 +91,13 @@ class ListIssue { addMilestone(milestone) { const miletoneId = this.milestone ? this.milestone.id : null; - if (isEE && milestone.id !== miletoneId) { + if (IS_EE && milestone.id !== miletoneId) { this.milestone = new ListMilestone(milestone); } } removeMilestone(removeMilestone) { - if (isEE && removeMilestone && removeMilestone.id === this.milestone.id) { + if (IS_EE && removeMilestone && removeMilestone.id === this.milestone.id) { this.milestone = {}; } } diff --git a/app/assets/javascripts/boards/models/list.js b/app/assets/javascripts/boards/models/list.js index cd553d0c4af..7e0ccb9bd2a 100644 --- a/app/assets/javascripts/boards/models/list.js +++ b/app/assets/javascripts/boards/models/list.js @@ -4,7 +4,7 @@ import { __ } from '~/locale'; import ListLabel from './label'; import ListAssignee from './assignee'; -import { isEE, urlParamsToObject } from '~/lib/utils/common_utils'; +import { urlParamsToObject } from '~/lib/utils/common_utils'; import boardsStore from '../stores/boards_store'; import ListMilestone from './milestone'; @@ -58,7 +58,7 @@ class List { } else if (obj.user) { this.assignee = new ListAssignee(obj.user); this.title = this.assignee.name; - } else if (isEE && obj.milestone) { + } else if (IS_EE && obj.milestone) { this.milestone = new ListMilestone(obj.milestone); this.title = this.milestone.title; } @@ -85,7 +85,7 @@ class List { entityType = 'label_id'; } else if (this.assignee) { entityType = 'assignee_id'; - } else if (isEE && this.milestone) { + } else if (IS_EE && this.milestone) { entityType = 'milestone_id'; } @@ -205,7 +205,7 @@ class List { issue.addAssignee(this.assignee); } - if (isEE && this.milestone) { + if (IS_EE && this.milestone) { if (listFrom && listFrom.type === 'milestone') { issue.removeMilestone(listFrom.milestone); } diff --git a/app/assets/javascripts/boards/models/milestone.js b/app/assets/javascripts/boards/models/milestone.js index 6f81d6bc6f8..7201b6e91f5 100644 --- a/app/assets/javascripts/boards/models/milestone.js +++ b/app/assets/javascripts/boards/models/milestone.js @@ -1,11 +1,9 @@ -import { isEE } from '~/lib/utils/common_utils'; - export default class ListMilestone { constructor(obj) { this.id = obj.id; this.title = obj.title; - if (isEE) { + if (IS_EE) { this.path = obj.path; this.state = obj.state; this.webUrl = obj.web_url || obj.webUrl; diff --git a/app/assets/javascripts/event_tracking/notes.js b/app/assets/javascripts/event_tracking/notes.js index 2d1ec238274..1f70290c397 100644 --- a/app/assets/javascripts/event_tracking/notes.js +++ b/app/assets/javascripts/event_tracking/notes.js @@ -1 +1,2 @@ +// Noop function which has a EE counter-part export default () => {}; diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js index 3f954b43ee3..bea43430edc 100644 --- a/app/assets/javascripts/labels_select.js +++ b/app/assets/javascripts/labels_select.js @@ -11,7 +11,7 @@ import CreateLabelDropdown from './create_label'; import flash from './flash'; import ModalStore from './boards/stores/modal_store'; import boardsStore from './boards/stores/boards_store'; -import { isEE, isScopedLabel } from '~/lib/utils/common_utils'; +import { isScopedLabel } from '~/lib/utils/common_utils'; export default class LabelsSelect { constructor(els, options = {}) { @@ -140,7 +140,7 @@ export default class LabelsSelect { labelCount = data.labels.length; // EE Specific - if (isEE) { + if (IS_EE) { /** * For Scoped labels, the last label selected with the * same key will be applied to the current issueable. diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js index cc5e12aa467..5e90893b684 100644 --- a/app/assets/javascripts/lib/utils/common_utils.js +++ b/app/assets/javascripts/lib/utils/common_utils.js @@ -726,14 +726,6 @@ export const NavigationType = { TYPE_RESERVED: 255, }; -/** - * Returns the value of `gon.ee` - * Used to check if it's the EE codebase or the CE one. - * - * @returns Boolean - */ -export const isEE = () => window.gon && window.gon.ee; - /** * Checks if the given Label has a special syntax `::` in * it's title. diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue index ed25a6e3684..ba79a697df2 100644 --- a/app/assets/javascripts/monitoring/components/dashboard.vue +++ b/app/assets/javascripts/monitoring/components/dashboard.vue @@ -4,7 +4,6 @@ import _ from 'underscore'; import { mapActions, mapState } from 'vuex'; import { s__ } from '~/locale'; import Icon from '~/vue_shared/components/icon.vue'; -import '~/vue_shared/mixins/is_ee'; import { getParameterValues } from '~/lib/utils/url_utility'; import invalidUrl from '~/lib/utils/invalid_url'; import MonitorAreaChart from './charts/area.vue'; @@ -160,6 +159,12 @@ export default { selectedDashboardText() { return this.currentDashboard || (this.allDashboards[0] && this.allDashboards[0].display_name); }, + addingMetricsAvailable() { + return IS_EE && this.canAddMetrics && !this.showEmptyState; + }, + alertWidgetAvailable() { + return IS_EE && this.prometheusAlertsAvailable && this.alertsEndpoint; + }, }, created() { this.setEndpoints({ @@ -313,7 +318,7 @@ export default {
-
+
{ }; }, mounted() { - if (isEE) { - initNoteStats(); - } + initNoteStats(); }, render(createElement) { return createElement('notes-app', { diff --git a/app/assets/javascripts/vue_shared/mixins/is_ee.js b/app/assets/javascripts/vue_shared/mixins/is_ee.js deleted file mode 100644 index 8e00d93ef18..00000000000 --- a/app/assets/javascripts/vue_shared/mixins/is_ee.js +++ /dev/null @@ -1,10 +0,0 @@ -import Vue from 'vue'; -import { isEE } from '~/lib/utils/common_utils'; - -Vue.mixin({ - computed: { - isEE() { - return isEE(); - }, - }, -}); diff --git a/config/webpack.config.js b/config/webpack.config.js index 19b48845305..a81590e8b8e 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -322,7 +322,10 @@ module.exports = { }), new webpack.DefinePlugin({ + // This one is used to define window.gon.ee and other things properly in tests: 'process.env.IS_GITLAB_EE': JSON.stringify(IS_EE), + // This one is used to check against "EE" properly in application code + IS_EE: IS_EE ? 'window.gon && window.gon.ee' : JSON.stringify(false), }), ].filter(Boolean), diff --git a/spec/javascripts/test_bundle.js b/spec/javascripts/test_bundle.js index 2cc476ed52a..50741e249ca 100644 --- a/spec/javascripts/test_bundle.js +++ b/spec/javascripts/test_bundle.js @@ -8,7 +8,6 @@ import '~/commons'; import Vue from 'vue'; import VueResource from 'vue-resource'; import Translate from '~/vue_shared/translate'; -import CheckEE from '~/vue_shared/mixins/is_ee'; import jasmineDiff from 'jasmine-diff'; import { config as testUtilsConfig } from '@vue/test-utils'; @@ -48,7 +47,6 @@ Vue.config.errorHandler = function(err) { Vue.use(VueResource); Vue.use(Translate); -Vue.use(CheckEE); // enable test fixtures jasmine.getFixtures().fixturesPath = FIXTURES_PATH; -- cgit v1.2.1 From fa790f5512c6a700239b395e81ecc2a45edd24fd Mon Sep 17 00:00:00 2001 From: Phil Hughes Date: Fri, 5 Jul 2019 15:54:37 +0100 Subject: Fixed apollo caching of the root repository file listing --- app/assets/javascripts/repository/components/table/index.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/repository/components/table/index.vue b/app/assets/javascripts/repository/components/table/index.vue index 1e66ccbfa29..0d9e992e596 100644 --- a/app/assets/javascripts/repository/components/table/index.vue +++ b/app/assets/javascripts/repository/components/table/index.vue @@ -76,7 +76,7 @@ export default { variables: { projectPath: this.projectPath, ref: this.ref, - path: this.path, + path: this.path || '/', nextPageCursor: this.nextPageCursor, pageSize: PAGE_SIZE, }, -- cgit v1.2.1 From a5c0809f3bf35303af087a4c35000f664f55d172 Mon Sep 17 00:00:00 2001 From: Douglas Barbosa Alexandre Date: Thu, 4 Jul 2019 18:25:54 -0300 Subject: Add note that internal URL works only with a LB with TLS termination --- doc/user/admin_area/geo_nodes.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/user/admin_area/geo_nodes.md b/doc/user/admin_area/geo_nodes.md index d99b87cbc5c..f535e7790bc 100644 --- a/doc/user/admin_area/geo_nodes.md +++ b/doc/user/admin_area/geo_nodes.md @@ -61,6 +61,12 @@ which is used by users. Internal URL does not need to be a private address. Internal URL defaults to External URL, but you can customize it under **Admin area > Geo Nodes**. +CAUTION: **Warning:** +We recommend using an HTTPS connection while configuring the Geo nodes. To avoid +breaking communication between **primary** and **secondary** nodes when using +HTTPS, customize your Internal URL to point to a Load Balancer with TLS +termination. + ## Multiple secondary nodes behind a load balancer In GitLab 11.11, **secondary** nodes can use identical external URLs as long as @@ -83,4 +89,4 @@ questions that you know someone might ask. Each scenario can be a third-level heading, e.g. `### Getting error message X`. If you have none to add when creating a doc, leave this section in place -but commented out to help encourage others to add to it in the future. --> \ No newline at end of file +but commented out to help encourage others to add to it in the future. --> -- cgit v1.2.1 From 7c41a02e4a695d42344488819111b5387d605e7e Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Fri, 5 Jul 2019 10:33:04 -0500 Subject: Fix top position of sticky file header on discussion tab --- app/assets/stylesheets/pages/notes.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 7bd1a4138e4..00c6a3a5476 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -406,7 +406,7 @@ $note-form-margin-left: 72px; border-radius: 0; @media (min-width: map-get($grid-breakpoints, md)) { - top: 91px; + top: $mr-tabs-height + $header-height; .with-performance-bar & { top: 126px; -- cgit v1.2.1 From 5f18598c0505adf78ed6078fbdee9846b7efddac Mon Sep 17 00:00:00 2001 From: mfluharty Date: Fri, 5 Jul 2019 09:57:38 -0600 Subject: Pin modals at 64px from the top of the viewport Was 30px --- app/assets/stylesheets/framework/modal.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/framework/modal.scss b/app/assets/stylesheets/framework/modal.scss index f75e5b55506..f8b3a1966d7 100644 --- a/app/assets/stylesheets/framework/modal.scss +++ b/app/assets/stylesheets/framework/modal.scss @@ -85,9 +85,9 @@ body.modal-open { .modal { background-color: $black-transparent; - @include media-breakpoint-up(md) { + @include media-breakpoint-up(sm) { .modal-dialog { - margin: 30px auto; + margin: 64px auto; } } } -- cgit v1.2.1 From 6feda1df3b53df3d2fb9f8ac076049fbf3ffc0f1 Mon Sep 17 00:00:00 2001 From: Marcel Amirault Date: Fri, 5 Jul 2019 16:25:58 +0000 Subject: Change absolute links to relative Change assorted absolute links to ce and ee docs to relative links --- doc/administration/gitaly/index.md | 10 ++++---- doc/administration/logs.md | 2 +- doc/administration/raketasks/maintenance.md | 2 +- .../ci_cd_for_external_repos/github_integration.md | 2 +- doc/development/changelog.md | 2 +- doc/development/chatops_on_gitlabcom.md | 2 +- doc/development/documentation/styleguide.md | 2 +- doc/development/feature_flags/controls.md | 4 +-- doc/development/feature_flags/development.md | 2 +- .../testing_guide/end_to_end/quick_start_guide.md | 8 +++--- doc/install/google_cloud_platform/index.md | 6 ++--- doc/raketasks/README.md | 2 +- .../application_development_platform/index.md | 30 +++++++++++----------- doc/university/README.md | 2 +- doc/user/project/integrations/webhooks.md | 2 +- doc/user/project/issues/managing_issues.md | 2 +- .../project/pages/getting_started_part_four.md | 2 +- doc/workflow/repository_mirroring.md | 4 +-- 18 files changed, 43 insertions(+), 43 deletions(-) diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md index 7c7bb9045c7..b98383f30fc 100644 --- a/doc/administration/gitaly/index.md +++ b/doc/administration/gitaly/index.md @@ -441,12 +441,12 @@ and want to eliminate NFS from your environment altogether, there are a few things that you need to do: 1. Make sure the [`git` user home directory](https://docs.gitlab.com/omnibus/settings/configuration.html#moving-the-home-directory-for-a-user) is on local disk. - 1. Configure [database lookup of SSH keys](https://docs.gitlab.com/ce/administration/operations/fast_ssh_key_lookup.html) + 1. Configure [database lookup of SSH keys](../operations/fast_ssh_key_lookup.md) to eliminate the need for a shared authorized_keys file. - 1. Configure [object storage for job artifacts](https://docs.gitlab.com/ce/administration/job_artifacts.html#using-object-storage) - including [live tracing](https://docs.gitlab.com/ce/administration/job_traces.html#new-live-trace-architecture). - 1. Configure [object storage for LFS objects](https://docs.gitlab.com/ce/workflow/lfs/lfs_administration.html#storing-lfs-objects-in-remote-object-storage). - 1. Configure [object storage for uploads](https://docs.gitlab.com/ce/administration/uploads.html#using-object-storage-core-only). + 1. Configure [object storage for job artifacts](../job_artifacts.md#using-object-storage) + including [live tracing](../job_traces.md#new-live-trace-architecture). + 1. Configure [object storage for LFS objects](../../workflow/lfs/lfs_administration.md#storing-lfs-objects-in-remote-object-storage). + 1. Configure [object storage for uploads](../uploads.md#using-object-storage-core-only). NOTE: **Note:** One current feature of GitLab still requires a shared directory (NFS): [GitLab Pages](../../user/project/pages/index.md). There is [work in progress](https://gitlab.com/gitlab-org/gitlab-pages/issues/196) diff --git a/doc/administration/logs.md b/doc/administration/logs.md index b49d8c8a28f..5a2f389d298 100644 --- a/doc/administration/logs.md +++ b/doc/administration/logs.md @@ -4,7 +4,7 @@ GitLab has an advanced log system where everything is logged so that you can analyze your instance using various system log files. In addition to system log files, GitLab Enterprise Edition comes with Audit Events. Find more about them [in Audit Events -documentation](https://docs.gitlab.com/ee/administration/audit_events.html) +documentation](audit_events.md) System log files are typically plain text in a standard log file format. This guide talks about how to read and use these system log files. diff --git a/doc/administration/raketasks/maintenance.md b/doc/administration/raketasks/maintenance.md index becd480a08f..2b31233d429 100644 --- a/doc/administration/raketasks/maintenance.md +++ b/doc/administration/raketasks/maintenance.md @@ -61,7 +61,7 @@ It will check that each component was set up according to the installation guide You may also have a look at our Troubleshooting Guides: -- [Troubleshooting Guide (GitLab)](http://docs.gitlab.com/ee/README.html#troubleshooting) +- [Troubleshooting Guide (GitLab)](../index.md#troubleshooting) - [Troubleshooting Guide (Omnibus Gitlab)](https://docs.gitlab.com/omnibus/README.html#troubleshooting) **Omnibus Installation** diff --git a/doc/ci/ci_cd_for_external_repos/github_integration.md b/doc/ci/ci_cd_for_external_repos/github_integration.md index 53b36181062..36031c7929f 100644 --- a/doc/ci/ci_cd_for_external_repos/github_integration.md +++ b/doc/ci/ci_cd_for_external_repos/github_integration.md @@ -109,7 +109,7 @@ your repository: new commits. The web hook URL should be set to the GitLab API to - [trigger pull mirroring](https://docs.gitlab.com/ee/api/projects.html#start-the-pull-mirroring-process-for-a-project-starter), + [trigger pull mirroring](../../api/projects.md#start-the-pull-mirroring-process-for-a-project-starter), using the GitLab personal access token we just created. ``` diff --git a/doc/development/changelog.md b/doc/development/changelog.md index 33c1c3bd9e4..f13c447fef2 100644 --- a/doc/development/changelog.md +++ b/doc/development/changelog.md @@ -35,7 +35,7 @@ the `author` field. GitLab team members **should not**. - Any user-facing change **should** have a changelog entry. Example: "GitLab now uses system fonts for all text." -- Any change behind a feature flag **should not** have a changelog entry. The entry should be added [in the merge request removing the feature flags](https://docs.gitlab.com/ee/development/feature_flags.html#developing-with-feature-flags). +- Any change behind a feature flag **should not** have a changelog entry. The entry should be added [in the merge request removing the feature flags](feature_flags/development.md). - A fix for a regression introduced and then fixed in the same release (i.e., fixing a bug introduced during a monthly release candidate) **should not** have a changelog entry. diff --git a/doc/development/chatops_on_gitlabcom.md b/doc/development/chatops_on_gitlabcom.md index a7b402c3fb0..de942c0ae94 100644 --- a/doc/development/chatops_on_gitlabcom.md +++ b/doc/development/chatops_on_gitlabcom.md @@ -17,6 +17,6 @@ To request access to Chatops on GitLab.com: ## See also - - [Chatops Usage](https://docs.gitlab.com/ee/ci/chatops/README.html) + - [Chatops Usage](../ci/chatops/README.md) - [Understanding EXPLAIN plans](understanding_explain_plans.md) - [Feature Groups](feature_flags/development.md#feature-groups) diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md index 6bfedcb1047..d0a887b6175 100644 --- a/doc/development/documentation/styleguide.md +++ b/doc/development/documentation/styleguide.md @@ -393,7 +393,7 @@ Instead: Example: ```md -For more information, see the [confidential issue](https://docs.gitlab.com/ee/user/project/issues/confidential_issues.html) `https://gitlab.com/gitlab-org/gitlab-ce/issues/`. +For more information, see the [confidential issue](../../user/project/issues/confidential_issues.md) `https://gitlab.com/gitlab-org/gitlab-ce/issues/`. ``` ### Unlinking emails diff --git a/doc/development/feature_flags/controls.md b/doc/development/feature_flags/controls.md index c67467b7c11..739f4207e27 100644 --- a/doc/development/feature_flags/controls.md +++ b/doc/development/feature_flags/controls.md @@ -5,7 +5,7 @@ GitLab Inc. provided environments such as staging and production, you need to have access to the chatops bot. Chatops bot is currently running on the ops instance, which is different from GitLab.com or dev.gitlab.org. -Follow the Chatops document to [request access](https://docs.gitlab.com/ee/development/chatops_on_gitlabcom.html#requesting-access). +Follow the Chatops document to [request access](../chatops_on_gitlabcom.md#requesting-access). Once you are added to the project test if your access propagated, run: @@ -112,7 +112,7 @@ instances. Make sure to add the ~"feature flag" label to this merge request so release managers are aware the changes are hidden behind a feature flag. If the merge request has to be picked into a stable branch, make sure to also add the appropriate "Pick into X" label (e.g. "Pick into XX.X"). -See [the process document](https://docs.gitlab.com/ee/development/feature_flags/process.html#including-a-feature-behind-feature-flag-in-the-final-release) for further details. +See [the process document](process.md#including-a-feature-behind-feature-flag-in-the-final-release) for further details. When a feature gate has been removed from the code base, the value still exists in the database. diff --git a/doc/development/feature_flags/development.md b/doc/development/feature_flags/development.md index 238052529d9..98773026122 100644 --- a/doc/development/feature_flags/development.md +++ b/doc/development/feature_flags/development.md @@ -57,7 +57,7 @@ the feature flag check will default to `true`. As an example, if you were to ship the backend half of a feature behind a flag, you'd want to explicitly disable that flag until the frontend half is also ready -to be shipped. [You can do this via Chatops](https://docs.gitlab.com/ee/development/feature_flags/controls.html): +to be shipped. [You can do this via Chatops](controls.md): ``` /chatops run feature set some_feature 0 diff --git a/doc/development/testing_guide/end_to_end/quick_start_guide.md b/doc/development/testing_guide/end_to_end/quick_start_guide.md index 041bdf716b3..064fb0e31dd 100644 --- a/doc/development/testing_guide/end_to_end/quick_start_guide.md +++ b/doc/development/testing_guide/end_to_end/quick_start_guide.md @@ -394,15 +394,15 @@ end By defining the `api_get_path` method, we allow the [`ApiFabricator`](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/qa/qa/resource/api_fabricator.rb) module to know which path to use to get a single issue. -> This `GET` path can be found in the [public API documentation](https://docs.gitlab.com/ee/api/issues.html#single-issue). +> This `GET` path can be found in the [public API documentation](../../../api/issues.md#single-issue). By defining the `api_post_path` method, we allow the [`ApiFabricator`](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/qa/qa/resource/api_fabricator.rb) module to know which path to use to create a new issue in a specific project. -> This `POST` path can be found in the [public API documentation](https://docs.gitlab.com/ee/api/issues.html#new-issue). +> This `POST` path can be found in the [public API documentation](../../../api/issues.md#new-issue). By defining the `api_post_body` method, we allow the [`ApiFabricator.api_post`](https://gitlab.com/gitlab-org/gitlab-ee/blob/a9177ca1812bac57e2b2fa4560e1d5dd8ffac38b/qa/qa/resource/api_fabricator.rb#L68) method to know which data to send when making the `POST` request. -> Notice that we pass both `labels` and `title` attributes in the `api_post_body`, where `labels` receives an array of labels, and [`title` is required](https://docs.gitlab.com/ee/api/issues.html#new-issue). Also, notice that we keep them alphabetically organized. +> Notice that we pass both `labels` and `title` attributes in the `api_post_body`, where `labels` receives an array of labels, and [`title` is required](../../../api/issues.md#new-issue). Also, notice that we keep them alphabetically organized. **Label resource** @@ -441,7 +441,7 @@ By defining the `api_post_path` method, we allow for the [`ApiFabricator `](http By defining the `api_post_body` method, we we allow for the [`ApiFabricator.api_post`](https://gitlab.com/gitlab-org/gitlab-ee/blob/a9177ca1812bac57e2b2fa4560e1d5dd8ffac38b/qa/qa/resource/api_fabricator.rb#L68) method to know which data to send when making the `POST` request. -> Notice that we pass both `color` and `name` attributes in the `api_post_body` since [those are required](https://docs.gitlab.com/ee/api/labels.html#create-a-new-label). Also, notice that we keep them alphabetically organized. +> Notice that we pass both `color` and `name` attributes in the `api_post_body` since [those are required](../../../api/labels.md#create-a-new-label). Also, notice that we keep them alphabetically organized. ### 8. Page Objects diff --git a/doc/install/google_cloud_platform/index.md b/doc/install/google_cloud_platform/index.md index 77c61acbfd4..2070187255a 100644 --- a/doc/install/google_cloud_platform/index.md +++ b/doc/install/google_cloud_platform/index.md @@ -128,9 +128,9 @@ GitLab can be configured to authenticate with other OAuth providers, LDAP, SAML, Kerberos, etc. Here are some documents you might be interested in reading: - [Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/) -- [Integration documentation](https://docs.gitlab.com/ce/integration/) -- [GitLab Pages configuration](https://docs.gitlab.com/ce/administration/pages/index.html) -- [GitLab Container Registry configuration](https://docs.gitlab.com/ce/administration/container_registry.html) +- [Integration documentation](../../integration/README.md) +- [GitLab Pages configuration](../../administration/pages/index.md) +- [GitLab Container Registry configuration](../../administration/container_registry.md) [freetrial]: https://console.cloud.google.com/freetrial "GCP free trial" [ip]: https://cloud.google.com/compute/docs/configure-instance-ip-addresses#promote_ephemeral_ip "Configuring an Instance's IP Addresses" diff --git a/doc/raketasks/README.md b/doc/raketasks/README.md index 0729875daf8..b28f21f83a9 100644 --- a/doc/raketasks/README.md +++ b/doc/raketasks/README.md @@ -13,6 +13,6 @@ comments: false - [User management](user_management.md) - [Webhooks](web_hooks.md) - [Import](import.md) of git repositories in bulk -- [Rebuild authorized_keys file](http://docs.gitlab.com/ce/raketasks/maintenance.html#rebuild-authorized_keys-file) task for administrators +- [Rebuild authorized_keys file](../administration/raketasks/maintenance.md#rebuild-authorized_keys-file) task for administrators - [Migrate Uploads](../administration/raketasks/uploads/migrate.md) - [Sanitize Uploads](../administration/raketasks/uploads/sanitize.md) diff --git a/doc/topics/application_development_platform/index.md b/doc/topics/application_development_platform/index.md index 8742606479d..2ea561eb943 100644 --- a/doc/topics/application_development_platform/index.md +++ b/doc/topics/application_development_platform/index.md @@ -9,10 +9,10 @@ The GitLab Application Development Platform aims to: - Reduce and even eliminate the time it takes for an Operations team to provide a full environment for software developers. -- Get developers up and running fast so they can focus on writing +- Get developers up and running fast so they can focus on writing great applications with a robust development feature set. -- Provide best-of-breed security features so that applications developed - with GitLab are not affected by vulnerabilities that may lead to security +- Provide best-of-breed security features so that applications developed + with GitLab are not affected by vulnerabilities that may lead to security problems and unintended use. It is comprised of the following high-level elements: @@ -35,28 +35,28 @@ with various cloud providers. ### Build, test, deploy In order to provide modern DevOps workflows, our Application Development Platform will rely on -[Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) to provide those workflows. Auto DevOps works with -any Kubernetes cluster; you're not limited to running on GitLab's infrastructure. Additionally, Auto DevOps offers -an incremental consumption path. Because it is [composable](https://docs.gitlab.com/ee/topics/autodevops/#using-components-of-auto-devops), +[Auto DevOps](../autodevops/index.md) to provide those workflows. Auto DevOps works with +any Kubernetes cluster; you're not limited to running on GitLab's infrastructure. Additionally, Auto DevOps offers +an incremental consumption path. Because it is [composable](../autodevops/index.md#using-components-of-auto-devops), you can use as much or as little of the default pipeline as you'd like, and deeply customize without having to integrate a completely different platform. ### Security -The Application Development Platform helps you ensure that the applications you create are not affected by vulnerabilities +The Application Development Platform helps you ensure that the applications you create are not affected by vulnerabilities that may lead to security problems and unintended use. This can be achieved by making use of the embedded security features of Auto DevOps, -which inform security teams and developers if there is something to consider changing in their apps +which inform security teams and developers if there is something to consider changing in their apps before it is too late to create a preventative fix. The following features are included: -- [Auto SAST (Static Application Security Testing)](https://docs.gitlab.com/ee/topics/autodevops/#auto-sast-ultimate) -- [Auto Dependency Scanning](https://docs.gitlab.com/ee/topics/autodevops/#auto-dependency-scanning-ultimate) -- [Auto Container Scanning](https://docs.gitlab.com/ee/topics/autodevops/#auto-container-scanning-ultimate) -- [Auto DAST (Dynamic Application Security Testing)](https://docs.gitlab.com/ee/topics/autodevops/#auto-dast-ultimate) +- [Auto SAST (Static Application Security Testing)](../autodevops/index.md#auto-sast-ultimate) +- [Auto Dependency Scanning](../autodevops/index.md#auto-dependency-scanning-ultimate) +- [Auto Container Scanning](../autodevops/index.md#auto-container-scanning-ultimate) +- [Auto DAST (Dynamic Application Security Testing)](../autodevops/index.md#auto-dast-ultimate) ### Observability Performance is a critical aspect of the user experience, and ensuring your application is responsive and available is everyone's -responsibility. The Application Development Platform integrates key performance analytics and feedback +responsibility. The Application Development Platform integrates key performance analytics and feedback into GitLab, automatically. The following features are included: -- [Auto Monitoring](https://docs.gitlab.com/ee/topics/autodevops/#auto-monitoring) -- [In-app Kubernetes Pod Logs](https://docs.gitlab.com/ee/user/project/clusters/kubernetes_pod_logs.html) \ No newline at end of file +- [Auto Monitoring](../autodevops/index.md#auto-monitoring) +- [In-app Kubernetes Pod Logs](../../user/project/clusters/kubernetes_pod_logs.md) diff --git a/doc/university/README.md b/doc/university/README.md index 9d861460618..f696db2df20 100644 --- a/doc/university/README.md +++ b/doc/university/README.md @@ -73,7 +73,7 @@ The GitLab University curriculum is composed of GitLab videos, screencasts, pres - Being part of our Great Community and Contributing to GitLab 1. [Getting Started with the GitLab Development Kit (GDK)](https://about.gitlab.com/2016/06/08/getting-started-with-gitlab-development-kit/) 1. [Contributing Technical Articles to the GitLab Blog](https://about.gitlab.com/2016/01/26/call-for-writers/) -1. [GitLab Training Workshops](https://docs.gitlab.com/ce/university/training/end-user/) +1. [GitLab Training Workshops](training/end-user/README.md) 1. [GitLab Professional Services](https://about.gitlab.com/services/) ### 1.8 GitLab Training Material diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md index 04a9d9568ca..30940b65454 100644 --- a/doc/user/project/integrations/webhooks.md +++ b/doc/user/project/integrations/webhooks.md @@ -24,7 +24,7 @@ to the webhook URL. In most cases, you'll need to set up your own [webhook receiver](#example-webhook-receiver) to receive information from GitLab, and send it to another app, according to your needs. -We already have a [built-in receiver](https://docs.gitlab.com/ce/project_services/slack.html) +We already have a [built-in receiver](slack.md) for sending [Slack](https://api.slack.com/incoming-webhooks) notifications _per project_. ## Overview diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md index 91dbf0d848e..1eb835d4606 100644 --- a/doc/user/project/issues/managing_issues.md +++ b/doc/user/project/issues/managing_issues.md @@ -115,7 +115,7 @@ The "Move issue" button is at the bottom of the right-sidebar when viewing the i If you have advanced technical skills you can also bulk move all the issues from one project to another in the rails console. The below script will move all the issues from one project to another that are not in status **closed**. -To access rails console run `sudo gitlab-rails console` on the GitLab server and run the below script. Please be sure to change **project**, **admin_user** and **target_project** to your values. We do also recommend [creating a backup](https://docs.gitlab.com/ee/raketasks/backup_restore.html#creating-a-backup-of-the-gitlab-system) before attempting any changes in the console. +To access rails console run `sudo gitlab-rails console` on the GitLab server and run the below script. Please be sure to change **project**, **admin_user** and **target_project** to your values. We do also recommend [creating a backup](../../../raketasks/backup_restore.md#creating-a-backup-of-the-gitlab-system) before attempting any changes in the console. ```ruby project = Project.find_by_full_path('full path of the project where issues are moved from') diff --git a/doc/user/project/pages/getting_started_part_four.md b/doc/user/project/pages/getting_started_part_four.md index 8baf41dba78..d844d4222b1 100644 --- a/doc/user/project/pages/getting_started_part_four.md +++ b/doc/user/project/pages/getting_started_part_four.md @@ -380,7 +380,7 @@ What you can do with GitLab CI is pretty much up to your creativity. Once you get used to it, you start creating awesome scripts that automate most of tasks you'd do manually in the past. Read through the -[documentation of GitLab CI](https://docs.gitlab.com/ce/ci/yaml/README.html) +[documentation of GitLab CI](../../../ci/yaml/README.md) to understand how to go even further on your scripts. - On this blog post, understand the concept of diff --git a/doc/workflow/repository_mirroring.md b/doc/workflow/repository_mirroring.md index 5a24c254ed1..92e88ea224a 100644 --- a/doc/workflow/repository_mirroring.md +++ b/doc/workflow/repository_mirroring.md @@ -286,10 +286,10 @@ project mirroring again by [Forcing an update](#forcing-an-update-core). [GitLab Starter](https://about.gitlab.com/pricing/) 10.3. Pull mirroring uses polling to detect new branches and commits added upstream, often minutes -afterwards. If you notify GitLab by [API](https://docs.gitlab.com/ee/api/projects.html#start-the-pull-mirroring-process-for-a-project-starter), +afterwards. If you notify GitLab by [API](../api/projects.md#start-the-pull-mirroring-process-for-a-project-starter), updates will be pulled immediately. -For more information, see [Start the pull mirroring process for a Project](https://docs.gitlab.com/ee/api/projects.html#start-the-pull-mirroring-process-for-a-project-starter). +For more information, see [Start the pull mirroring process for a Project](../api/projects.md#start-the-pull-mirroring-process-for-a-project-starter). ## Forcing an update **[CORE]** -- cgit v1.2.1 From 1897ec48d3ea4bea0a501e88944eeffc7e16ca70 Mon Sep 17 00:00:00 2001 From: David Palubin Date: Fri, 5 Jul 2019 16:42:51 +0000 Subject: Remove unresolved class and fixed height in discussion header --- .../javascripts/notes/components/noteable_discussion.vue | 15 +++------------ app/assets/stylesheets/pages/notes.scss | 12 +++++------- .../Remove-unresolved-class-in-discussion-header.yml | 5 +++++ 3 files changed, 13 insertions(+), 19 deletions(-) create mode 100644 changelogs/unreleased/Remove-unresolved-class-in-discussion-header.yml diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index 3fbd0a9f715..ac743d9f4b8 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -144,15 +144,6 @@ export default { return {}; }, - componentClassName() { - if (this.shouldRenderDiffs) { - if (!this.lastUpdatedAt && !this.discussion.resolved) { - return 'unresolved'; - } - } - - return ''; - }, isExpanded() { return this.discussion.expanded || this.alwaysExpanded; }, @@ -313,11 +304,11 @@ export default { -
+ - - {{ __('Read more') }} - -

diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index a12029d2419..e75c1379dfb 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -287,8 +287,8 @@ list-style: none; padding: 0 1px; - a:not(.help-link), - button:not(.btn), + a, + button:not(.dropdown-toggle,.ci-action-icon-container), .menu-item { @include dropdown-link; } diff --git a/spec/frontend/confidential_merge_request/components/__snapshots__/project_form_group_spec.js.snap b/spec/frontend/confidential_merge_request/components/__snapshots__/project_form_group_spec.js.snap index ba0ee8dfd59..fd307ce5ab3 100644 --- a/spec/frontend/confidential_merge_request/components/__snapshots__/project_form_group_spec.js.snap +++ b/spec/frontend/confidential_merge_request/components/__snapshots__/project_form_group_spec.js.snap @@ -28,23 +28,6 @@ exports[`Confidential merge request project form group component renders empty s and set the forks visiblity to private. - - - - Read more - - -