From dce57587960022ca3582bedfc5bcf356893fe603 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Mon, 28 Sep 2020 18:09:40 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- GITALY_SERVER_VERSION | 2 +- GITLAB_WORKHORSE_VERSION | 2 +- app/assets/javascripts/awards_handler.js | 2 +- .../components/triggers_list.vue | 143 +++++++ .../ci_settings_pipeline_triggers/index.js | 36 ++ .../components/delete_button.vue | 2 +- .../components/list/item.vue | 1 + .../design_management/pages/index.vue | 4 + app/assets/javascripts/emoji/index.js | 109 +++-- .../commit_sidebar/message_field.vue | 18 +- app/assets/javascripts/layout_nav.js | 9 + .../projects/settings/ci_cd/show/index.js | 3 + .../components/pipeline_new_form.vue | 10 +- .../pipelines_list/nav_controls.vue | 1 + .../components/labels/sidebar_labels.vue | 1 + .../states/mr_widget_auto_merge_failed.vue | 14 +- .../labels_select_vue/dropdown_contents.vue | 1 + .../dropdown_contents_labels_view.vue | 6 +- .../labels_select_vue/dropdown_value.vue | 2 + .../javascripts/whats_new/components/app.vue | 10 +- app/assets/javascripts/whats_new/index.js | 1 + .../javascripts/whats_new/store/actions.js | 6 +- .../stylesheets/components/whats_new.scss | 25 +- .../stylesheets/pages/settings_ci_cd.scss | 4 + .../projects/settings/ci_cd_controller.rb | 6 + .../concerns/issue_resolver_arguments.rb | 3 + app/helpers/whats_new_helper.rb | 22 + app/serializers/ci/trigger_entity.rb | 42 ++ app/serializers/ci/trigger_serializer.rb | 7 + app/services/quick_actions/target_service.rb | 4 + app/views/layouts/header/_default.html.haml | 2 +- .../projects/pages_domains/_form.html.haml | 3 +- .../projects/pipelines/_with_tabs.html.haml | 2 +- app/views/projects/triggers/_index.html.haml | 35 +- .../projects/triggers/_trigger.html.haml | 4 +- app/views/shared/issuable/_sidebar.html.haml | 10 +- app/workers/git_garbage_collect_worker.rb | 1 - .../233693-remove-bootstrap-pages.yml | 5 + ...ove-cleanup-lfs-during-gc-feature-flag.yml | 5 + ...3-add-multiple-assignee-filter-graphql.yml | 5 + ...s-migration-helper-opclass-replication.yml | 6 + .../43499-update-commit-message-popover.yml | 5 + .../alipniagov-update-wh-version.yml | 5 + .../unreleased/fix-retry-job-button-422.yml | 5 + ...dd-approval-rules-approvers-usage-ping.yml | 5 + .../unreleased/improve-emoji-support.yml | 5 + config/application.rb | 38 +- .../api_kaminari_count_with_limit.yml | 7 - .../development/ci_key_autocomplete.yml | 6 +- ... ci_pipeline_triggers_settings_vue_ui.yml} | 8 +- .../development/dag_pipeline_tab.yml | 6 +- .../development/deploy_from_footer.yml | 6 +- .../development/metrics_dashboard.yml | 6 +- .../release_evidence_collection.yml | 6 +- .../ops/api_kaminari_count_with_limit.yml | 7 + data/whats_new/202008180001_12_10.yml | 4 +- ...4_add_indices_to_approval_project_rules.rb | 25 ++ db/schema_migrations/20200915134004 | 1 + db/structure.sql | 4 + .../geo/replication/datatypes.md | 4 +- doc/administration/housekeeping.md | 3 + .../graphql/reference/gitlab_schema.graphql | 138 +++++- doc/api/graphql/reference/gitlab_schema.json | 394 +++++++++++++++++- doc/api/graphql/reference/index.md | 19 +- .../feature_flags_development/index.md | 12 +- .../documentation/feature_flags.md | 4 +- doc/development/geo/framework.md | 8 +- doc/development/integrations/secure.md | 6 +- doc/development/telemetry/usage_ping.md | 11 +- doc/user/analytics/value_stream_analytics.md | 20 +- .../dependency_scanning/index.md | 8 + doc/user/group/saml_sso/scim_setup.md | 18 +- doc/user/permissions.md | 4 +- doc/user/project/import/bitbucket_server.md | 7 +- .../reducing_the_repo_size_using_git.md | 1 + geo_architecture.png | Bin 0 -> 226694 bytes lib/gitlab/ci/trace/metrics.rb | 2 +- lib/gitlab/database/batch_count.rb | 4 +- lib/gitlab/database/migration_helpers.rb | 2 +- lib/gitlab/pagination/offset_pagination.rb | 2 +- lib/gitlab/utils/usage_data.rb | 4 +- locale/gitlab.pot | 33 ++ package.json | 2 +- qa/qa.rb | 2 + qa/qa/page/component/design_management.rb | 29 +- qa/qa/page/component/issuable/sidebar.rb | 33 +- qa/qa/page/project/pipeline/index.rb | 12 + qa/qa/page/project/pipeline/new.rb | 19 + qa/qa/resource/design.rb | 31 ++ .../archive_design_content_spec.rb | 51 +++ .../create_merge_request_spec.rb | 2 +- .../run_pipeline_via_web_only_spec.rb | 65 +++ qa/spec/fixtures/tanuki.jpg | Bin 0 -> 84616 bytes qa/spec/fixtures/values.png | Bin 0 -> 122101 bytes spec/factories/ci/pipelines.rb | 2 +- spec/factories/merge_request_diffs.rb | 8 +- spec/factories/merge_requests.rb | 8 + spec/factories/services.rb | 6 +- spec/features/triggers_spec.rb | 220 +++++----- .../api/schemas/entities/trigger.json | 39 ++ spec/frontend/awards_handler_spec.js | 14 + .../components/triggers_list_spec.js | 102 +++++ .../mock_data.js | 30 ++ .../list/__snapshots__/item_spec.js.snap | 2 + .../pages/__snapshots__/index_spec.js.snap | 10 + spec/frontend/emoji/emoji_spec.js | 37 +- spec/frontend/fixtures/releases.rb | 88 ++++ .../mr_widget_auto_merge_failed_spec.js | 14 +- .../frontend/whats_new/components/app_spec.js | 5 +- spec/frontend/whats_new/store/actions_spec.js | 7 +- .../graphql/resolvers/issues_resolver_spec.rb | 7 + spec/helpers/whats_new_helper_spec.rb | 46 ++ spec/lib/gitlab/ci/trace/metrics_spec.rb | 18 + .../gitlab/database/migration_helpers_spec.rb | 60 ++- spec/serializers/ci/trigger_entity_spec.rb | 70 ++++ .../serializers/ci/trigger_serializer_spec.rb | 15 + .../git_garbage_collect_worker_spec.rb | 65 +-- yarn.lock | 8 +- 118 files changed, 2165 insertions(+), 389 deletions(-) create mode 100644 app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue create mode 100644 app/assets/javascripts/ci_settings_pipeline_triggers/index.js create mode 100644 app/serializers/ci/trigger_entity.rb create mode 100644 app/serializers/ci/trigger_serializer.rb create mode 100644 changelogs/unreleased/233693-remove-bootstrap-pages.yml create mode 100644 changelogs/unreleased/238605-remove-cleanup-lfs-during-gc-feature-flag.yml create mode 100644 changelogs/unreleased/254903-add-multiple-assignee-filter-graphql.yml create mode 100644 changelogs/unreleased/256094-fix-copy-indexes-migration-helper-opclass-replication.yml create mode 100644 changelogs/unreleased/43499-update-commit-message-popover.yml create mode 100644 changelogs/unreleased/alipniagov-update-wh-version.yml create mode 100644 changelogs/unreleased/fix-retry-job-button-422.yml create mode 100644 changelogs/unreleased/id-add-approval-rules-approvers-usage-ping.yml create mode 100644 changelogs/unreleased/improve-emoji-support.yml delete mode 100644 config/feature_flags/development/api_kaminari_count_with_limit.yml rename config/feature_flags/development/{cleanup_lfs_during_gc.yml => ci_pipeline_triggers_settings_vue_ui.yml} (62%) create mode 100644 config/feature_flags/ops/api_kaminari_count_with_limit.yml create mode 100644 db/migrate/20200915134004_add_indices_to_approval_project_rules.rb create mode 100644 db/schema_migrations/20200915134004 create mode 100644 geo_architecture.png create mode 100644 qa/qa/page/project/pipeline/new.rb create mode 100644 qa/qa/resource/design.rb create mode 100644 qa/qa/specs/features/browser_ui/3_create/design_management/archive_design_content_spec.rb create mode 100644 qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb create mode 100644 qa/spec/fixtures/tanuki.jpg create mode 100644 qa/spec/fixtures/values.png create mode 100644 spec/fixtures/api/schemas/entities/trigger.json create mode 100644 spec/frontend/ci_settings_pipeline_triggers/components/triggers_list_spec.js create mode 100644 spec/frontend/ci_settings_pipeline_triggers/mock_data.js create mode 100644 spec/frontend/fixtures/releases.rb create mode 100644 spec/lib/gitlab/ci/trace/metrics_spec.rb create mode 100644 spec/serializers/ci/trigger_entity_spec.rb create mode 100644 spec/serializers/ci/trigger_serializer_spec.rb diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 57baa84c1b7..689ca77dae3 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -9096b269b6abfa8cbe8cf6c48a03e3bec93d47ae +69c5d9bad86e9402d5e2b0d7c09e88fd5603b572 diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION index 8cf933256d4..7b7e68c163e 100644 --- a/GITLAB_WORKHORSE_VERSION +++ b/GITLAB_WORKHORSE_VERSION @@ -1 +1 @@ -8.47.0 +8.48.0 diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js index 6354ad323e4..bc69c02e21e 100644 --- a/app/assets/javascripts/awards_handler.js +++ b/app/assets/javascripts/awards_handler.js @@ -572,7 +572,7 @@ export class AwardsHandler { } findMatchingEmojiElements(query) { - const emojiMatches = this.emoji.queryEmojiNames(query); + const emojiMatches = this.emoji.searchEmoji(query).map(({ name }) => name); const $emojiElements = $('.emoji-menu-list:not(.frequent-emojis) [data-name]'); const $matchingElements = $emojiElements.filter( (i, elm) => emojiMatches.indexOf(elm.dataset.name) >= 0, diff --git a/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue b/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue new file mode 100644 index 00000000000..ad07052a298 --- /dev/null +++ b/app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue @@ -0,0 +1,143 @@ + + + diff --git a/app/assets/javascripts/ci_settings_pipeline_triggers/index.js b/app/assets/javascripts/ci_settings_pipeline_triggers/index.js new file mode 100644 index 00000000000..182d5ca5ffb --- /dev/null +++ b/app/assets/javascripts/ci_settings_pipeline_triggers/index.js @@ -0,0 +1,36 @@ +import Vue from 'vue'; +import TriggersList from './components/triggers_list.vue'; +import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; + +const parseJsonArray = triggers => { + try { + return convertObjectPropsToCamelCase(JSON.parse(triggers), { deep: true }); + } catch { + return []; + } +}; + +export default (containerId = 'js-ci-pipeline-triggers-list') => { + const containerEl = document.getElementById(containerId); + + // Note: Remove this check when FF `ci_pipeline_triggers_settings_vue_ui` is removed. + if (!containerEl) { + return null; + } + + const triggers = parseJsonArray(containerEl.dataset.triggers); + + return new Vue({ + el: containerEl, + components: { + TriggersList, + }, + render(h) { + return h(TriggersList, { + props: { + triggers, + }, + }); + }, + }); +}; diff --git a/app/assets/javascripts/design_management/components/delete_button.vue b/app/assets/javascripts/design_management/components/delete_button.vue index 970197ef41b..273fa3f6be2 100644 --- a/app/assets/javascripts/design_management/components/delete_button.vue +++ b/app/assets/javascripts/design_management/components/delete_button.vue @@ -63,7 +63,7 @@ export default { title: s__('DesignManagement|Are you sure you want to archive the selected designs?'), actionPrimary: { text: s__('DesignManagement|Archive designs'), - attributes: { variant: 'warning' }, + attributes: { variant: 'warning', 'data-qa-selector': 'confirm_archiving_button' }, }, actionCancel: { text: __('Cancel'), diff --git a/app/assets/javascripts/design_management/components/list/item.vue b/app/assets/javascripts/design_management/components/list/item.vue index 36ea812d92e..b179b1b5e79 100644 --- a/app/assets/javascripts/design_management/components/list/item.vue +++ b/app/assets/javascripts/design_management/components/list/item.vue @@ -149,6 +149,7 @@ export default { :alt="filename" class="gl-display-block gl-mx-auto gl-max-w-full mh-100 design-img" data-qa-selector="design_image" + :data-qa-filename="filename" @load="onImageLoad" @error="onImageError" /> diff --git a/app/assets/javascripts/design_management/pages/index.vue b/app/assets/javascripts/design_management/pages/index.vue index 49476b481bd..7bf9454240b 100644 --- a/app/assets/javascripts/design_management/pages/index.vue +++ b/app/assets/javascripts/design_management/pages/index.vue @@ -351,6 +351,7 @@ export default { button-category="secondary" button-class="gl-mr-3" button-size="small" + data-qa-selector="archive_button" :loading="loading" :has-selected-designs="hasSelectedDesigns" @deleteSelectedDesigns="mutate()" @@ -417,6 +418,8 @@ export default { :checked="isDesignSelected(design.filename)" type="checkbox" class="design-checkbox" + data-qa-selector="design_checkbox" + :data-qa-design="design.filename" @change="changeSelectedDesigns(design.filename)" /> @@ -426,6 +429,7 @@ export default { :is-dragging-design="isDraggingDesign" :class="{ 'design-list-item design-list-item-new': !isDesignListEmpty }" :has-designs="hasDesigns" + data-qa-selector="design_dropzone_content" @change="onUploadDesign" /> diff --git a/app/assets/javascripts/emoji/index.js b/app/assets/javascripts/emoji/index.js index 41f6524de79..1bdc7b3a8b5 100644 --- a/app/assets/javascripts/emoji/index.js +++ b/app/assets/javascripts/emoji/index.js @@ -2,53 +2,57 @@ import { uniq } from 'lodash'; import fuzzaldrinPlus from 'fuzzaldrin-plus'; import emojiAliases from 'emojis/aliases.json'; import axios from '../lib/utils/axios_utils'; - import AccessorUtilities from '../lib/utils/accessor'; let emojiMap = null; -let emojiPromise = null; let validEmojiNames = null; export const EMOJI_VERSION = '1'; const isLocalStorageAvailable = AccessorUtilities.isLocalStorageAccessSafe(); -export function initEmojiMap() { - emojiPromise = - emojiPromise || - new Promise((resolve, reject) => { - if (emojiMap) { - resolve(emojiMap); - } else if ( - isLocalStorageAvailable && - window.localStorage.getItem('gl-emoji-map-version') === EMOJI_VERSION && - window.localStorage.getItem('gl-emoji-map') - ) { - emojiMap = JSON.parse(window.localStorage.getItem('gl-emoji-map')); - validEmojiNames = [...Object.keys(emojiMap), ...Object.keys(emojiAliases)]; - resolve(emojiMap); - } else { - // We load the JSON file direct from the server - // because it can't be loaded from a CDN due to - // cross domain problems with JSON - axios - .get(`${gon.relative_url_root || ''}/-/emojis/${EMOJI_VERSION}/emojis.json`) - .then(({ data }) => { - emojiMap = data; - validEmojiNames = [...Object.keys(emojiMap), ...Object.keys(emojiAliases)]; - resolve(emojiMap); - if (isLocalStorageAvailable) { - window.localStorage.setItem('gl-emoji-map-version', EMOJI_VERSION); - window.localStorage.setItem('gl-emoji-map', JSON.stringify(emojiMap)); - } - }) - .catch(err => { - reject(err); - }); - } - }); +async function loadEmoji() { + if ( + isLocalStorageAvailable && + window.localStorage.getItem('gl-emoji-map-version') === EMOJI_VERSION && + window.localStorage.getItem('gl-emoji-map') + ) { + return JSON.parse(window.localStorage.getItem('gl-emoji-map')); + } - return emojiPromise; + // We load the JSON file direct from the server + // because it can't be loaded from a CDN due to + // cross domain problems with JSON + const { data } = await axios.get( + `${gon.relative_url_root || ''}/-/emojis/${EMOJI_VERSION}/emojis.json`, + ); + window.localStorage.setItem('gl-emoji-map-version', EMOJI_VERSION); + window.localStorage.setItem('gl-emoji-map', JSON.stringify(data)); + return data; +} + +async function prepareEmojiMap() { + emojiMap = await loadEmoji(); + + validEmojiNames = [...Object.keys(emojiMap), ...Object.keys(emojiAliases)]; + + Object.keys(emojiMap).forEach(name => { + emojiMap[name].aliases = []; + emojiMap[name].name = name; + }); + Object.entries(emojiAliases).forEach(([alias, name]) => { + // This check, `if (name in emojiMap)` is necessary during testing. In + // production, it shouldn't be necessary, because at no point should there + // be an entry in aliases.json with no corresponding entry in emojis.json. + // However, during testing, the endpoint for emojis.json is mocked with a + // small dataset, whereas aliases.json is always `import`ed directly. + if (name in emojiMap) emojiMap[name].aliases.push(alias); + }); +} + +export function initEmojiMap() { + initEmojiMap.promise = initEmojiMap.promise || prepareEmojiMap(); + return initEmojiMap.promise; } export function normalizeEmojiName(name) { @@ -77,6 +81,37 @@ export function queryEmojiNames(filter) { return uniq(matches.map(name => normalizeEmojiName(name))); } +/** + * Searches emoji by name, alias, description, and unicode value and returns an + * array of matches. + * + * Note: `initEmojiMap` must have been called and completed before this method + * can safely be called. + * + * @param {String} query The search query + * @returns {Object[]} A list of emoji that match the query + */ +export function searchEmoji(query) { + if (!emojiMap) + // eslint-disable-next-line @gitlab/require-i18n-strings + throw new Error('The emoji map is uninitialized or initialization has not completed'); + + const matches = s => fuzzaldrinPlus.score(s, query) > 0; + + // Search emoji + return Object.values(emojiMap).filter( + emoji => + // by name + matches(emoji.name) || + // by alias + emoji.aliases.some(matches) || + // by description + matches(emoji.d) || + // by unicode value + query === emoji.e, + ); +} + let emojiCategoryMap; export function getEmojiCategoryMap() { if (!emojiCategoryMap) { diff --git a/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue b/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue index 2787b10a48b..5b392470e41 100644 --- a/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue +++ b/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue @@ -1,5 +1,5 @@