diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-04-16 09:09:37 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-04-16 09:09:37 +0000 |
commit | 513eff621044e77bc00cd1b4ae0cb5e0e7c2e77e (patch) | |
tree | 1de915ccc488a661129b410db83ad9f20a7c806c | |
parent | 1ab35c9208287638a097abc895738fbc0c0860e6 (diff) | |
download | gitlab-ce-513eff621044e77bc00cd1b4ae0cb5e0e7c2e77e.tar.gz |
Add latest changes from gitlab-org/gitlab@master
71 files changed, 733 insertions, 191 deletions
diff --git a/app/assets/javascripts/admin/application_settings/setup_metrics_and_profiling.js b/app/assets/javascripts/admin/application_settings/setup_metrics_and_profiling.js new file mode 100644 index 00000000000..b4803be4d52 --- /dev/null +++ b/app/assets/javascripts/admin/application_settings/setup_metrics_and_profiling.js @@ -0,0 +1,8 @@ +import PayloadPreviewer from '~/pages/admin/application_settings/payload_previewer'; + +export default () => { + new PayloadPreviewer( + document.querySelector('.js-usage-ping-payload-trigger'), + document.querySelector('.js-usage-ping-payload'), + ).init(); +}; diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js index 9c788e283b9..07879ebf7d5 100644 --- a/app/assets/javascripts/diffs/store/utils.js +++ b/app/assets/javascripts/diffs/store/utils.js @@ -424,6 +424,7 @@ export function getDiffPositionByLineCode(diffFiles, useSingleDiffStyle) { old_path: file.old_path, old_line: line.old_line, new_line: line.new_line, + line_range: null, line_code: line.line_code, position_type: 'text', }; diff --git a/app/assets/javascripts/logs/constants.js b/app/assets/javascripts/logs/constants.js index 450b83f4827..51770aa7a1c 100644 --- a/app/assets/javascripts/logs/constants.js +++ b/app/assets/javascripts/logs/constants.js @@ -1,3 +1,3 @@ -export const dateFormatMask = 'UTC:mmm dd HH:MM:ss.l"Z"'; +export const dateFormatMask = 'mmm dd HH:MM:ss.l'; export const TOKEN_TYPE_POD_NAME = 'TOKEN_TYPE_POD_NAME'; diff --git a/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/index.js b/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/index.js index c40503603be..bbaaeb55c65 100644 --- a/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/index.js +++ b/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/index.js @@ -1,8 +1,3 @@ -import UsagePingPayload from './../usage_ping_payload'; +import setup from 'ee_else_ce/admin/application_settings/setup_metrics_and_profiling'; -document.addEventListener('DOMContentLoaded', () => { - new UsagePingPayload( - document.querySelector('.js-usage-ping-payload-trigger'), - document.querySelector('.js-usage-ping-payload'), - ).init(); -}); +document.addEventListener('DOMContentLoaded', setup); diff --git a/app/assets/javascripts/pages/admin/application_settings/usage_ping_payload.js b/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js index 95f4ba28b42..413045d960e 100644 --- a/app/assets/javascripts/pages/admin/application_settings/usage_ping_payload.js +++ b/app/assets/javascripts/pages/admin/application_settings/payload_previewer.js @@ -2,7 +2,7 @@ import axios from '../../../lib/utils/axios_utils'; import { __ } from '../../../locale'; import flash from '../../../flash'; -export default class UsagePingPayload { +export default class PayloadPreviewer { constructor(trigger, container) { this.trigger = trigger; this.container = container; @@ -38,7 +38,7 @@ export default class UsagePingPayload { }) .catch(() => { this.spinner.classList.remove('d-inline-flex'); - flash(__('Error fetching usage ping data.')); + flash(__('Error fetching payload data.')); }); } diff --git a/app/assets/javascripts/static_site_editor/components/saved_changes_message.vue b/app/assets/javascripts/static_site_editor/components/saved_changes_message.vue index 13f66551c00..41cb901720c 100644 --- a/app/assets/javascripts/static_site_editor/components/saved_changes_message.vue +++ b/app/assets/javascripts/static_site_editor/components/saved_changes_message.vue @@ -60,7 +60,7 @@ export default { <ul> <li> {{ s__('StaticSiteEditor|You created a new branch:') }} - <gl-link ref="branchLink" :href="branch.url">{{ branch.label }}</gl-link> + <span ref="branchLink">{{ branch.label }}</span> </li> <li> {{ s__('StaticSiteEditor|You created a merge request:') }} diff --git a/app/assets/javascripts/static_site_editor/components/static_site_editor.vue b/app/assets/javascripts/static_site_editor/components/static_site_editor.vue index 28e10c3c2cb..f8cc6d1630b 100644 --- a/app/assets/javascripts/static_site_editor/components/static_site_editor.vue +++ b/app/assets/javascripts/static_site_editor/components/static_site_editor.vue @@ -6,6 +6,7 @@ import EditArea from './edit_area.vue'; import EditHeader from './edit_header.vue'; import Toolbar from './publish_toolbar.vue'; import InvalidContentMessage from './invalid_content_message.vue'; +import SubmitChangesError from './submit_changes_error.vue'; export default { components: { @@ -14,6 +15,7 @@ export default { InvalidContentMessage, GlSkeletonLoader, Toolbar, + SubmitChangesError, }, computed: { ...mapState([ @@ -24,6 +26,7 @@ export default { 'isSupportedContent', 'returnUrl', 'title', + 'submitChangesError', ]), ...mapGetters(['contentChanged']), }, @@ -33,7 +36,7 @@ export default { } }, methods: { - ...mapActions(['loadContent', 'setContent', 'submitChanges']), + ...mapActions(['loadContent', 'setContent', 'submitChanges', 'dismissSubmitChangesError']), }, }; </script> @@ -51,6 +54,13 @@ export default { </gl-skeleton-loader> </div> <div v-if="isContentLoaded" class="d-flex flex-grow-1 flex-column"> + <submit-changes-error + v-if="submitChangesError" + class="w-75 align-self-center" + :error="submitChangesError" + @retry="submitChanges" + @dismiss="dismissSubmitChangesError" + /> <edit-header class="w-75 align-self-center py-2" :title="title" /> <edit-area class="w-75 h-100 shadow-none align-self-center" diff --git a/app/assets/javascripts/static_site_editor/components/submit_changes_error.vue b/app/assets/javascripts/static_site_editor/components/submit_changes_error.vue new file mode 100644 index 00000000000..c5b6c685124 --- /dev/null +++ b/app/assets/javascripts/static_site_editor/components/submit_changes_error.vue @@ -0,0 +1,24 @@ +<script> +import { GlAlert, GlButton } from '@gitlab/ui'; + +export default { + components: { + GlAlert, + GlButton, + }, + props: { + error: { + type: String, + required: true, + }, + }, +}; +</script> +<template> + <gl-alert variant="danger" dismissible @dismiss="$emit('dismiss')"> + {{ s__('StaticSiteEditor|An error occurred while submitting your changes.') }} {{ error }} + <template #actions> + <gl-button variant="danger" @click="$emit('retry')">{{ __('Retry') }}</gl-button> + </template> + </gl-alert> +</template> diff --git a/app/assets/javascripts/static_site_editor/store/actions.js b/app/assets/javascripts/static_site_editor/store/actions.js index c57ef86f6ef..9f5e9e8c589 100644 --- a/app/assets/javascripts/static_site_editor/store/actions.js +++ b/app/assets/javascripts/static_site_editor/store/actions.js @@ -26,9 +26,12 @@ export const submitChanges = ({ state: { projectId, content, sourcePath, usernam return submitContentChanges({ content, projectId, sourcePath, username }) .then(data => commit(mutationTypes.SUBMIT_CHANGES_SUCCESS, data)) .catch(error => { - commit(mutationTypes.SUBMIT_CHANGES_ERROR); - createFlash(error.message); + commit(mutationTypes.SUBMIT_CHANGES_ERROR, error.message); }); }; +export const dismissSubmitChangesError = ({ commit }) => { + commit(mutationTypes.DISMISS_SUBMIT_CHANGES_ERROR); +}; + export default () => {}; diff --git a/app/assets/javascripts/static_site_editor/store/mutation_types.js b/app/assets/javascripts/static_site_editor/store/mutation_types.js index 35eb35ebbe9..9cf356aecc5 100644 --- a/app/assets/javascripts/static_site_editor/store/mutation_types.js +++ b/app/assets/javascripts/static_site_editor/store/mutation_types.js @@ -5,3 +5,4 @@ export const SET_CONTENT = 'setContent'; export const SUBMIT_CHANGES = 'submitChanges'; export const SUBMIT_CHANGES_SUCCESS = 'submitChangesSuccess'; export const SUBMIT_CHANGES_ERROR = 'submitChangesError'; +export const DISMISS_SUBMIT_CHANGES_ERROR = 'dismissSubmitChangesError'; diff --git a/app/assets/javascripts/static_site_editor/store/mutations.js b/app/assets/javascripts/static_site_editor/store/mutations.js index 4727d04439c..72fe71f1c9b 100644 --- a/app/assets/javascripts/static_site_editor/store/mutations.js +++ b/app/assets/javascripts/static_site_editor/store/mutations.js @@ -19,13 +19,18 @@ export default { }, [types.SUBMIT_CHANGES](state) { state.isSavingChanges = true; + state.submitChangesError = ''; }, [types.SUBMIT_CHANGES_SUCCESS](state, meta) { state.savedContentMeta = meta; state.isSavingChanges = false; state.originalContent = state.content; }, - [types.SUBMIT_CHANGES_ERROR](state) { + [types.SUBMIT_CHANGES_ERROR](state, error) { + state.submitChangesError = error; state.isSavingChanges = false; }, + [types.DISMISS_SUBMIT_CHANGES_ERROR](state) { + state.submitChangesError = ''; + }, }; diff --git a/app/assets/javascripts/static_site_editor/store/state.js b/app/assets/javascripts/static_site_editor/store/state.js index 3d9fa9e6303..8c524b4ffe9 100644 --- a/app/assets/javascripts/static_site_editor/store/state.js +++ b/app/assets/javascripts/static_site_editor/store/state.js @@ -14,6 +14,7 @@ const createState = (initialState = {}) => ({ content: '', title: '', + submitChangesError: '', savedContentMeta: null, ...initialState, diff --git a/app/models/diff_note_position.rb b/app/models/diff_note_position.rb index 716a56c6430..a25b0def643 100644 --- a/app/models/diff_note_position.rb +++ b/app/models/diff_note_position.rb @@ -2,6 +2,7 @@ class DiffNotePosition < ApplicationRecord belongs_to :note + attr_accessor :line_range enum diff_content_type: { text: 0, @@ -42,6 +43,7 @@ class DiffNotePosition < ApplicationRecord def self.position_to_attrs(position) position_attrs = position.to_h position_attrs[:diff_content_type] = position_attrs.delete(:position_type) + position_attrs.delete(:line_range) position_attrs end end diff --git a/app/models/project_services/prometheus_service.rb b/app/models/project_services/prometheus_service.rb index 1a85289a04f..4a28d1ff2b0 100644 --- a/app/models/project_services/prometheus_service.rb +++ b/app/models/project_services/prometheus_service.rb @@ -36,10 +36,6 @@ class PrometheusService < MonitoringService false end - def editable? - manual_configuration? || !prometheus_available? - end - def title 'Prometheus' end @@ -53,8 +49,6 @@ class PrometheusService < MonitoringService end def fields - return [] unless editable? - [ { type: 'checkbox', diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml index ec05ff50f25..2e5953bf0a6 100644 --- a/app/views/projects/commits/_commits.html.haml +++ b/app/views/projects/commits/_commits.html.haml @@ -4,11 +4,12 @@ - commits = @commits - hidden = @hidden_commit_count +- commits_count = @commits.size - commits.chunk { |c| c.committed_date.in_time_zone.to_date }.each do |day, commits| %li.commit-header.js-commit-header{ data: { day: day } } %span.day= l(day, format: '%d %b, %Y') - %span.commits-count= n_("%d commit", "%d commits", commits.count) % commits.count + %span.commits-count= n_("%d commit", "%d commits", commits_count) % commits_count %li.commits-row{ data: { day: day } } %ul.content-list.commit-list.flex-list @@ -17,3 +18,9 @@ - if hidden > 0 %li.alert.alert-warning = n_('%s additional commit has been omitted to prevent performance issues.', '%s additional commits have been omitted to prevent performance issues.', hidden) % number_with_delimiter(hidden) + +- if commits_count == 0 + .mt-4.text-center + .bold + = _('Your search didn\'t match any commits.') + = _('Try changing or removing filters.') diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml index bd9defe5f74..0dbd6a48ec5 100644 --- a/app/views/projects/services/_form.html.haml +++ b/app/views/projects/services/_form.html.haml @@ -12,11 +12,10 @@ .col-lg-9 = form_for(@service, as: :service, url: scoped_integration_path(@service), method: :put, html: { class: 'gl-show-field-errors integration-settings-form js-integration-settings-form', data: { 'can-test' => @service.can_test?, 'test-url' => test_project_service_path(@project, @service) } }) do |form| = render 'shared/service_settings', form: form, service: @service - - if @service.editable? - .footer-block.row-content-block - = service_save_button(@service) - - = link_to _('Cancel'), project_settings_integrations_path(@project), class: 'btn btn-cancel' + .footer-block.row-content-block + = service_save_button(@service) + + = link_to _('Cancel'), project_settings_integrations_path(@project), class: 'btn btn-cancel' - if lookup_context.template_exists?('show', "projects/services/#{@service.to_param}", true) %hr diff --git a/app/views/projects/services/prometheus/_help.html.haml b/app/views/projects/services/prometheus/_help.html.haml index 35d655e4b32..1b5b794a7aa 100644 --- a/app/views/projects/services/prometheus/_help.html.haml +++ b/app/views/projects/services/prometheus/_help.html.haml @@ -3,7 +3,5 @@ %h4.append-bottom-default = s_('PrometheusService|Manual configuration') - -- unless @service.editable? - .info-well - = s_('PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters') +%p + = s_('PrometheusService|Select the Active checkbox to override the Auto Configuration with custom settings. If unchecked, Auto Configuration settings are used.') diff --git a/app/views/projects/settings/operations/_prometheus.html.haml b/app/views/projects/settings/operations/_prometheus.html.haml index 3d7a6b021a8..b0fa750e131 100644 --- a/app/views/projects/settings/operations/_prometheus.html.haml +++ b/app/views/projects/settings/operations/_prometheus.html.haml @@ -13,7 +13,5 @@ %b.append-bottom-default = s_('PrometheusService|Manual configuration') - - - unless service.editable? - .info-well - = s_('PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters') + %p + = s_('PrometheusService|Select the Active checkbox to override the Auto Configuration with custom settings. If unchecked, Auto Configuration settings are used.') diff --git a/changelogs/unreleased/14984-add-text-for-empty-commit-list.yml b/changelogs/unreleased/14984-add-text-for-empty-commit-list.yml new file mode 100644 index 00000000000..deae5b4fe09 --- /dev/null +++ b/changelogs/unreleased/14984-add-text-for-empty-commit-list.yml @@ -0,0 +1,5 @@ +--- +title: Add temporary empty message when no result is found +merge_request: 29306 +author: +type: added diff --git a/changelogs/unreleased/205058-add-env-vars-to-ds.yml b/changelogs/unreleased/205058-add-env-vars-to-ds.yml new file mode 100644 index 00000000000..b783110e382 --- /dev/null +++ b/changelogs/unreleased/205058-add-env-vars-to-ds.yml @@ -0,0 +1,5 @@ +--- +title: Add GRADLE_CLI_OPTS and SBT_CLI_OPTS env vars to dependency scanning orchestrator +merge_request: 29595 +author: +type: added diff --git a/changelogs/unreleased/207233-k8s-cluster-blocks-project-manual-prometheus-configuration.yml b/changelogs/unreleased/207233-k8s-cluster-blocks-project-manual-prometheus-configuration.yml new file mode 100644 index 00000000000..fe94ee48e97 --- /dev/null +++ b/changelogs/unreleased/207233-k8s-cluster-blocks-project-manual-prometheus-configuration.yml @@ -0,0 +1,5 @@ +--- +title: Make manual prometheus configuration section always editable +merge_request: 29209 +author: +type: changed diff --git a/changelogs/unreleased/214108-log-explorer-timestamp-in-the-logs-presented-in-utc-and-should-be-.yml b/changelogs/unreleased/214108-log-explorer-timestamp-in-the-logs-presented-in-utc-and-should-be-.yml new file mode 100644 index 00000000000..109be757dce --- /dev/null +++ b/changelogs/unreleased/214108-log-explorer-timestamp-in-the-logs-presented-in-utc-and-should-be-.yml @@ -0,0 +1,5 @@ +--- +title: Display local timezone in log explorer +merge_request: 29409 +author: +type: changed diff --git a/changelogs/unreleased/dblessing-add-missing-on-delete-fk-constraints.yml b/changelogs/unreleased/dblessing-add-missing-on-delete-fk-constraints.yml new file mode 100644 index 00000000000..dc9daa2825f --- /dev/null +++ b/changelogs/unreleased/dblessing-add-missing-on-delete-fk-constraints.yml @@ -0,0 +1,5 @@ +--- +title: Add missing ON DELETE FK constraints referencing users table +merge_request: 28720 +author: +type: fixed diff --git a/changelogs/unreleased/display-retry-button-in-error-message.yml b/changelogs/unreleased/display-retry-button-in-error-message.yml new file mode 100644 index 00000000000..6b529143310 --- /dev/null +++ b/changelogs/unreleased/display-retry-button-in-error-message.yml @@ -0,0 +1,5 @@ +--- +title: Allow to retry submitting changes when an error occurs +merge_request: 29434 +author: +type: changed diff --git a/changelogs/unreleased/do-not-display-branch-link.yml b/changelogs/unreleased/do-not-display-branch-link.yml new file mode 100644 index 00000000000..4b402820f88 --- /dev/null +++ b/changelogs/unreleased/do-not-display-branch-link.yml @@ -0,0 +1,5 @@ +--- +title: Do not display branch link in saved changes message UI +merge_request: 29611 +author: +type: changed diff --git a/changelogs/unreleased/feature-bump-cluster-applications-to-0-15.yml b/changelogs/unreleased/feature-bump-cluster-applications-to-0-15.yml new file mode 100644 index 00000000000..dbedaf2d97e --- /dev/null +++ b/changelogs/unreleased/feature-bump-cluster-applications-to-0-15.yml @@ -0,0 +1,5 @@ +--- +title: Adds Knative and Fluentd as CI/CD managed applications +merge_request: 29637 +author: +type: added diff --git a/changelogs/unreleased/multi-line-notes-take-3.yml b/changelogs/unreleased/multi-line-notes-take-3.yml new file mode 100644 index 00000000000..3d290d8c027 --- /dev/null +++ b/changelogs/unreleased/multi-line-notes-take-3.yml @@ -0,0 +1,5 @@ +--- +title: Add line range to diff note position +merge_request: 29135 +author: +type: added diff --git a/config/routes/project.rb b/config/routes/project.rb index ab7c439318f..1ce889dd578 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -26,10 +26,6 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do scope '-' do get 'archive/*id', constraints: { format: Gitlab::PathRegex.archive_formats_regex, id: /.+?/ }, to: 'repositories#archive', as: 'archive' - scope controller: :static_site_editor do - get '/sse/*id', action: :show, as: :show_sse - end - resources :artifacts, only: [:index, :destroy] resources :jobs, only: [:index, :show], constraints: { id: /\d+/ } do diff --git a/config/routes/repository.rb b/config/routes/repository.rb index 38d6cdbbaf8..eec204f2870 100644 --- a/config/routes/repository.rb +++ b/config/routes/repository.rb @@ -21,6 +21,9 @@ resources :commit, only: [:show], constraints: { id: /\h{7,40}/ } do end end +# NOTE: Add new routes to repository_scoped.rb instead (see +# https://docs.gitlab.com/ee/development/routing.html#project-routes). +# # Don't use format parameter as file extension (old 3.0.x behavior) # See http://guides.rubyonrails.org/routing.html#route-globbing-and-wildcard-segments scope format: false do diff --git a/config/routes/repository_scoped.rb b/config/routes/repository_scoped.rb index c6343039d62..42ec8ca1806 100644 --- a/config/routes/repository_scoped.rb +++ b/config/routes/repository_scoped.rb @@ -30,5 +30,11 @@ scope format: false do resources :protected_branches, only: [:index, :show, :create, :update, :destroy, :patch], constraints: { id: Gitlab::PathRegex.git_reference_regex } resources :protected_tags, only: [:index, :show, :create, :update, :destroy] + + scope constraints: { id: /[^\0]+/ } do + scope controller: :static_site_editor do + get '/sse/*id', action: :show, as: :show_sse + end + end end end diff --git a/db/migrate/20200407171133_add_protected_tag_create_access_levels_user_id_foreign_key.rb b/db/migrate/20200407171133_add_protected_tag_create_access_levels_user_id_foreign_key.rb new file mode 100644 index 00000000000..d6d6d86a0ad --- /dev/null +++ b/db/migrate/20200407171133_add_protected_tag_create_access_levels_user_id_foreign_key.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +# rubocop: disable Migration/AddConcurrentForeignKey +class AddProtectedTagCreateAccessLevelsUserIdForeignKey < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + CONSTRAINT_NAME = 'fk_protected_tag_create_access_levels_user_id' + + def up + with_lock_retries do + add_foreign_key(:protected_tag_create_access_levels, :users, on_delete: :cascade, validate: false, name: CONSTRAINT_NAME) + remove_foreign_key_if_exists(:protected_tag_create_access_levels, column: :user_id, on_delete: nil) + end + end + + def down + fk_exists = foreign_key_exists?(:protected_tag_create_access_levels, :users, column: :user_id, on_delete: nil) + + unless fk_exists + with_lock_retries do + add_foreign_key(:protected_tag_create_access_levels, :users, column: :user_id, validate: false) + end + end + + remove_foreign_key_if_exists(:protected_tag_create_access_levels, column: :user_id, name: CONSTRAINT_NAME) + + fk_name = concurrent_foreign_key_name(:protected_tag_create_access_levels, :user_id, prefix: 'fk_rails_') + validate_foreign_key(:protected_tag_create_access_levels, :user_id, name: fk_name) + end +end diff --git a/db/migrate/20200407171417_validate_protected_tag_create_access_levels_user_id_foreign_key.rb b/db/migrate/20200407171417_validate_protected_tag_create_access_levels_user_id_foreign_key.rb new file mode 100644 index 00000000000..baba65e0b7d --- /dev/null +++ b/db/migrate/20200407171417_validate_protected_tag_create_access_levels_user_id_foreign_key.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class ValidateProtectedTagCreateAccessLevelsUserIdForeignKey < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + CONSTRAINT_NAME = 'fk_protected_tag_create_access_levels_user_id' + + def up + validate_foreign_key :protected_tag_create_access_levels, :user_id, name: CONSTRAINT_NAME + end + + def down + # no op + end +end diff --git a/db/migrate/20200408154331_add_protected_branch_merge_access_levels_user_id_foreign_key.rb b/db/migrate/20200408154331_add_protected_branch_merge_access_levels_user_id_foreign_key.rb new file mode 100644 index 00000000000..0d80c095757 --- /dev/null +++ b/db/migrate/20200408154331_add_protected_branch_merge_access_levels_user_id_foreign_key.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +# rubocop: disable Migration/AddConcurrentForeignKey +class AddProtectedBranchMergeAccessLevelsUserIdForeignKey < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + CONSTRAINT_NAME = 'fk_protected_branch_merge_access_levels_user_id' + + def up + with_lock_retries do + add_foreign_key(:protected_branch_merge_access_levels, :users, on_delete: :cascade, validate: false, name: CONSTRAINT_NAME) + remove_foreign_key_if_exists(:protected_branch_merge_access_levels, column: :user_id, on_delete: nil) + end + end + + def down + fk_exists = foreign_key_exists?(:protected_branch_merge_access_levels, :users, column: :user_id, on_delete: nil) + + unless fk_exists + with_lock_retries do + add_foreign_key(:protected_branch_merge_access_levels, :users, column: :user_id, validate: false) + end + end + + remove_foreign_key_if_exists(:protected_branch_merge_access_levels, column: :user_id, name: CONSTRAINT_NAME) + + fk_name = concurrent_foreign_key_name(:protected_branch_merge_access_levels, :user_id, prefix: 'fk_rails_') + validate_foreign_key(:protected_branch_merge_access_levels, :user_id, name: fk_name) + end +end diff --git a/db/migrate/20200408154349_validate_protected_branch_merge_access_levels_user_id_foreign_key.rb b/db/migrate/20200408154349_validate_protected_branch_merge_access_levels_user_id_foreign_key.rb new file mode 100644 index 00000000000..c4ec957d607 --- /dev/null +++ b/db/migrate/20200408154349_validate_protected_branch_merge_access_levels_user_id_foreign_key.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class ValidateProtectedBranchMergeAccessLevelsUserIdForeignKey < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + CONSTRAINT_NAME = 'fk_protected_branch_merge_access_levels_user_id' + + def up + validate_foreign_key :protected_branch_merge_access_levels, :user_id, name: CONSTRAINT_NAME + end + + def down + # no op + end +end diff --git a/db/migrate/20200408154411_add_path_locks_user_id_foreign_key.rb b/db/migrate/20200408154411_add_path_locks_user_id_foreign_key.rb new file mode 100644 index 00000000000..8fcfb2615bb --- /dev/null +++ b/db/migrate/20200408154411_add_path_locks_user_id_foreign_key.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +# rubocop: disable Migration/AddConcurrentForeignKey +class AddPathLocksUserIdForeignKey < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + CONSTRAINT_NAME = 'fk_path_locks_user_id' + + def up + with_lock_retries do + add_foreign_key(:path_locks, :users, on_delete: :cascade, validate: false, name: CONSTRAINT_NAME) + remove_foreign_key_if_exists(:path_locks, column: :user_id, on_delete: nil) + end + end + + def down + fk_exists = foreign_key_exists?(:path_locks, :users, column: :user_id, on_delete: nil) + + unless fk_exists + with_lock_retries do + add_foreign_key(:path_locks, :users, column: :user_id, validate: false) + end + end + + remove_foreign_key_if_exists(:path_locks, column: :user_id, name: CONSTRAINT_NAME) + + fk_name = concurrent_foreign_key_name(:path_locks, :user_id, prefix: 'fk_rails_') + validate_foreign_key(:path_locks, :user_id, name: fk_name) + end +end diff --git a/db/migrate/20200408154428_validate_path_locks_user_id_foreign_key.rb b/db/migrate/20200408154428_validate_path_locks_user_id_foreign_key.rb new file mode 100644 index 00000000000..500409ee44a --- /dev/null +++ b/db/migrate/20200408154428_validate_path_locks_user_id_foreign_key.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class ValidatePathLocksUserIdForeignKey < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + CONSTRAINT_NAME = 'fk_path_locks_user_id' + + def up + validate_foreign_key :path_locks, :user_id, name: CONSTRAINT_NAME + end + + def down + # no op + end +end diff --git a/db/migrate/20200408154455_add_protected_branch_push_access_levels_user_id_foreign_key.rb b/db/migrate/20200408154455_add_protected_branch_push_access_levels_user_id_foreign_key.rb new file mode 100644 index 00000000000..9127e5dea7f --- /dev/null +++ b/db/migrate/20200408154455_add_protected_branch_push_access_levels_user_id_foreign_key.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +# rubocop: disable Migration/AddConcurrentForeignKey +class AddProtectedBranchPushAccessLevelsUserIdForeignKey < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + CONSTRAINT_NAME = 'fk_protected_branch_push_access_levels_user_id' + + def up + with_lock_retries do + add_foreign_key(:protected_branch_push_access_levels, :users, on_delete: :cascade, validate: false, name: CONSTRAINT_NAME) + remove_foreign_key_if_exists(:protected_branch_push_access_levels, column: :user_id, on_delete: nil) + end + end + + def down + fk_exists = foreign_key_exists?(:protected_branch_push_access_levels, :users, column: :user_id, on_delete: nil) + + unless fk_exists + with_lock_retries do + add_foreign_key(:protected_branch_push_access_levels, :users, column: :user_id, validate: false) + end + end + + remove_foreign_key_if_exists(:protected_branch_push_access_levels, column: :user_id, name: CONSTRAINT_NAME) + + fk_name = concurrent_foreign_key_name(:protected_branch_push_access_levels, :user_id, prefix: 'fk_rails_') + validate_foreign_key(:protected_branch_push_access_levels, :user_id, name: fk_name) + end +end diff --git a/db/migrate/20200408154533_validate_protected_branch_push_access_levels_user_id_foreign_key.rb b/db/migrate/20200408154533_validate_protected_branch_push_access_levels_user_id_foreign_key.rb new file mode 100644 index 00000000000..d6f9cab6d7e --- /dev/null +++ b/db/migrate/20200408154533_validate_protected_branch_push_access_levels_user_id_foreign_key.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class ValidateProtectedBranchPushAccessLevelsUserIdForeignKey < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + CONSTRAINT_NAME = 'fk_protected_branch_push_access_levels_user_id' + + def up + validate_foreign_key :protected_branch_push_access_levels, :user_id, name: CONSTRAINT_NAME + end + + def down + # no op + end +end diff --git a/db/migrate/20200408154604_add_u2f_registrations_user_id_foreign_key.rb b/db/migrate/20200408154604_add_u2f_registrations_user_id_foreign_key.rb new file mode 100644 index 00000000000..92aded750e5 --- /dev/null +++ b/db/migrate/20200408154604_add_u2f_registrations_user_id_foreign_key.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +# rubocop: disable Migration/AddConcurrentForeignKey +class AddU2fRegistrationsUserIdForeignKey < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + CONSTRAINT_NAME = 'fk_u2f_registrations_user_id' + + def up + with_lock_retries do + add_foreign_key(:u2f_registrations, :users, on_delete: :cascade, validate: false, name: CONSTRAINT_NAME) + remove_foreign_key_if_exists(:u2f_registrations, column: :user_id, on_delete: nil) + end + end + + def down + fk_exists = foreign_key_exists?(:u2f_registrations, :users, column: :user_id, on_delete: nil) + + unless fk_exists + with_lock_retries do + add_foreign_key(:u2f_registrations, :users, column: :user_id, validate: false) + end + end + + remove_foreign_key_if_exists(:u2f_registrations, column: :user_id, name: CONSTRAINT_NAME) + + fk_name = concurrent_foreign_key_name(:u2f_registrations, :user_id, prefix: 'fk_rails_') + validate_foreign_key(:u2f_registrations, :user_id, name: fk_name) + end +end diff --git a/db/migrate/20200408154624_validate_u2f_registrations_user_id_foreign_key.rb b/db/migrate/20200408154624_validate_u2f_registrations_user_id_foreign_key.rb new file mode 100644 index 00000000000..ff723a4793f --- /dev/null +++ b/db/migrate/20200408154624_validate_u2f_registrations_user_id_foreign_key.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true +# +class ValidateU2fRegistrationsUserIdForeignKey < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + CONSTRAINT_NAME = 'fk_u2f_registrations_user_id' + + def up + validate_foreign_key :u2f_registrations, :user_id, name: CONSTRAINT_NAME + end + + def down + # no op + end +end diff --git a/db/structure.sql b/db/structure.sql index 56efa356123..83b01662530 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -11044,9 +11044,21 @@ ALTER TABLE ONLY public.issues ALTER TABLE ONLY public.geo_event_log ADD CONSTRAINT fk_geo_event_log_on_geo_event_id FOREIGN KEY (geo_event_id) REFERENCES public.geo_events(id) ON DELETE CASCADE; +ALTER TABLE ONLY public.path_locks + ADD CONSTRAINT fk_path_locks_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + ALTER TABLE ONLY public.personal_access_tokens ADD CONSTRAINT fk_personal_access_tokens_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; +ALTER TABLE ONLY public.protected_branch_merge_access_levels + ADD CONSTRAINT fk_protected_branch_merge_access_levels_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + +ALTER TABLE ONLY public.protected_branch_push_access_levels + ADD CONSTRAINT fk_protected_branch_push_access_levels_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + +ALTER TABLE ONLY public.protected_tag_create_access_levels + ADD CONSTRAINT fk_protected_tag_create_access_levels_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + ALTER TABLE ONLY public.approval_merge_request_rules ADD CONSTRAINT fk_rails_004ce82224 FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE; @@ -11191,9 +11203,6 @@ ALTER TABLE ONLY public.clusters_applications_runners ALTER TABLE ONLY public.service_desk_settings ADD CONSTRAINT fk_rails_223a296a85 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE; -ALTER TABLE ONLY public.protected_tag_create_access_levels - ADD CONSTRAINT fk_rails_2349b78b91 FOREIGN KEY (user_id) REFERENCES public.users(id); - ALTER TABLE ONLY public.group_custom_attributes ADD CONSTRAINT fk_rails_246e0db83a FOREIGN KEY (group_id) REFERENCES public.namespaces(id) ON DELETE CASCADE; @@ -11440,9 +11449,6 @@ ALTER TABLE ONLY public.resource_weight_events ALTER TABLE ONLY public.approval_project_rules ADD CONSTRAINT fk_rails_5fb4dd100b FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE; -ALTER TABLE ONLY public.protected_branch_merge_access_levels - ADD CONSTRAINT fk_rails_5ffb4f3590 FOREIGN KEY (user_id) REFERENCES public.users(id); - ALTER TABLE ONLY public.user_highest_roles ADD CONSTRAINT fk_rails_60f6c325a6 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; @@ -11551,9 +11557,6 @@ ALTER TABLE ONLY public.geo_repositories_changed_events ALTER TABLE ONLY public.resource_label_events ADD CONSTRAINT fk_rails_75efb0a653 FOREIGN KEY (epic_id) REFERENCES public.epics(id) ON DELETE CASCADE; -ALTER TABLE ONLY public.path_locks - ADD CONSTRAINT fk_rails_762cdcf942 FOREIGN KEY (user_id) REFERENCES public.users(id); - ALTER TABLE ONLY public.x509_certificates ADD CONSTRAINT fk_rails_76479fb5b4 FOREIGN KEY (x509_issuer_id) REFERENCES public.x509_issuers(id) ON DELETE CASCADE; @@ -11629,9 +11632,6 @@ ALTER TABLE ONLY public.vulnerability_feedback ALTER TABLE ONLY public.approval_merge_request_rules_approved_approvers ADD CONSTRAINT fk_rails_8dc94cff4d FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; -ALTER TABLE ONLY public.protected_branch_push_access_levels - ADD CONSTRAINT fk_rails_8dcb712d65 FOREIGN KEY (user_id) REFERENCES public.users(id); - ALTER TABLE ONLY public.design_user_mentions ADD CONSTRAINT fk_rails_8de8c6d632 FOREIGN KEY (note_id) REFERENCES public.notes(id) ON DELETE CASCADE; @@ -11842,9 +11842,6 @@ ALTER TABLE ONLY public.resource_weight_events ALTER TABLE ONLY public.design_management_designs ADD CONSTRAINT fk_rails_bfe283ec3c FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE; -ALTER TABLE ONLY public.u2f_registrations - ADD CONSTRAINT fk_rails_bfe6a84544 FOREIGN KEY (user_id) REFERENCES public.users(id); - ALTER TABLE ONLY public.serverless_domain_cluster ADD CONSTRAINT fk_rails_c09009dee1 FOREIGN KEY (pages_domain_id) REFERENCES public.pages_domains(id) ON DELETE CASCADE; @@ -12079,6 +12076,9 @@ ALTER TABLE ONLY public.timelogs ALTER TABLE ONLY public.timelogs ADD CONSTRAINT fk_timelogs_merge_requests_merge_request_id FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE; +ALTER TABLE ONLY public.u2f_registrations + ADD CONSTRAINT fk_u2f_registrations_user_id FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE; + COPY "schema_migrations" (version) FROM STDIN; 20171230123729 20180101160629 @@ -13161,9 +13161,19 @@ COPY "schema_migrations" (version) FROM STDIN; 20200406193427 20200407094005 20200407094923 +20200407171133 +20200407171417 20200408110856 20200408133211 20200408153842 +20200408154331 +20200408154349 +20200408154411 +20200408154428 +20200408154455 +20200408154533 +20200408154604 +20200408154624 20200408175424 20200409211607 20200415160722 diff --git a/doc/api/discussions.md b/doc/api/discussions.md index f1e8965b336..572e174201d 100644 --- a/doc/api/discussions.md +++ b/doc/api/discussions.md @@ -739,7 +739,7 @@ GET /projects/:id/merge_requests/:merge_request_iid/discussions ] ``` -Diff comments contain also position: +Diff comments also contain position: ```json [ @@ -774,7 +774,11 @@ Diff comments contain also position: "new_path": "package.json", "position_type": "text", "old_line": 27, - "new_line": 27 + "new_line": 27, + "line_range": { + "start_line_code": "588440f66559714280628a4f9799f0c4eb880a4a_10_10", + "end_line_code": "588440f66559714280628a4f9799f0c4eb880a4a_11_11" + } }, "resolved": false, "resolvable": true, @@ -820,25 +824,28 @@ POST /projects/:id/merge_requests/:merge_request_iid/discussions Parameters: -| Attribute | Type | Required | Description | -| ------------------------- | -------------- | -------- | ----------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) | -| `merge_request_iid` | integer | yes | The IID of a merge request | -| `body` | string | yes | The content of the thread | -| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) | -| `position` | hash | no | Position when creating a diff note | -| `position[base_sha]` | string | yes | Base commit SHA in the source branch | -| `position[start_sha]` | string | yes | SHA referencing commit in target branch | -| `position[head_sha]` | string | yes | SHA referencing HEAD of this merge request | -| `position[position_type]` | string | yes | Type of the position reference', allowed values: 'text' or 'image' | -| `position[new_path]` | string | no | File path after change | -| `position[new_line]` | integer | no | Line number after change (for 'text' diff notes) | -| `position[old_path]` | string | no | File path before change | -| `position[old_line]` | integer | no | Line number before change (for 'text' diff notes) | -| `position[width]` | integer | no | Width of the image (for 'image' diff notes) | -| `position[height]` | integer | no | Height of the image (for 'image' diff notes) | -| `position[x]` | integer | no | X coordinate (for 'image' diff notes) | -| `position[y]` | integer | no | Y coordinate (for 'image' diff notes) | +| Attribute | Type | Required | Description | +| --------------------------------------- | -------------- | -------- | ----------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) | +| `merge_request_iid` | integer | yes | The IID of a merge request | +| `body` | string | yes | The content of the thread | +| `created_at` | string | no | Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights) | +| `position` | hash | no | Position when creating a diff note | +| `position[base_sha]` | string | yes | Base commit SHA in the source branch | +| `position[start_sha]` | string | yes | SHA referencing commit in target branch | +| `position[head_sha]` | string | yes | SHA referencing HEAD of this merge request | +| `position[position_type]` | string | yes | Type of the position reference', allowed values: 'text' or 'image' | +| `position[new_path]` | string | no | File path after change | +| `position[new_line]` | integer | no | Line number after change (for 'text' diff notes) | +| `position[old_path]` | string | no | File path before change | +| `position[old_line]` | integer | no | Line number before change (for 'text' diff notes) | +| `position[line_range]` | hash | no | Line range for a multi-line diff note | +| `position[line_range][start_line_code]` | string | yes | Line code for the start line | +| `position[line_range][end_line_code]` | string | yes | Line code for the end line | +| `position[width]` | integer | no | Width of the image (for 'image' diff notes) | +| `position[height]` | integer | no | Height of the image (for 'image' diff notes) | +| `position[x]` | integer | no | X coordinate (for 'image' diff notes) | +| `position[y]` | integer | no | Y coordinate (for 'image' diff notes) | ```shell curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions?body=comment diff --git a/doc/ci/review_apps/index.md b/doc/ci/review_apps/index.md index 860eab469dd..c3bdd524bff 100644 --- a/doc/ci/review_apps/index.md +++ b/doc/ci/review_apps/index.md @@ -188,9 +188,6 @@ With Visual Reviews, you can provide a feedback form to your Review Apps so that reviewers can post comments directly from the app back to the merge request that spawned the Review App. -NOTE: **Note:** Visual Reviews currently only work for public projects. Support for private -and internal projects [is planned](https://gitlab.com/gitlab-org/gitlab/-/issues/42750). - ### Configuring Visual Reviews Ensure that the `anonymous_visual_review_feedback` feature flag is enabled. @@ -218,6 +215,7 @@ looks like: data-merge-request-id='1' data-mr-url='https://gitlab.example.com' data-project-path='sarah/review-app-tester' + data-require-auth='true' id='review-app-toolbar-script' src='https://gitlab.example.com/assets/webpack/visual_review_toolbar.js'> </script> @@ -235,6 +233,7 @@ to replace those values at runtime when each review app is created: - `data-mr-url` is the URL of the GitLab instance and will be the same for all review apps. - `data-project-path` is the project's path, which can be found by `CI_PROJECT_PATH`. +- `data-require-auth` is optional for public projects but required for [private and internal ones](#visual-reviews-in-private-or-internal-projects). If this is set to `true`, the user will be required to enter their [personal access token](../../user/profile/personal_access_tokens.md) instead of their name and email. - `id` is always `review-app-toolbar-script`, you don't need to change that. - `src` is the source of the review toolbar script, which resides in the respective GitLab instance and will be the same for all review apps. @@ -272,6 +271,15 @@ can supply the ID by either: - Dynamically adding the `data-merge-request-id` value during the build of the app. - Supplying it manually through the visual review form in the app. +### Visual Reviews in private or internal projects + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/42750#note_317271120) in GitLab 12.10. + +To enable visual reviews for private and internal projects, set the +[`data-require-auth` variable](#configuring-visual-reviews) to `true`. When enabled, +the user must enter a [personal access token](../../user/profile/personal_access_tokens.md) +with `read_api` scope before submitting feedback. + ### Using Visual Reviews After Visual Reviews has been [enabled](#configuring-visual-reviews) for the @@ -285,7 +293,7 @@ To use the feedback form: 1. Make a comment on the visual review. You can make use of all the [Markdown annotations](../../user/markdown.md) that are also available in merge request comments. -1. Submit your feedback anonymously or add your name. +1. If `data-require-auth` is `true`, you must enter your [personal access token](../../user/profile/personal_access_tokens.md). Otherwise, you must enter your name, and optionally, your email. 1. Finally, click **Send feedback**. After you make and submit a comment in the visual review box, it will appear diff --git a/doc/development/architecture.md b/doc/development/architecture.md index 436cb43199e..bbd5ca3c494 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -314,7 +314,7 @@ You can use it either for personal or business websites, such as portfolios, doc - Layer: Core Service (Processor) - GitLab.com: [Runner](../user/gitlab_com/index.md#shared-runners) -GitLab Runner runs tests and sends the results to GitLab. +GitLab Runner runs jobs and sends the results to GitLab. GitLab CI/CD is the open-source continuous integration service included with GitLab that coordinates the testing. The old name of this project was `GitLab CI Multi Runner` but please use `GitLab Runner` (without CI) from now on. diff --git a/doc/subscriptions/index.md b/doc/subscriptions/index.md index 63a10fdf4be..c81310edc44 100644 --- a/doc/subscriptions/index.md +++ b/doc/subscriptions/index.md @@ -308,6 +308,11 @@ Sg0KU1hNMGExaE9SVGR2V2pKQlBUMWNiaUo5DQo=', </details> +You can view the exact JSON payload in the administration panel. To view the payload: + +1. Navigate to **Admin Area > Settings > Metrics and profiling** and expand **Seat Links**. +1. Click **Preview payload**. + #### Disable Seat Link > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212375) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.10. diff --git a/lib/api/discussions.rb b/lib/api/discussions.rb index 8ff275a3a1b..0dd1850e526 100644 --- a/lib/api/discussions.rb +++ b/lib/api/discussions.rb @@ -74,6 +74,11 @@ module API optional :height, type: Integer, desc: 'Height of the image' optional :x, type: Integer, desc: 'X coordinate in the image' optional :y, type: Integer, desc: 'Y coordinate in the image' + + optional :line_range, type: Hash, desc: 'Multi-line start and end' do + requires :start_line_code, type: String, desc: 'Start line code for multi-line note' + requires :end_line_code, type: String, desc: 'End line code for multi-line note' + end end end post ":id/#{noteables_path}/:noteable_id/discussions" do diff --git a/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml b/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml index 713b11c4d8f..54a29b04d39 100644 --- a/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml @@ -1,6 +1,6 @@ apply: stage: deploy - image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.13.1" + image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.15.0" environment: name: production variables: @@ -17,6 +17,8 @@ apply: ELASTIC_STACK_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/elastic-stack/values.yaml VAULT_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/vault/values.yaml CROSSPLANE_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/crossplane/values.yaml + FLUENTD_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/fluentd/values.yaml + KNATIVE_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/knative/values.yaml script: - gitlab-managed-apps /usr/local/share/gitlab-managed-apps/helmfile.yaml only: diff --git a/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml index 717e91b3ae5..0ecf37b37a3 100644 --- a/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml @@ -57,6 +57,8 @@ dependency_scanning: PIP_EXTRA_INDEX_URL \ PIP_REQUIREMENTS_FILE \ MAVEN_CLI_OPTS \ + GRADLE_CLI_OPTS \ + SBT_CLI_OPTS \ BUNDLER_AUDIT_UPDATE_DISABLED \ BUNDLER_AUDIT_ADVISORY_DB_URL \ BUNDLER_AUDIT_ADVISORY_DB_REF_NAME \ diff --git a/lib/gitlab/diff/formatters/text_formatter.rb b/lib/gitlab/diff/formatters/text_formatter.rb index 5b670b1f83b..728457b3139 100644 --- a/lib/gitlab/diff/formatters/text_formatter.rb +++ b/lib/gitlab/diff/formatters/text_formatter.rb @@ -6,10 +6,12 @@ module Gitlab class TextFormatter < BaseFormatter attr_reader :old_line attr_reader :new_line + attr_reader :line_range def initialize(attrs) @old_line = attrs[:old_line] @new_line = attrs[:new_line] + @line_range = attrs[:line_range] super(attrs) end @@ -23,7 +25,7 @@ module Gitlab end def to_h - super.merge(old_line: old_line, new_line: new_line) + super.merge(old_line: old_line, new_line: new_line, line_range: line_range) end def line_age diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 3c265774fc6..9f8e24d8696 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -8222,6 +8222,9 @@ msgstr "" msgid "Error fetching network graph." msgstr "" +msgid "Error fetching payload data." +msgstr "" + msgid "Error fetching projects" msgstr "" @@ -8231,9 +8234,6 @@ msgstr "" msgid "Error fetching the dependency list. Please check your network connection and try again." msgstr "" -msgid "Error fetching usage ping data." -msgstr "" - msgid "Error loading branch data. Please try again." msgstr "" @@ -16342,13 +16342,13 @@ msgstr "" msgid "PrometheusService|Prometheus is being automatically managed on your clusters" msgstr "" -msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment" +msgid "PrometheusService|Select the Active checkbox to override the Auto Configuration with custom settings. If unchecked, Auto Configuration settings are used." msgstr "" -msgid "PrometheusService|Time-series monitoring service" +msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment" msgstr "" -msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters" +msgid "PrometheusService|Time-series monitoring service" msgstr "" msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below" @@ -19496,6 +19496,9 @@ msgstr "" msgid "Static Application Security Testing (SAST)" msgstr "" +msgid "StaticSiteEditor|An error occurred while submitting your changes." +msgstr "" + msgid "StaticSiteEditor|Branch could not be created." msgstr "" @@ -21861,6 +21864,9 @@ msgstr "" msgid "Try all GitLab has to offer for 30 days." msgstr "" +msgid "Try changing or removing filters." +msgstr "" + msgid "Try to fork again" msgstr "" @@ -24114,6 +24120,9 @@ msgstr "" msgid "Your request for access has been queued for review." msgstr "" +msgid "Your search didn't match any commits." +msgstr "" + msgid "Your subscription expired!" msgstr "" @@ -24236,6 +24245,9 @@ msgstr "" msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}" msgstr "" +msgid "ciReport|%{linkStartTag}Learn more about Secret Scanning %{linkEndTag}" +msgstr "" + msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}" msgstr "" @@ -24399,6 +24411,12 @@ msgstr "" msgid "ciReport|SAST" msgstr "" +msgid "ciReport|Secret scanning" +msgstr "" + +msgid "ciReport|Secret scanning detects secrets and credentials vulnerabilities in your source code." +msgstr "" + msgid "ciReport|Security scanning" msgstr "" diff --git a/package.json b/package.json index 5ddbe10df04..84283e48342 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "@gitlab/at.js": "1.5.5", "@gitlab/svgs": "1.119.0", "@gitlab/ui": "12.0.0", - "@gitlab/visual-review-tools": "1.5.1", + "@gitlab/visual-review-tools": "1.6.1", "@sentry/browser": "^5.10.2", "@sourcegraph/code-host-integration": "0.0.36", "apollo-cache-inmemory": "^1.6.3", diff --git a/spec/factories/diff_position.rb b/spec/factories/diff_position.rb index a43c5afdff4..685272acf5c 100644 --- a/spec/factories/diff_position.rb +++ b/spec/factories/diff_position.rb @@ -34,10 +34,20 @@ FactoryBot.define do position_type { 'text' } old_line { 10 } new_line { 10 } + line_range { nil } trait :added do old_line { nil } end + + trait :multi_line do + line_range do + { + start_line_code: Gitlab::Git.diff_line_code(file, 10, 10), + end_line_code: Gitlab::Git.diff_line_code(file, 12, 13) + } + end + end end factory :image_diff_position do diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index 8eb15bb6bf5..1a3da8cb373 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -348,12 +348,19 @@ describe 'Admin updates settings', :clean_gitlab_redis_shared_state, :do_not_moc it 'loads usage ping payload on click', :js do allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false) - expect(page).to have_button 'Preview payload' + page.within('#js-usage-settings') do + expected_payload_content = /(?=.*"uuid")(?=.*"hostname")/m - find('.js-usage-ping-payload-trigger').click + expect(page).not_to have_content expected_payload_content - expect(page).to have_selector '.js-usage-ping-payload' - expect(page).to have_button 'Hide payload' + click_button('Preview payload') + + wait_for_requests + + expect(page).to have_selector '.js-usage-ping-payload' + expect(page).to have_button 'Hide payload' + expect(page).to have_content expected_payload_content + end end end diff --git a/spec/features/projects/environments_pod_logs_spec.rb b/spec/features/projects/environments_pod_logs_spec.rb index 2b2327940a5..a51f121bf59 100644 --- a/spec/features/projects/environments_pod_logs_spec.rb +++ b/spec/features/projects/environments_pod_logs_spec.rb @@ -57,7 +57,9 @@ describe 'Environment > Pod Logs', :js do expect(item.text).to eq(pod_names[i]) end end - expect(page).to have_content("Dec 13 14:04:22.123Z | kube-pod | Log 1 Dec 13 14:04:23.123Z | kube-pod | Log 2 Dec 13 14:04:24.123Z | kube-pod | Log 3") + expect(page).to have_content("kube-pod | Log 1") + expect(page).to have_content("kube-pod | Log 2") + expect(page).to have_content("kube-pod | Log 3") end end end diff --git a/spec/features/static_site_editor_spec.rb b/spec/features/static_site_editor_spec.rb new file mode 100644 index 00000000000..c457002f888 --- /dev/null +++ b/spec/features/static_site_editor_spec.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Static Site Editor' do + let(:user) { create(:user) } + let(:project) { create(:project, :public, :repository) } + + before do + project.add_maintainer(user) + sign_in(user) + + visit project_show_sse_path(project, 'master/README.md') + end + + it 'renders Static Site Editor page' do + expect(page).to have_selector('#static-site-editor') + end +end diff --git a/spec/frontend/diffs/store/actions_spec.js b/spec/frontend/diffs/store/actions_spec.js index 8a1c3e56e5a..ceccce6312f 100644 --- a/spec/frontend/diffs/store/actions_spec.js +++ b/spec/frontend/diffs/store/actions_spec.js @@ -466,6 +466,7 @@ describe('DiffsStoreActions', () => { old_path: 'file2', line_code: 'ABC_1_1', position_type: 'text', + line_range: null, }, }, hash: 'ABC_123', diff --git a/spec/frontend/logs/mock_data.js b/spec/frontend/logs/mock_data.js index 537582cff5a..14c8f7a2ba2 100644 --- a/spec/frontend/logs/mock_data.js +++ b/spec/frontend/logs/mock_data.js @@ -34,91 +34,31 @@ export const mockPods = [ export const mockLogsResult = [ { timestamp: '2019-12-13T13:43:18.2760123Z', - message: '10.36.0.1 - - [16/Oct/2019:06:29:48 UTC] "GET / HTTP/1.1" 200 13', + message: 'log line 1', pod: 'foo', }, { timestamp: '2019-12-13T13:43:18.2760123Z', - message: '- -> /', + message: 'log line A', pod: 'bar', }, { timestamp: '2019-12-13T13:43:26.8420123Z', - message: '10.36.0.1 - - [16/Oct/2019:06:29:57 UTC] "GET / HTTP/1.1" 200 13', + message: 'log line 2', pod: 'foo', }, { timestamp: '2019-12-13T13:43:26.8420123Z', - message: '- -> /', - pod: 'bar', - }, - { - timestamp: '2019-12-13T13:43:28.3710123Z', - message: '10.36.0.1 - - [16/Oct/2019:06:29:58 UTC] "GET / HTTP/1.1" 200 13', - pod: 'foo', - }, - { - timestamp: '2019-12-13T13:43:28.3710123Z', - message: '- -> /', - pod: 'bar', - }, - { - timestamp: '2019-12-13T13:43:36.8860123Z', - message: '10.36.0.1 - - [16/Oct/2019:06:30:07 UTC] "GET / HTTP/1.1" 200 13', - pod: 'foo', - }, - { - timestamp: '2019-12-13T13:43:36.8860123Z', - message: '- -> /', - pod: 'bar', - }, - { - timestamp: '2019-12-13T13:43:38.4000123Z', - message: '10.36.0.1 - - [16/Oct/2019:06:30:08 UTC] "GET / HTTP/1.1" 200 13', - pod: 'foo', - }, - { - timestamp: '2019-12-13T13:43:38.4000123Z', - message: '- -> /', - pod: 'bar', - }, - { - timestamp: '2019-12-13T13:43:46.8420123Z', - message: '10.36.0.1 - - [16/Oct/2019:06:30:17 UTC] "GET / HTTP/1.1" 200 13', - pod: 'foo', - }, - { - timestamp: '2019-12-13T13:43:46.8430123Z', - message: '- -> /', - pod: 'bar', - }, - { - timestamp: '2019-12-13T13:43:48.3240123Z', - message: '10.36.0.1 - - [16/Oct/2019:06:30:18 UTC] "GET / HTTP/1.1" 200 13', - pod: 'foo', - }, - { - timestamp: '2019-12-13T13:43:48.3250123Z', - message: '- -> /', + message: 'log line B', pod: 'bar', }, ]; export const mockTrace = [ - 'Dec 13 13:43:18.276Z | foo | 10.36.0.1 - - [16/Oct/2019:06:29:48 UTC] "GET / HTTP/1.1" 200 13', - 'Dec 13 13:43:18.276Z | bar | - -> /', - 'Dec 13 13:43:26.842Z | foo | 10.36.0.1 - - [16/Oct/2019:06:29:57 UTC] "GET / HTTP/1.1" 200 13', - 'Dec 13 13:43:26.842Z | bar | - -> /', - 'Dec 13 13:43:28.371Z | foo | 10.36.0.1 - - [16/Oct/2019:06:29:58 UTC] "GET / HTTP/1.1" 200 13', - 'Dec 13 13:43:28.371Z | bar | - -> /', - 'Dec 13 13:43:36.886Z | foo | 10.36.0.1 - - [16/Oct/2019:06:30:07 UTC] "GET / HTTP/1.1" 200 13', - 'Dec 13 13:43:36.886Z | bar | - -> /', - 'Dec 13 13:43:38.400Z | foo | 10.36.0.1 - - [16/Oct/2019:06:30:08 UTC] "GET / HTTP/1.1" 200 13', - 'Dec 13 13:43:38.400Z | bar | - -> /', - 'Dec 13 13:43:46.842Z | foo | 10.36.0.1 - - [16/Oct/2019:06:30:17 UTC] "GET / HTTP/1.1" 200 13', - 'Dec 13 13:43:46.843Z | bar | - -> /', - 'Dec 13 13:43:48.324Z | foo | 10.36.0.1 - - [16/Oct/2019:06:30:18 UTC] "GET / HTTP/1.1" 200 13', - 'Dec 13 13:43:48.325Z | bar | - -> /', + 'Dec 13 13:43:18.276 | foo | log line 1', + 'Dec 13 13:43:18.276 | bar | log line A', + 'Dec 13 13:43:26.842 | foo | log line 2', + 'Dec 13 13:43:26.842 | bar | log line B', ]; export const mockResponse = { diff --git a/spec/frontend/static_site_editor/components/saved_changes_message_spec.js b/spec/frontend/static_site_editor/components/saved_changes_message_spec.js index 76ac7de5c32..cac990df40f 100644 --- a/spec/frontend/static_site_editor/components/saved_changes_message_spec.js +++ b/spec/frontend/static_site_editor/components/saved_changes_message_spec.js @@ -51,11 +51,14 @@ describe('~/static_site_editor/components/saved_changes_message.vue', () => { ${'branch'} | ${findBranchLink} | ${props.branch} ${'commit'} | ${findCommitLink} | ${props.commit} ${'merge request'} | ${findMergeRequestLink} | ${props.mergeRequest} - `('renders $desc link', ({ findEl, prop }) => { + `('renders $desc link', ({ desc, findEl, prop }) => { const el = findEl(); expect(el.exists()).toBe(true); - expect(el.attributes('href')).toBe(prop.url); expect(el.text()).toBe(prop.label); + + if (desc !== 'branch') { + expect(el.attributes('href')).toBe(prop.url); + } }); }); diff --git a/spec/frontend/static_site_editor/components/static_site_editor_spec.js b/spec/frontend/static_site_editor/components/static_site_editor_spec.js index 19a86de9cd8..14e9fe211ce 100644 --- a/spec/frontend/static_site_editor/components/static_site_editor_spec.js +++ b/spec/frontend/static_site_editor/components/static_site_editor_spec.js @@ -10,8 +10,9 @@ import EditArea from '~/static_site_editor/components/edit_area.vue'; import EditHeader from '~/static_site_editor/components/edit_header.vue'; import InvalidContentMessage from '~/static_site_editor/components/invalid_content_message.vue'; import PublishToolbar from '~/static_site_editor/components/publish_toolbar.vue'; +import SubmitChangesError from '~/static_site_editor/components/submit_changes_error.vue'; -import { sourceContent, sourceContentTitle } from '../mock_data'; +import { sourceContent, sourceContentTitle, submitChangesError } from '../mock_data'; const localVue = createLocalVue(); @@ -23,11 +24,13 @@ describe('StaticSiteEditor', () => { let loadContentActionMock; let setContentActionMock; let submitChangesActionMock; + let dismissSubmitChangesErrorActionMock; const buildStore = ({ initialState, getters } = {}) => { loadContentActionMock = jest.fn(); setContentActionMock = jest.fn(); submitChangesActionMock = jest.fn(); + dismissSubmitChangesErrorActionMock = jest.fn(); store = new Vuex.Store({ state: createState({ @@ -42,6 +45,7 @@ describe('StaticSiteEditor', () => { loadContent: loadContentActionMock, setContent: setContentActionMock, submitChanges: submitChangesActionMock, + dismissSubmitChangesError: dismissSubmitChangesErrorActionMock, }, }); }; @@ -69,6 +73,7 @@ describe('StaticSiteEditor', () => { const findInvalidContentMessage = () => wrapper.find(InvalidContentMessage); const findPublishToolbar = () => wrapper.find(PublishToolbar); const findSkeletonLoader = () => wrapper.find(GlSkeletonLoader); + const findSubmitChangesError = () => wrapper.find(SubmitChangesError); beforeEach(() => { buildStore(); @@ -145,6 +150,13 @@ describe('StaticSiteEditor', () => { expect(findSkeletonLoader().exists()).toBe(true); }); + it('does not display submit changes error when an error does not exist', () => { + buildContentLoadedStore(); + buildWrapper(); + + expect(findSubmitChangesError().exists()).toBe(false); + }); + it('sets toolbar as saving when saving changes', () => { buildContentLoadedStore({ initialState: { @@ -163,6 +175,33 @@ describe('StaticSiteEditor', () => { expect(findInvalidContentMessage().exists()).toBe(true); }); + describe('when submitting changes fail', () => { + beforeEach(() => { + buildContentLoadedStore({ + initialState: { + submitChangesError, + }, + }); + buildWrapper(); + }); + + it('displays submit changes error message', () => { + expect(findSubmitChangesError().exists()).toBe(true); + }); + + it('dispatches submitChanges action when error message emits retry event', () => { + findSubmitChangesError().vm.$emit('retry'); + + expect(submitChangesActionMock).toHaveBeenCalled(); + }); + + it('dispatches dismissSubmitChangesError action when error message emits dismiss event', () => { + findSubmitChangesError().vm.$emit('dismiss'); + + expect(dismissSubmitChangesErrorActionMock).toHaveBeenCalled(); + }); + }); + it('dispatches load content action', () => { expect(loadContentActionMock).toHaveBeenCalled(); }); diff --git a/spec/frontend/static_site_editor/components/submit_changes_error_spec.js b/spec/frontend/static_site_editor/components/submit_changes_error_spec.js new file mode 100644 index 00000000000..7af3014b338 --- /dev/null +++ b/spec/frontend/static_site_editor/components/submit_changes_error_spec.js @@ -0,0 +1,48 @@ +import { shallowMount } from '@vue/test-utils'; +import { GlButton, GlAlert } from '@gitlab/ui'; + +import SubmitChangesError from '~/static_site_editor/components/submit_changes_error.vue'; + +import { submitChangesError as error } from '../mock_data'; + +describe('Submit Changes Error', () => { + let wrapper; + + const buildWrapper = (propsData = {}) => { + wrapper = shallowMount(SubmitChangesError, { + propsData: { + ...propsData, + }, + stubs: { + GlAlert, + }, + }); + }; + + const findRetryButton = () => wrapper.find(GlButton); + const findAlert = () => wrapper.find(GlAlert); + + beforeEach(() => { + buildWrapper({ error }); + }); + + afterEach(() => { + wrapper.destroy(); + }); + + it('renders error message', () => { + expect(findAlert().text()).toContain(error); + }); + + it('emits dismiss event when alert emits dismiss event', () => { + findAlert().vm.$emit('dismiss'); + + expect(wrapper.emitted('dismiss')).toHaveLength(1); + }); + + it('emits retry event when retry button is clicked', () => { + findRetryButton().vm.$emit('click'); + + expect(wrapper.emitted('retry')).toHaveLength(1); + }); +}); diff --git a/spec/frontend/static_site_editor/store/actions_spec.js b/spec/frontend/static_site_editor/store/actions_spec.js index a9c039517b7..6b0b77f59b7 100644 --- a/spec/frontend/static_site_editor/store/actions_spec.js +++ b/spec/frontend/static_site_editor/store/actions_spec.js @@ -124,24 +124,29 @@ describe('Static Site Editor Store actions', () => { }); describe('on error', () => { + const error = new Error(submitChangesError); const expectedMutations = [ { type: mutationTypes.SUBMIT_CHANGES }, - { type: mutationTypes.SUBMIT_CHANGES_ERROR }, + { type: mutationTypes.SUBMIT_CHANGES_ERROR, payload: error.message }, ]; beforeEach(() => { - submitContentChanges.mockRejectedValueOnce(new Error(submitChangesError)); + submitContentChanges.mockRejectedValueOnce(error); }); it('dispatches receiveContentError', () => { testAction(actions.submitChanges, null, state, expectedMutations); }); + }); + }); - it('displays flash communicating error', () => { - return testAction(actions.submitChanges, null, state, expectedMutations).then(() => { - expect(createFlash).toHaveBeenCalledWith(submitChangesError); - }); - }); + describe('dismissSubmitChangesError', () => { + it('commits dismissSubmitChangesError', () => { + testAction(actions.dismissSubmitChangesError, null, state, [ + { + type: mutationTypes.DISMISS_SUBMIT_CHANGES_ERROR, + }, + ]); }); }); }); diff --git a/spec/frontend/static_site_editor/store/mutations_spec.js b/spec/frontend/static_site_editor/store/mutations_spec.js index 0b213c11a04..2441f317d90 100644 --- a/spec/frontend/static_site_editor/store/mutations_spec.js +++ b/spec/frontend/static_site_editor/store/mutations_spec.js @@ -5,6 +5,7 @@ import { sourceContentTitle as title, sourceContent as content, savedContentMeta, + submitChangesError, } from '../mock_data'; describe('Static Site Editor Store mutations', () => { @@ -16,19 +17,21 @@ describe('Static Site Editor Store mutations', () => { }); it.each` - mutation | stateProperty | payload | expectedValue - ${types.LOAD_CONTENT} | ${'isLoadingContent'} | ${undefined} | ${true} - ${types.RECEIVE_CONTENT_SUCCESS} | ${'isLoadingContent'} | ${contentLoadedPayload} | ${false} - ${types.RECEIVE_CONTENT_SUCCESS} | ${'isContentLoaded'} | ${contentLoadedPayload} | ${true} - ${types.RECEIVE_CONTENT_SUCCESS} | ${'title'} | ${contentLoadedPayload} | ${title} - ${types.RECEIVE_CONTENT_SUCCESS} | ${'content'} | ${contentLoadedPayload} | ${content} - ${types.RECEIVE_CONTENT_SUCCESS} | ${'originalContent'} | ${contentLoadedPayload} | ${content} - ${types.RECEIVE_CONTENT_ERROR} | ${'isLoadingContent'} | ${undefined} | ${false} - ${types.SET_CONTENT} | ${'content'} | ${content} | ${content} - ${types.SUBMIT_CHANGES} | ${'isSavingChanges'} | ${undefined} | ${true} - ${types.SUBMIT_CHANGES_SUCCESS} | ${'savedContentMeta'} | ${savedContentMeta} | ${savedContentMeta} - ${types.SUBMIT_CHANGES_SUCCESS} | ${'isSavingChanges'} | ${savedContentMeta} | ${false} - ${types.SUBMIT_CHANGES_ERROR} | ${'isSavingChanges'} | ${undefined} | ${false} + mutation | stateProperty | payload | expectedValue + ${types.LOAD_CONTENT} | ${'isLoadingContent'} | ${undefined} | ${true} + ${types.RECEIVE_CONTENT_SUCCESS} | ${'isLoadingContent'} | ${contentLoadedPayload} | ${false} + ${types.RECEIVE_CONTENT_SUCCESS} | ${'isContentLoaded'} | ${contentLoadedPayload} | ${true} + ${types.RECEIVE_CONTENT_SUCCESS} | ${'title'} | ${contentLoadedPayload} | ${title} + ${types.RECEIVE_CONTENT_SUCCESS} | ${'content'} | ${contentLoadedPayload} | ${content} + ${types.RECEIVE_CONTENT_SUCCESS} | ${'originalContent'} | ${contentLoadedPayload} | ${content} + ${types.RECEIVE_CONTENT_ERROR} | ${'isLoadingContent'} | ${undefined} | ${false} + ${types.SET_CONTENT} | ${'content'} | ${content} | ${content} + ${types.SUBMIT_CHANGES} | ${'isSavingChanges'} | ${undefined} | ${true} + ${types.SUBMIT_CHANGES_SUCCESS} | ${'savedContentMeta'} | ${savedContentMeta} | ${savedContentMeta} + ${types.SUBMIT_CHANGES_SUCCESS} | ${'isSavingChanges'} | ${savedContentMeta} | ${false} + ${types.SUBMIT_CHANGES_ERROR} | ${'isSavingChanges'} | ${undefined} | ${false} + ${types.SUBMIT_CHANGES_ERROR} | ${'submitChangesError'} | ${submitChangesError} | ${submitChangesError} + ${types.DISMISS_SUBMIT_CHANGES_ERROR} | ${'submitChangesError'} | ${undefined} | ${''} `( '$mutation sets $stateProperty to $expectedValue', ({ mutation, stateProperty, payload, expectedValue }) => { diff --git a/spec/lib/gitlab/diff/formatters/text_formatter_spec.rb b/spec/lib/gitlab/diff/formatters/text_formatter_spec.rb index 33d4994f5db..e275ebef2c9 100644 --- a/spec/lib/gitlab/diff/formatters/text_formatter_spec.rb +++ b/spec/lib/gitlab/diff/formatters/text_formatter_spec.rb @@ -9,7 +9,8 @@ describe Gitlab::Diff::Formatters::TextFormatter do start_sha: 456, head_sha: 789, old_path: 'old_path.txt', - new_path: 'new_path.txt' + new_path: 'new_path.txt', + line_range: nil } end diff --git a/spec/lib/gitlab/diff/position_spec.rb b/spec/lib/gitlab/diff/position_spec.rb index 4b11ff16c38..a83c0f35d92 100644 --- a/spec/lib/gitlab/diff/position_spec.rb +++ b/spec/lib/gitlab/diff/position_spec.rb @@ -28,6 +28,7 @@ describe Gitlab::Diff::Position do new_path: "files/ruby/popen.rb", old_line: nil, new_line: 14, + line_range: nil, base_sha: nil, head_sha: nil, start_sha: nil, diff --git a/spec/lib/gitlab/prometheus/adapter_spec.rb b/spec/lib/gitlab/prometheus/adapter_spec.rb index 202bf65f92b..afee95467fa 100644 --- a/spec/lib/gitlab/prometheus/adapter_spec.rb +++ b/spec/lib/gitlab/prometheus/adapter_spec.rb @@ -19,6 +19,14 @@ describe Gitlab::Prometheus::Adapter do it 'return prometheus service as prometheus adapter' do expect(subject.prometheus_adapter).to eq(prometheus_service) end + + context 'with cluster with prometheus available' do + let!(:prometheus) { create(:clusters_applications_prometheus, :installed, cluster: cluster) } + + it 'returns prometheus service' do + expect(subject.prometheus_adapter).to eq(prometheus_service) + end + end end context "prometheus service can't execute queries" do diff --git a/spec/models/diff_note_position_spec.rb b/spec/models/diff_note_position_spec.rb index dedb8a8da4d..d93e0af5526 100644 --- a/spec/models/diff_note_position_spec.rb +++ b/spec/models/diff_note_position_spec.rb @@ -40,4 +40,11 @@ describe DiffNotePosition, type: :model do expect { diff_note_position.save! }.to raise_error(ActiveRecord::RecordNotUnique) end + + it 'accepts a line_range attribute' do + diff_note_position = build(:diff_note_position) + + expect(diff_note_position).to respond_to(:line_range) + expect(diff_note_position).to respond_to(:line_range=) + end end diff --git a/spec/models/project_services/prometheus_service_spec.rb b/spec/models/project_services/prometheus_service_spec.rb index 5565d30d8c1..a85dbe3a7df 100644 --- a/spec/models/project_services/prometheus_service_spec.rb +++ b/spec/models/project_services/prometheus_service_spec.rb @@ -418,4 +418,48 @@ describe PrometheusService, :use_clean_rails_memory_store_caching do end end end + + describe '#editable?' do + it 'is editable' do + expect(service.editable?).to be(true) + end + + context 'when cluster exists with prometheus installed' do + let(:cluster) { create(:cluster, projects: [project]) } + + before do + service.update!(manual_configuration: false) + + create(:clusters_applications_prometheus, :installed, cluster: cluster) + end + + it 'remains editable' do + expect(service.editable?).to be(true) + end + end + end + + describe '#fields' do + let(:expected_fields) do + [ + { + type: 'checkbox', + name: 'manual_configuration', + title: s_('PrometheusService|Active'), + required: true + }, + { + type: 'text', + name: 'api_url', + title: 'API URL', + placeholder: s_('PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/'), + required: true + } + ] + end + + it 'returns fields' do + expect(service.fields).to eq(expected_fields) + end + end end diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb index 0272d269aa4..c1b1150c28b 100644 --- a/spec/routing/project_routing_spec.rb +++ b/spec/routing/project_routing_spec.rb @@ -838,6 +838,13 @@ describe 'project routing' do end end + describe Projects::StaticSiteEditorController, 'routing' do + it 'routes to static_site_editor#show', :aggregate_failures do + expect(get('/gitlab/gitlabhq/-/sse/master/CONTRIBUTING.md')).to route_to('projects/static_site_editor#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/CONTRIBUTING.md') + expect(get('/gitlab/gitlabhq/-/sse/master/README')).to route_to('projects/static_site_editor#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/README') + end + end + describe Projects::EnvironmentsController, 'routing' do describe 'legacy routing' do it_behaves_like 'redirecting a legacy project path', "/gitlab/gitlabhq/environments", "/gitlab/gitlabhq/-/environments" diff --git a/spec/support/shared_examples/models/diff_positionable_note_shared_examples.rb b/spec/support/shared_examples/models/diff_positionable_note_shared_examples.rb index 38a9f1fe098..aa8979603b6 100644 --- a/spec/support/shared_examples/models/diff_positionable_note_shared_examples.rb +++ b/spec/support/shared_examples/models/diff_positionable_note_shared_examples.rb @@ -13,6 +13,7 @@ RSpec.shared_examples 'a valid diff positionable note' do |factory_on_commit| new_path: "files/ruby/popen.rb", old_line: nil, new_line: 14, + line_range: nil, diff_refs: diff_refs ) end diff --git a/spec/support/shared_examples/requests/api/diff_discussions_shared_examples.rb b/spec/support/shared_examples/requests/api/diff_discussions_shared_examples.rb index 583475678f1..3d25b9076ad 100644 --- a/spec/support/shared_examples/requests/api/diff_discussions_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/diff_discussions_shared_examples.rb @@ -22,12 +22,18 @@ RSpec.shared_examples 'diff discussions API' do |parent_type, noteable_type, id_ expect(json_response['id']).to eq(diff_note.discussion_id) expect(json_response['notes'].first['body']).to eq(diff_note.note) expect(json_response['notes'].first['position']).to eq(diff_note.position.to_h.stringify_keys) + expect(json_response['notes'].first['line_range']).to eq(nil) end end describe "POST /#{parent_type}/:id/#{noteable_type}/:noteable_id/discussions" do it "creates a new diff note" do - position = diff_note.position.to_h + line_range = { + "start_line_code" => Gitlab::Git.diff_line_code(diff_note.position.file_path, 1, 1), + "end_line_code" => Gitlab::Git.diff_line_code(diff_note.position.file_path, 2, 2) + } + + position = diff_note.position.to_h.merge({ line_range: line_range }) post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions", user), params: { body: 'hi!', position: position } diff --git a/yarn.lock b/yarn.lock index 280bc27d183..f5fbd60efb0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -806,10 +806,10 @@ vue-loader "^15.4.2" vue-runtime-helpers "^1.1.2" -"@gitlab/visual-review-tools@1.5.1": - version "1.5.1" - resolved "https://registry.yarnpkg.com/@gitlab/visual-review-tools/-/visual-review-tools-1.5.1.tgz#2552927cd7a376f1f06ef3293a69fe2ffcdddb52" - integrity sha512-8d6xgK4TsLA5gucd78jzaMyginAMJ8cbu/6ghUGws84zzAEsyJsMTstyt/fA5l4toQXVxtOh90BvDzwxSjZ6hQ== +"@gitlab/visual-review-tools@1.6.1": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@gitlab/visual-review-tools/-/visual-review-tools-1.6.1.tgz#0d8f3ff9f51b05f7c80b9a107727703d48997e4e" + integrity sha512-vY8K1igwZFoEOmU0h4E7XTLlilsQ4ylPr27O01UsSe6ZTKi6oEMREsRAEpNIUgRlxUARCsf+Opp4pgSFzFkFcw== "@gitlab/vue-toasted@^1.3.0": version "1.3.0" |