diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-06 15:09:36 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-06 15:09:36 +0300 |
commit | 4279f24a19836d3e74e4aae8bea7acc2dd8222cc (patch) | |
tree | 76e4b3cf4d6bd85ff50e40bf011e7f9bc350441a /app | |
parent | 51c20446a0dcf2f5f4a0254230876bd472a254e7 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
21 files changed, 252 insertions, 74 deletions
diff --git a/app/assets/javascripts/ide/components/jobs/detail.vue b/app/assets/javascripts/ide/components/jobs/detail.vue index 504391ffdc7..975d54c7a4e 100644 --- a/app/assets/javascripts/ide/components/jobs/detail.vue +++ b/app/assets/javascripts/ide/components/jobs/detail.vue @@ -79,7 +79,7 @@ export default { <icon name="chevron-left" /> {{ __('View jobs') }} </button> </header> - <div class="top-bar d-flex border-left-0"> + <div class="top-bar d-flex border-left-0 mr-3"> <job-description :job="detailJob" /> <div class="controllers ml-auto"> <a @@ -97,7 +97,7 @@ export default { <scroll-button :disabled="isScrolledToBottom" direction="down" @click="scrollDown" /> </div> </div> - <pre ref="buildTrace" class="build-trace mb-0 h-100" @scroll="scrollBuildLog"> + <pre ref="buildTrace" class="build-trace mb-0 h-100 mr-3" @scroll="scrollBuildLog"> <code v-show="!detailJob.isLoading" class="bash" diff --git a/app/assets/javascripts/registry/explorer/index.js b/app/assets/javascripts/registry/explorer/index.js index 9269aa074f8..2bba3ee4ff9 100644 --- a/app/assets/javascripts/registry/explorer/index.js +++ b/app/assets/javascripts/registry/explorer/index.js @@ -19,7 +19,7 @@ export default () => { const { endpoint } = el.dataset; const store = createStore(); - const router = createRouter(endpoint, store); + const router = createRouter(endpoint); store.dispatch('setInitialState', el.dataset); const attachMainComponent = () => diff --git a/app/assets/javascripts/registry/explorer/pages/details.vue b/app/assets/javascripts/registry/explorer/pages/details.vue index 1d4dcd9a7a2..df29ee44419 100644 --- a/app/assets/javascripts/registry/explorer/pages/details.vue +++ b/app/assets/javascripts/registry/explorer/pages/details.vue @@ -157,6 +157,9 @@ export default { return config; }, }, + mounted() { + this.requestTagsList({ params: this.$route.params.id }); + }, methods: { ...mapActions(['requestTagsList', 'requestDeleteTag', 'requestDeleteTags']), setModalDescription(itemIndex = -1) { diff --git a/app/assets/javascripts/registry/explorer/pages/list.vue b/app/assets/javascripts/registry/explorer/pages/list.vue index 8923c305b2d..e932544feb8 100644 --- a/app/assets/javascripts/registry/explorer/pages/list.vue +++ b/app/assets/javascripts/registry/explorer/pages/list.vue @@ -103,8 +103,16 @@ export default { : DELETE_IMAGE_ERROR_MESSAGE; }, }, + mounted() { + this.loadImageList(this.$route.name); + }, methods: { ...mapActions(['requestImagesList', 'requestDeleteImage']), + loadImageList(fromName) { + if (!fromName || !this.images?.length) { + this.requestImagesList(); + } + }, deleteImage(item) { this.track('click_button'); this.itemToDelete = item; diff --git a/app/assets/javascripts/registry/explorer/router.js b/app/assets/javascripts/registry/explorer/router.js index 28df3177df4..478eaca1a68 100644 --- a/app/assets/javascripts/registry/explorer/router.js +++ b/app/assets/javascripts/registry/explorer/router.js @@ -7,7 +7,7 @@ import { decodeAndParse } from './utils'; Vue.use(VueRouter); -export default function createRouter(base, store) { +export default function createRouter(base) { const router = new VueRouter({ base, mode: 'history', @@ -20,12 +20,6 @@ export default function createRouter(base, store) { nameGenerator: () => s__('ContainerRegistry|Container Registry'), root: true, }, - beforeEnter: (to, from, next) => { - if (!from.name || !store.state.images?.length) { - store.dispatch('requestImagesList'); - } - next(); - }, }, { name: 'details', @@ -34,10 +28,6 @@ export default function createRouter(base, store) { meta: { nameGenerator: route => decodeAndParse(route.params.id).name, }, - beforeEnter: (to, from, next) => { - store.dispatch('requestTagsList', { params: to.params.id }); - next(); - }, }, ], }); diff --git a/app/assets/javascripts/registry/explorer/stores/index.js b/app/assets/javascripts/registry/explorer/stores/index.js index b3ff2e6e002..153032e37d3 100644 --- a/app/assets/javascripts/registry/explorer/stores/index.js +++ b/app/assets/javascripts/registry/explorer/stores/index.js @@ -15,4 +15,5 @@ export const createStore = () => mutations, }); +// Deprecated and to be removed export default createStore(); diff --git a/app/assets/javascripts/snippets/components/snippet_header.vue b/app/assets/javascripts/snippets/components/snippet_header.vue index 615983ed3cf..46ab04c9b19 100644 --- a/app/assets/javascripts/snippets/components/snippet_header.vue +++ b/app/assets/javascripts/snippets/components/snippet_header.vue @@ -10,6 +10,7 @@ import { GlDropdown, GlDropdownItem, GlButton, + GlTooltipDirective, } from '@gitlab/ui'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; @@ -30,6 +31,9 @@ export default { TimeAgoTooltip, GlButton, }, + directives: { + GlTooltip: GlTooltipDirective, + }, apollo: { canCreateSnippet: { query() { @@ -67,6 +71,10 @@ export default { condition: this.snippet.userPermissions.updateSnippet, text: __('Edit'), href: this.editLink, + disabled: this.snippet.blob.binary, + title: this.snippet.blob.binary + ? __('Snippets with non-text files can only be edited via Git.') + : undefined, }, { condition: this.snippet.userPermissions.adminSnippet, @@ -186,18 +194,24 @@ export default { <div class="detail-page-header-actions"> <div class="d-none d-sm-flex"> <template v-for="(action, index) in personalSnippetActions"> - <gl-button + <div v-if="action.condition" :key="index" - :disabled="action.disabled" - :variant="action.variant" - :category="action.category" - :class="action.cssClass" - :href="action.href" - @click="action.click ? action.click() : undefined" + v-gl-tooltip + :title="action.title" + class="d-inline-block" > - {{ action.text }} - </gl-button> + <gl-button + :disabled="action.disabled" + :variant="action.variant" + :category="action.category" + :class="action.cssClass" + :href="action.href" + @click="action.click ? action.click() : undefined" + > + {{ action.text }} + </gl-button> + </div> </template> </div> <div class="d-block d-sm-none dropdown"> @@ -205,6 +219,8 @@ export default { <gl-dropdown-item v-for="(action, index) in personalSnippetActions" :key="index" + :disabled="action.disabled" + :title="action.title" :href="action.href" @click="action.click ? action.click() : undefined" >{{ action.text }}</gl-dropdown-item diff --git a/app/assets/stylesheets/page_bundles/_ide_mixins.scss b/app/assets/stylesheets/page_bundles/_ide_mixins.scss index 9465dd5bed6..48b8a7230b1 100644 --- a/app/assets/stylesheets/page_bundles/_ide_mixins.scss +++ b/app/assets/stylesheets/page_bundles/_ide_mixins.scss @@ -9,7 +9,6 @@ top: 0; font-size: 12px; border-top-right-radius: $border-radius-default; - margin-left: -$gl-padding; .controllers { @include build-controllers(15px, center, false, 0, inline, 0); diff --git a/app/assets/stylesheets/page_bundles/ide.scss b/app/assets/stylesheets/page_bundles/ide.scss index c5869880af9..d0660422f7e 100644 --- a/app/assets/stylesheets/page_bundles/ide.scss +++ b/app/assets/stylesheets/page_bundles/ide.scss @@ -890,11 +890,15 @@ $ide-commit-header-height: 48px; .multi-file-commit-panel-inner { width: 350px; - padding: $grid-size $gl-padding; + padding: $grid-size 0; background-color: $white; border-left: 1px solid $white-dark; } + .ide-right-sidebar-jobs-detail { + padding-bottom: 0; + } + .ide-right-sidebar-clientside { padding: 0; } @@ -915,15 +919,12 @@ $ide-commit-header-height: 48px; margin: 0; } } - - .build-trace { - margin-left: -$gl-padding; - } } .ide-pipeline-list { flex: 1; overflow: auto; + padding: 0 $gl-padding; } .ide-pipeline-header { @@ -966,6 +967,7 @@ $ide-commit-header-height: 48px; .ide-job-header { min-height: 60px; + padding: 0 $gl-padding; } .ide-nav-form { diff --git a/app/assets/stylesheets/page_bundles/themes/_dark.scss b/app/assets/stylesheets/page_bundles/themes/_dark.scss index 66b4b745532..634f18ee1bd 100644 --- a/app/assets/stylesheets/page_bundles/themes/_dark.scss +++ b/app/assets/stylesheets/page_bundles/themes/_dark.scss @@ -33,7 +33,7 @@ $diff-insert: rgba(155, 185, 85, 0.2); $diff-remove: rgba(255, 0, 0, 0.2); - a { + a:not(.btn) { color: $link-color; } @@ -57,27 +57,46 @@ textarea, .md-area.is-focused, .ide-entry-dropdown-toggle, - .nav-links:not(.quick-links) li:not(.md-header-toolbar) a:hover, .dropdown-menu li button, .ide-merge-request-project-path, .dropdown-menu-selectable li a.is-active, .dropdown-menu-inner-title, - .dropdown-menu-inner-content { + .dropdown-menu-inner-content, + .nav-links:not(.quick-links) li:not(.md-header-toolbar) a, + .nav-links:not(.quick-links) li:not(.md-header-toolbar) a:hover, + .nav-links:not(.quick-links) li:not(.md-header-toolbar) a.active .badge.badge-pill, + .nav-links:not(.quick-links) li:not(.md-header-toolbar) a:hover .badge.badge-pill, + .badge.badge-pill, + .ide-navigator-button, + .bs-callout, + .ide-navigator-btn, + .ide-pipeline .top-bar, + .ide-pipeline .top-bar .controllers .controllers-buttons { color: $text-color; } + .drag-handle:hover, + .card-header .badge.badge-pill { + background-color: $dropdown-hover-background; + } + .modal-body { color: $gl-text-color; } .dropdown-menu-toggle svg, .dropdown-menu-toggle svg:hover, - .ide-tree-header svg, + .ide-tree-header:not(.ide-pipeline-header) svg, .file-row .file-row-icon svg, - .file-row:hover .file-row-icon svg { + .file-row:hover .file-row-icon svg, + .controllers-buttons svg { fill: $text-color; } + .ide-pipeline svg { + --svg-status-bg: transparent; + } + .multi-file-tab-close:hover { background-color: $input-border; } @@ -118,7 +137,12 @@ .ide-commit-editor-header, .ide-file-templates, .ide-entry-dropdown-toggle, - .ide-staged-action-btn { + .ide-staged-action-btn, + .badge.badge-pill, + .card-header, + .bs-callout, + .ide-pipeline .top-bar, + .ide-terminal .top-bar { background-color: $background; } @@ -126,6 +150,18 @@ background-color: inherit; } + .bs-callout { + border-color: $dropdown-background; + + code { + background-color: $dropdown-background; + } + } + + .nav-links:not(.quick-links) li:not(.md-header-toolbar) a:hover { + border-color: $dropdown-hover-background; + } + .ide-sidebar-link:hover, .multi-file-tabs li { background-color: $background-hover; @@ -144,7 +180,10 @@ .ide-sidebar-link.active::after, .ide-right-sidebar .multi-file-commit-panel-inner, .common-note-form .md-area, - .ide-commit-message-field { + .ide-commit-message-field, + .card, + .multi-file-commit-panel-success-message, + .ide-preview-header { background-color: $highlight-background; } @@ -163,7 +202,12 @@ .multi-file-tabs li, .ide-status-bar, .ide-commit-editor-header, - .ide-file-templates { + .ide-file-templates, + .card, + .card-header, + .ide-job-item:not(:last-child), + .ide-terminal .top-bar, + .ide-pipeline .top-bar { border-color: $border-color; } @@ -179,7 +223,9 @@ .multi-file-commit-form > form, .multi-file-commit-form hr, .ide-commit-list-container.is-first, - .multi-file-commit-form .nav-links:not(.quick-links) { + .multi-file-commit-form .nav-links:not(.quick-links), + .ide-pipeline-list .nav-links:not(.quick-links), + .ide-preview-header { border-color: $background; } @@ -201,7 +247,8 @@ } } - .nav-links li.active a { + .nav-links li.active a, + .nav-links li a.active { border-color: $highlight-accent; color: $text-color; } @@ -223,7 +270,7 @@ input[type='search'], .filtered-search-box { border-color: $input-border; - background-color: $input-background; + background: $input-background !important; } input[type='text'], @@ -252,16 +299,16 @@ background: $gray-800; } - .btn:not(.btn-link):hover { + .btn:not(.btn-link):not([disabled]):hover { border-width: 2px; padding: 5px 9px; } - .btn.btn-sm:hover { + .btn:not([disabled]).btn-sm:hover { padding: 3px 9px; } - .btn.btn-block:hover { + .btn:not([disabled]).btn-block:hover { padding: 5px 0; } diff --git a/app/graphql/mutations/alert_management/base.rb b/app/graphql/mutations/alert_management/base.rb new file mode 100644 index 00000000000..eb0d2304ba3 --- /dev/null +++ b/app/graphql/mutations/alert_management/base.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module Mutations + module AlertManagement + class Base < BaseMutation + include Mutations::ResolvesProject + + argument :project_path, GraphQL::ID_TYPE, + required: true, + description: "The project the alert to mutate is in" + + argument :iid, GraphQL::STRING_TYPE, + required: true, + description: "The iid of the alert to mutate" + + field :alert, + Types::AlertManagement::AlertType, + null: true, + description: "The alert after mutation" + + authorize :update_alert_management_alerts + + private + + def find_object(project_path:, iid:) + project = resolve_project(full_path: project_path) + + return unless project + + resolver = Resolvers::AlertManagementAlertResolver.single.new(object: project, context: context, field: nil) + resolver.resolve(iid: iid) + end + end + end +end diff --git a/app/graphql/mutations/alert_management/update_alert_status.rb b/app/graphql/mutations/alert_management/update_alert_status.rb new file mode 100644 index 00000000000..ac6a5412956 --- /dev/null +++ b/app/graphql/mutations/alert_management/update_alert_status.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Mutations + module AlertManagement + class UpdateAlertStatus < Base + graphql_name 'UpdateAlertStatus' + + argument :status, Types::AlertManagement::StatusEnum, + required: true, + description: 'The status to set the alert' + + def resolve(args) + alert = authorized_find!(project_path: args[:project_path], iid: args[:iid]) + + result = update_status(alert, args[:status]) + + prepare_response(result) + end + + private + + def update_status(alert, status) + ::AlertManagement::UpdateAlertStatusService.new(alert, status).execute + end + + def prepare_response(result) + { + alert: result.payload[:alert], + errors: result.error? ? [result.message] : [] + } + end + end + end +end diff --git a/app/graphql/types/alert_management/alert_type.rb b/app/graphql/types/alert_management/alert_type.rb index 5055a9caef2..69fc2718f1e 100644 --- a/app/graphql/types/alert_management/alert_type.rb +++ b/app/graphql/types/alert_management/alert_type.rb @@ -18,6 +18,11 @@ module Types null: true, description: 'Title of the alert' + field :description, + GraphQL::STRING_TYPE, + null: true, + description: 'Description of the alert' + field :severity, AlertManagement::SeverityEnum, null: true, @@ -38,6 +43,11 @@ module Types null: true, description: 'Monitoring tool the alert came from' + field :hosts, + [GraphQL::STRING_TYPE], + null: true, + description: 'List of hosts the alert came from' + field :started_at, Types::TimeType, null: true, @@ -53,6 +63,21 @@ module Types null: true, description: 'Number of events of this alert', method: :events + + field :details, + GraphQL::Types::JSON, + null: true, + description: 'Alert details' + + field :created_at, + Types::TimeType, + null: true, + description: 'Timestamp the alert was created' + + field :updated_at, + Types::TimeType, + null: true, + description: 'Timestamp the alert was last updated' end end end diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb index c9b8f235ae1..b18a3968a03 100644 --- a/app/graphql/types/mutation_type.rb +++ b/app/graphql/types/mutation_type.rb @@ -7,6 +7,7 @@ module Types graphql_name 'Mutation' mount_mutation Mutations::Admin::SidekiqQueues::DeleteJobs + mount_mutation Mutations::AlertManagement::UpdateAlertStatus mount_mutation Mutations::AwardEmojis::Add mount_mutation Mutations::AwardEmojis::Remove mount_mutation Mutations::AwardEmojis::Toggle diff --git a/app/models/alert_management/alert.rb b/app/models/alert_management/alert.rb index 810ec8f5583..1263423e1c4 100644 --- a/app/models/alert_management/alert.rb +++ b/app/models/alert_management/alert.rb @@ -53,6 +53,12 @@ module AlertManagement end end + def details + details_payload = payload.except(*attributes.keys) + + Gitlab::Utils::InlineHash.merge_keys(details_payload) + end + private def hosts_length diff --git a/app/models/ci/persistent_ref.rb b/app/models/ci/persistent_ref.rb index 76139f5d676..91163c85a9e 100644 --- a/app/models/ci/persistent_ref.rb +++ b/app/models/ci/persistent_ref.rb @@ -14,16 +14,12 @@ module Ci delegate :ref_exists?, :create_ref, :delete_refs, to: :repository def exist? - return unless enabled? - ref_exists?(path) rescue false end def create - return unless enabled? - create_ref(sha, path) rescue => e Gitlab::ErrorTracking @@ -31,8 +27,6 @@ module Ci end def delete - return unless enabled? - delete_refs(path) rescue Gitlab::Git::Repository::NoRepository # no-op @@ -44,11 +38,5 @@ module Ci def path "refs/#{Repository::REF_PIPELINES}/#{pipeline.id}" end - - private - - def enabled? - Feature.enabled?(:depend_on_persistent_pipeline_ref, project, default_enabled: true) - end end end diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index 4e0bcfe0985..6aa3d791a0f 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -240,6 +240,7 @@ class ProjectPolicy < BasePolicy enable :read_prometheus enable :read_metrics_dashboard_annotation enable :read_alert_management_alerts + enable :update_alert_management_alerts enable :metrics_dashboard end diff --git a/app/presenters/ci/build_runner_presenter.rb b/app/presenters/ci/build_runner_presenter.rb index a409a3d7160..61fcbaf691a 100644 --- a/app/presenters/ci/build_runner_presenter.rb +++ b/app/presenters/ci/build_runner_presenter.rb @@ -34,7 +34,6 @@ module Ci def refspecs specs = [] - specs << refspec_for_pipeline_ref if should_expose_merge_request_ref? specs << refspec_for_persistent_ref if persistent_ref_exist? if git_depth > 0 @@ -50,19 +49,6 @@ module Ci private - # We will stop exposing merge request refs when we fully depend on persistent refs - # (i.e. remove `refspec_for_pipeline_ref` when we remove `depend_on_persistent_pipeline_ref` feature flag.) - # `ci_force_exposing_merge_request_refs` is an extra feature flag that allows us to - # forcibly expose MR refs even if the `depend_on_persistent_pipeline_ref` feature flag enabled. - # This is useful when we see an unexpected behaviors/reports from users. - # See https://gitlab.com/gitlab-org/gitlab/issues/35140. - def should_expose_merge_request_ref? - return false unless merge_request_ref? - return true if Feature.enabled?(:ci_force_exposing_merge_request_refs, project) - - Feature.disabled?(:depend_on_persistent_pipeline_ref, project, default_enabled: true) - end - def create_archive(artifacts) return unless artifacts[:untracked] || artifacts[:paths] @@ -100,10 +86,6 @@ module Ci "+#{Gitlab::Git::TAG_REF_PREFIX}#{ref}:#{RUNNER_REMOTE_TAG_PREFIX}#{ref}" end - def refspec_for_pipeline_ref - "+#{ref}:#{ref}" - end - def refspec_for_persistent_ref "+#{persistent_ref_path}:#{persistent_ref_path}" end diff --git a/app/services/alert_management/update_alert_status_service.rb b/app/services/alert_management/update_alert_status_service.rb new file mode 100644 index 00000000000..73ee654874f --- /dev/null +++ b/app/services/alert_management/update_alert_status_service.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module AlertManagement + class UpdateAlertStatusService + def initialize(alert, status) + @alert = alert + @status = status + end + + def execute + return error('Invalid status') unless AlertManagement::Alert.statuses.key?(status.to_s) + + alert.status = status + + if alert.save + success + else + error(alert.errors.full_messages.to_sentence) + end + end + + private + + attr_reader :alert, :status + + def success + ServiceResponse.success(payload: { alert: alert }) + end + + def error(message) + ServiceResponse.error(payload: { alert: alert }, message: message) + end + end +end diff --git a/app/services/spam/spam_action_service.rb b/app/services/spam/spam_action_service.rb index 0c938ba00c2..f0a4aff4443 100644 --- a/app/services/spam/spam_action_service.rb +++ b/app/services/spam/spam_action_service.rb @@ -28,6 +28,7 @@ module Spam # update the spam log accordingly. SpamLog.verify_recaptcha!(user_id: user.id, id: spam_log_id) else + return if allowlisted?(user) return unless request return unless check_for_spam? @@ -39,6 +40,10 @@ module Spam private + def allowlisted?(user) + user.respond_to?(:gitlab_employee) && user.gitlab_employee? + end + def perform_spam_service_check(api) # since we can check for spam, and recaptcha is not verified, # ask the SpamVerdictService what to do with the target. diff --git a/app/views/projects/alert_management/details.html.haml b/app/views/projects/alert_management/details.html.haml index 1208c541a9d..766dbf7c128 100644 --- a/app/views/projects/alert_management/details.html.haml +++ b/app/views/projects/alert_management/details.html.haml @@ -1,3 +1,4 @@ -- page_title _('Alert Details') +- add_to_breadcrumbs s_('AlertManagement|Alerts'), project_alert_management_index_path(@project) +- page_title s_('AlertManagement|Alert detail') #js-alert_details |