diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-30 09:07:58 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-30 09:07:58 +0000 |
commit | 45b4df3e57c949c88107840c44ccbfaf2eabdf26 (patch) | |
tree | f73c1533a75b03d2ceb1361644e0d8ab97568a8f /app | |
parent | 7421e6f9f2b5889b05738af7eba568af6ae3fcbc (diff) | |
download | gitlab-ce-45b4df3e57c949c88107840c44ccbfaf2eabdf26.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
12 files changed, 120 insertions, 45 deletions
diff --git a/app/assets/javascripts/environments/components/confirm_rollback_modal.vue b/app/assets/javascripts/environments/components/confirm_rollback_modal.vue index 70b5c6b0094..5c03c008faf 100644 --- a/app/assets/javascripts/environments/components/confirm_rollback_modal.vue +++ b/app/assets/javascripts/environments/components/confirm_rollback_modal.vue @@ -3,7 +3,7 @@ * Render modal to confirm rollback/redeploy. */ -import _ from 'underscore'; +import { escape as esc } from 'lodash'; import { GlModal } from '@gitlab/ui'; import { s__, sprintf } from '~/locale'; @@ -30,7 +30,7 @@ export default { : s__('Environments|Rollback environment %{name}?'); return sprintf(title, { - name: _.escape(this.environment.name), + name: esc(this.environment.name), }); }, @@ -50,10 +50,10 @@ export default { }, modalText() { - const linkStart = `<a class="commit-sha mr-0" href="${_.escape(this.commitUrl)}">`; - const commitId = _.escape(this.commitShortSha); + const linkStart = `<a class="commit-sha mr-0" href="${esc(this.commitUrl)}">`; + const commitId = esc(this.commitShortSha); const linkEnd = '</a>'; - const name = _.escape(this.name); + const name = esc(this.name); const body = this.environment.isLastDeployment ? s__( 'Environments|This action will relaunch the job for commit %{linkStart}%{commitId}%{linkEnd}, putting the environment in a previous version. Are you sure you want to continue?', diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue index ec5b1092c14..305d860a692 100644 --- a/app/assets/javascripts/environments/components/environment_item.vue +++ b/app/assets/javascripts/environments/components/environment_item.vue @@ -1,6 +1,6 @@ <script> /* eslint-disable @gitlab/vue-require-i18n-strings */ -import _ from 'underscore'; +import { isEmpty } from 'lodash'; import { GlTooltipDirective } from '@gitlab/ui'; import { __, sprintf } from '~/locale'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; @@ -79,7 +79,7 @@ export default { * @returns {Boolean} */ hasLastDeploymentKey() { - if (this.model && this.model.last_deployment && !_.isEmpty(this.model.last_deployment)) { + if (this.model && this.model.last_deployment && !isEmpty(this.model.last_deployment)) { return true; } return false; @@ -390,8 +390,8 @@ export default { deploymentHasUser() { return ( this.model && - !_.isEmpty(this.model.last_deployment) && - !_.isEmpty(this.model.last_deployment.user) + !isEmpty(this.model.last_deployment) && + !isEmpty(this.model.last_deployment.user) ); }, @@ -404,8 +404,8 @@ export default { deploymentUser() { if ( this.model && - !_.isEmpty(this.model.last_deployment) && - !_.isEmpty(this.model.last_deployment.user) + !isEmpty(this.model.last_deployment) && + !isEmpty(this.model.last_deployment.user) ) { return this.model.last_deployment.user; } @@ -431,8 +431,8 @@ export default { shouldRenderBuildName() { return ( !this.isFolder && - !_.isEmpty(this.model.last_deployment) && - !_.isEmpty(this.model.last_deployment.deployable) + !isEmpty(this.model.last_deployment) && + !isEmpty(this.model.last_deployment.deployable) ); }, @@ -473,7 +473,7 @@ export default { shouldRenderDeploymentID() { return ( !this.isFolder && - !_.isEmpty(this.model.last_deployment) && + !isEmpty(this.model.last_deployment) && this.model.last_deployment.iid !== undefined ); }, diff --git a/app/assets/javascripts/environments/components/environments_table.vue b/app/assets/javascripts/environments/components/environments_table.vue index 3f316643784..01a00e03814 100644 --- a/app/assets/javascripts/environments/components/environments_table.vue +++ b/app/assets/javascripts/environments/components/environments_table.vue @@ -3,7 +3,7 @@ * Render environments table. */ import { GlLoadingIcon } from '@gitlab/ui'; -import _ from 'underscore'; +import { flow, reverse, sortBy } from 'lodash/fp'; import environmentTableMixin from 'ee_else_ce/environments/mixins/environments_table_mixin'; import { s__ } from '~/locale'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; @@ -102,13 +102,13 @@ export default { * 4. Reverse (last deployment descending, name ascending), * 5. Put folders first. */ - return _.chain(environments) - .sortBy(env => (env.isFolder ? env.folderName : env.name)) - .reverse() - .sortBy(env => (env.last_deployment ? env.last_deployment.created_at : '0000')) - .reverse() - .sortBy(env => (env.isFolder ? -1 : 1)) - .value(); + return flow( + sortBy(env => (env.isFolder ? env.folderName : env.name)), + reverse, + sortBy(env => (env.last_deployment ? env.last_deployment.created_at : '0000')), + reverse, + sortBy(env => (env.isFolder ? -1 : 1)), + )(environments); }, }, }; diff --git a/app/assets/javascripts/environments/mixins/environments_mixin.js b/app/assets/javascripts/environments/mixins/environments_mixin.js index 4fadecdd3e9..73dc8c02485 100644 --- a/app/assets/javascripts/environments/mixins/environments_mixin.js +++ b/app/assets/javascripts/environments/mixins/environments_mixin.js @@ -1,7 +1,7 @@ /** * Common code between environmets app and folder view */ -import _ from 'underscore'; +import { isEqual, isFunction, omitBy } from 'lodash'; import Visibility from 'visibilityjs'; import EnvironmentsStore from 'ee_else_ce/environments/stores/environments_store'; import Poll from '../../lib/utils/poll'; @@ -54,7 +54,7 @@ export default { const response = this.filterNilValues(resp.config.params); const request = this.filterNilValues(this.requestData); - if (_.isEqual(response, request)) { + if (isEqual(response, request)) { this.store.storeAvailableCount(resp.data.available_count); this.store.storeStoppedCount(resp.data.stopped_count); this.store.storeEnvironments(resp.data.environments); @@ -64,7 +64,7 @@ export default { }, filterNilValues(obj) { - return _.omit(obj, value => _.isUndefined(value) || _.isNull(value)); + return omitBy(obj, value => value === undefined || value === null); }, /** @@ -109,7 +109,7 @@ export default { .then(() => this.fetchEnvironments()) .catch(err => { this.isLoading = false; - Flash(_.isFunction(errorMessage) ? errorMessage(err.response.data) : errorMessage); + Flash(isFunction(errorMessage) ? errorMessage(err.response.data) : errorMessage); }); } }, diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index d813d7b8225..a50d516f75e 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -44,7 +44,7 @@ class Projects::IssuesController < Projects::ApplicationController before_action do push_frontend_feature_flag(:vue_issuable_sidebar, project.group) - push_frontend_feature_flag(:save_issuable_health_status, project.group) + push_frontend_feature_flag(:save_issuable_health_status, project.group, default_enabled: true) end before_action only: :show do diff --git a/app/graphql/types/project_statistics_type.rb b/app/graphql/types/project_statistics_type.rb index c46410df6c0..e1546d31e89 100644 --- a/app/graphql/types/project_statistics_type.rb +++ b/app/graphql/types/project_statistics_type.rb @@ -6,20 +6,20 @@ module Types authorize :read_statistics - field :commit_count, GraphQL::INT_TYPE, null: false, + field :commit_count, GraphQL::FLOAT_TYPE, null: false, description: 'Commit count of the project' - field :storage_size, GraphQL::INT_TYPE, null: false, + field :storage_size, GraphQL::FLOAT_TYPE, null: false, description: 'Storage size of the project' - field :repository_size, GraphQL::INT_TYPE, null: false, + field :repository_size, GraphQL::FLOAT_TYPE, null: false, description: 'Repository size of the project' - field :lfs_objects_size, GraphQL::INT_TYPE, null: false, + field :lfs_objects_size, GraphQL::FLOAT_TYPE, null: false, description: 'Large File Storage (LFS) object size of the project' - field :build_artifacts_size, GraphQL::INT_TYPE, null: false, + field :build_artifacts_size, GraphQL::FLOAT_TYPE, null: false, description: 'Build artifacts size of the project' - field :packages_size, GraphQL::INT_TYPE, null: false, + field :packages_size, GraphQL::FLOAT_TYPE, null: false, description: 'Packages size of the project' - field :wiki_size, GraphQL::INT_TYPE, null: true, + field :wiki_size, GraphQL::FLOAT_TYPE, null: true, description: 'Wiki size of the project' end end diff --git a/app/graphql/types/root_storage_statistics_type.rb b/app/graphql/types/root_storage_statistics_type.rb index 3c471df072d..e2d85aebc48 100644 --- a/app/graphql/types/root_storage_statistics_type.rb +++ b/app/graphql/types/root_storage_statistics_type.rb @@ -6,11 +6,11 @@ module Types authorize :read_statistics - field :storage_size, GraphQL::INT_TYPE, null: false, description: 'The total storage in bytes' - field :repository_size, GraphQL::INT_TYPE, null: false, description: 'The Git repository size in bytes' - field :lfs_objects_size, GraphQL::INT_TYPE, null: false, description: 'The LFS objects size in bytes' - field :build_artifacts_size, GraphQL::INT_TYPE, null: false, description: 'The CI artifacts size in bytes' - field :packages_size, GraphQL::INT_TYPE, null: false, description: 'The packages size in bytes' - field :wiki_size, GraphQL::INT_TYPE, null: false, description: 'The wiki size in bytes' + field :storage_size, GraphQL::FLOAT_TYPE, null: false, description: 'The total storage in bytes' + field :repository_size, GraphQL::FLOAT_TYPE, null: false, description: 'The Git repository size in bytes' + field :lfs_objects_size, GraphQL::FLOAT_TYPE, null: false, description: 'The LFS objects size in bytes' + field :build_artifacts_size, GraphQL::FLOAT_TYPE, null: false, description: 'The CI artifacts size in bytes' + field :packages_size, GraphQL::FLOAT_TYPE, null: false, description: 'The packages size in bytes' + field :wiki_size, GraphQL::FLOAT_TYPE, null: false, description: 'The wiki size in bytes' end end diff --git a/app/models/container_registry/event.rb b/app/models/container_registry/event.rb new file mode 100644 index 00000000000..109fda675a2 --- /dev/null +++ b/app/models/container_registry/event.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +module ContainerRegistry + class Event + ALLOWED_ACTIONS = %w(push delete).freeze + PUSH_ACTION = 'push' + EVENT_TRACKING_CATEGORY = 'container_registry:notification' + + attr_reader :event + + def initialize(event) + @event = event + end + + def supported? + action.in?(ALLOWED_ACTIONS) + end + + def handle! + # no op + end + + def track! + tracked_target = target_tag? ? :tag : :repository + tracking_action = "#{action}_#{tracked_target}" + + if target_repository? && action_push? && !container_repository_exists? + tracking_action = "create_repository" + end + + ::Gitlab::Tracking.event(EVENT_TRACKING_CATEGORY, tracking_action) + end + + private + + def target_tag? + # There is no clear indication in the event structure when we delete a top-level manifest + # except existance of "tag" key + event['target'].has_key?('tag') + end + + def target_repository? + !target_tag? && event['target'].has_key?('repository') + end + + def action + event['action'] + end + + def action_push? + PUSH_ACTION == action + end + + def container_repository_exists? + return unless container_registry_path + + ContainerRepository.exists_by_path?(container_registry_path) + end + + def container_registry_path + path = event.dig('target', 'repository') + return unless path + + ContainerRegistry::Path.new(path) + end + end +end + +::ContainerRegistry::Event.prepend_if_ee('EE::ContainerRegistry::Event') diff --git a/app/models/container_repository.rb b/app/models/container_repository.rb index fcbfda8fbc2..b74c044b687 100644 --- a/app/models/container_repository.rb +++ b/app/models/container_repository.rb @@ -16,6 +16,13 @@ class ContainerRepository < ApplicationRecord where(project_id: Project.for_group_and_its_subgroups(group).with_container_registry.select(:id)) end + def self.exists_by_path?(path) + where( + project: path.repository_project, + name: path.repository_name + ).exists? + end + # rubocop: disable CodeReuse/ServiceClass def registry @registry ||= begin diff --git a/app/views/projects/issues/_nav_btns.html.haml b/app/views/projects/issues/_nav_btns.html.haml index 329efa0cdbf..d81089bee68 100644 --- a/app/views/projects/issues/_nav_btns.html.haml +++ b/app/views/projects/issues/_nav_btns.html.haml @@ -20,7 +20,6 @@ issue: { assignee_id: finder.assignee.try(:id), milestone_id: finder.milestones.first.try(:id) }), class: "btn btn-success", - title: _("New issue"), id: "new_issue_link" - if show_export_button diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index f7702499970..1f499dbd0a2 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -48,7 +48,7 @@ - if can_create_issue - if can_update_issue || can_report_spam %li.divider - %li= link_to 'New issue', new_project_issue_path(@project), title: 'New issue', id: 'new_issue_link' + %li= link_to 'New issue', new_project_issue_path(@project), id: 'new_issue_link' = render 'shared/issuable/close_reopen_button', issuable: @issue, can_update: can_update_issue, can_reopen: can_reopen_issue diff --git a/app/views/shared/empty_states/_issues.html.haml b/app/views/shared/empty_states/_issues.html.haml index 325e01bb5c8..eb5637acca0 100644 --- a/app/views/shared/empty_states/_issues.html.haml +++ b/app/views/shared/empty_states/_issues.html.haml @@ -20,7 +20,7 @@ = _("To widen your search, change or remove filters above") - if show_new_issue_link?(@project) .text-center - = link_to _("New issue"), new_project_issue_path(@project), class: "btn btn-success", title: _("New issue"), id: "new_issue_body_link" + = link_to _("New issue"), new_project_issue_path(@project), class: "btn btn-success", id: "new_issue_body_link" - elsif is_opened_state && opened_issues_count == 0 && closed_issues_count > 0 %h4.text-center = _("There are no open issues") @@ -28,7 +28,7 @@ = _("To keep this project going, create a new issue") - if show_new_issue_link?(@project) .text-center - = link_to _("New issue"), new_project_issue_path(@project), class: "btn btn-success", title: _("New issue"), id: "new_issue_body_link" + = link_to _("New issue"), new_project_issue_path(@project), class: "btn btn-success", id: "new_issue_body_link" - elsif is_closed_state && opened_issues_count > 0 && closed_issues_count == 0 %h4.text-center = _("There are no closed issues") @@ -42,7 +42,7 @@ - if project_select_button = render 'shared/new_project_item_select', path: 'issues/new', label: _('New issue'), type: :issues, with_feature_enabled: 'issues' - else - = link_to _('New issue'), button_path, class: 'btn btn-success', title: _('New issue'), id: 'new_issue_link' + = link_to _('New issue'), button_path, class: 'btn btn-success', id: 'new_issue_link' - if show_import_button = render 'projects/issues/import_csv/button', type: :text |