Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitpod.yml12
-rw-r--r--CHANGELOG.md17
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_bundle.js8
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_table.vue16
-rw-r--r--app/assets/javascripts/content_editor/extensions/hard_break.js10
-rw-r--r--app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue9
-rw-r--r--app/assets/stylesheets/pages/clusters.scss14
-rw-r--r--app/workers/all_queues.yml2
-rw-r--r--app/workers/ci/resource_groups/assign_resource_from_resource_group_worker.rb12
-rw-r--r--config/webpack.config.js4
-rw-r--r--doc/administration/geo/replication/version_specific_updates.md20
-rw-r--r--doc/api/graphql/custom_emoji.md111
-rw-r--r--doc/api/graphql/img/custom_emoji_query_example.pngbin0 -> 178815 bytes
-rw-r--r--doc/user/markdown.md10
-rw-r--r--locale/gitlab.pot11
-rw-r--r--package.json8
-rw-r--r--spec/frontend/commit/pipelines/pipelines_table_spec.js4
-rw-r--r--spec/frontend/content_editor/extensions/hard_break_spec.js46
-rw-r--r--spec/frontend/content_editor/test_utils.js10
-rw-r--r--spec/frontend/editor/source_editor_spec.js2
-rw-r--r--spec/frontend/environment.js18
-rw-r--r--spec/frontend_integration/ide/helpers/ide_helper.js10
-rw-r--r--spec/workers/ci/resource_groups/assign_resource_from_resource_group_worker_spec.rb18
-rw-r--r--yarn.lock43
25 files changed, 360 insertions, 57 deletions
diff --git a/.gitpod.yml b/.gitpod.yml
index f6c1a60b03a..0cb0e55c373 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -78,9 +78,9 @@ ports:
vscode:
extensions:
- - rebornix.ruby@0.27.0:QyGBeRyslOfdRgOPRGm6PQ==
- - wingrunr21.vscode-ruby@0.27.0:beIqQUhLRuJ5Vao4B2Lyng==
- - karunamurti.haml@1.1.0:twCwOYt3/Ttfb3+iwblPDA==
- - octref.vetur@0.25.0:UofirBhedyhdx/jCnPeJDg==
- - dbaeumer.vscode-eslint@2.1.3:1NRvj3UKNTNwmYjptmUmIw==
- - GitLab.gitlab-workflow@3.3.0:50q1byIi4M01G9qrTCCAYQ==
+ - rebornix.ruby@0.28.0
+ - wingrunr21.vscode-ruby@0.27.0
+ - karunamurti.haml@1.3.1
+ - octref.vetur@0.34.1
+ - dbaeumer.vscode-eslint@2.1.8
+ - gitlab.gitlab-workflow@3.24.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4c334e7ffac..f834c2b04be 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,23 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 14.0.3 (2021-07-06)
+
+### Fixed (7 changes)
+
+- [Fix deploy keys not working with LFS auth check](gitlab-org/gitlab@134b244c7f59f8a20cb191bc0d2aaa43171f3d6e) ([merge request](gitlab-org/gitlab!65498))
+- [DevOps Adoption - ensure displayNamespaceId is included](gitlab-org/gitlab@1166130f1e6786a8c96735b6518241fb704047b1) ([merge request](gitlab-org/gitlab!65498)) **GitLab Enterprise Edition**
+- [Geo - Fix state value in the lfs_object_registry table](gitlab-org/gitlab@b6f30299d255949b79d149ee71ee50025ac0c8c2) ([merge request](gitlab-org/gitlab!65498)) **GitLab Enterprise Edition**
+- [Fix broken Time Tracking Reports on Issuable sidebar](gitlab-org/gitlab@da0b4a92f791a3f621ec8da8e2fbb0ad4e39d399) ([merge request](gitlab-org/gitlab!65498))
+- [Fix bug where Milestone page led to console error](gitlab-org/gitlab@179948d489ed92f5d8158c23190430e819941a29) ([merge request](gitlab-org/gitlab!65498))
+- [Fix frequent items timestamps not updated](gitlab-org/gitlab@481d4d36252dc91291afe9dacd7d48558878d27f) ([merge request](gitlab-org/gitlab!65498))
+- [Fix pages deployment storage migration](gitlab-org/gitlab@0eab6e579890c557bf97dd48dd6a2a7adaf97358) ([merge request](gitlab-org/gitlab!65498))
+
+### Changed (2 changes)
+
+- [Geo - Move migration to a pre-deployment migration](gitlab-org/gitlab@84327652855cafe36c574df798322b63d0649561) ([merge request](gitlab-org/gitlab!65498)) **GitLab Enterprise Edition**
+- [Reintroduce recursive_approach_for_all_projects default-enabled](gitlab-org/gitlab@14b3aa69cad85541ae6b845b346c80d1eaea099b) ([merge request](gitlab-org/gitlab!65498))
+
## 14.0.2 (2021-07-01)
### Added (1 change)
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index fe3e0ff8747..0d2ad188483 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-6ee267a02055a7f48871d66fae594417c4cdec9b
+b84ba4f096da54ebb6a85c14ab736474c72f1a2a
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
index 29ad6cc4125..60cfb758e14 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
+++ b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
@@ -14,14 +14,10 @@ export default () => {
if (pipelineTableViewEl) {
// Update MR and Commits tabs
pipelineTableViewEl.addEventListener('update-pipelines-count', (event) => {
- if (
- event.detail.pipelines &&
- event.detail.pipelines.count &&
- event.detail.pipelines.count.all
- ) {
+ if (event.detail.pipelineCount) {
const badge = document.querySelector('.js-pipelines-mr-count');
- badge.textContent = event.detail.pipelines.count.all;
+ badge.textContent = event.detail.pipelineCount;
}
});
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.vue b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
index 7aa8b40aef4..c145bbdf4d2 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_table.vue
+++ b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
@@ -133,15 +133,15 @@ export default {
this.store.storePagination(resp.headers);
this.setCommonData(pipelines);
- const updatePipelinesEvent = new CustomEvent('update-pipelines-count', {
- detail: {
- pipelines: resp.data,
- },
- });
+ if (resp.headers?.['x-total']) {
+ const updatePipelinesEvent = new CustomEvent('update-pipelines-count', {
+ detail: { pipelineCount: resp.headers['x-total'] },
+ });
- // notifiy to update the count in tabs
- if (this.$el.parentElement) {
- this.$el.parentElement.dispatchEvent(updatePipelinesEvent);
+ // notifiy to update the count in tabs
+ if (this.$el.parentElement) {
+ this.$el.parentElement.dispatchEvent(updatePipelinesEvent);
+ }
}
},
/**
diff --git a/app/assets/javascripts/content_editor/extensions/hard_break.js b/app/assets/javascripts/content_editor/extensions/hard_break.js
index dc1ba431151..756eefa875c 100644
--- a/app/assets/javascripts/content_editor/extensions/hard_break.js
+++ b/app/assets/javascripts/content_editor/extensions/hard_break.js
@@ -1,5 +1,13 @@
import { HardBreak } from '@tiptap/extension-hard-break';
import { defaultMarkdownSerializer } from 'prosemirror-markdown/src/to_markdown';
-export const tiptapExtension = HardBreak;
+const ExtendedHardBreak = HardBreak.extend({
+ addKeyboardShortcuts() {
+ return {
+ 'Shift-Enter': () => this.editor.commands.setHardBreak(),
+ };
+ },
+});
+
+export const tiptapExtension = ExtendedHardBreak;
export const serializer = defaultMarkdownSerializer.nodes.hard_break;
diff --git a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
index 26f6d1d683a..8771086279e 100644
--- a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
+++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
@@ -212,13 +212,20 @@ export default {
.then(({ data }) => data.body);
},
- handleFormSubmit() {
+ async handleFormSubmit(e) {
+ e.preventDefault();
+
if (this.useContentEditor) {
this.content = this.contentEditor.getSerializedContent();
this.trackFormSubmit();
}
+ // Wait until form field values are refreshed
+ await this.$nextTick();
+
+ e.target.submit();
+
this.isDirty = false;
},
diff --git a/app/assets/stylesheets/pages/clusters.scss b/app/assets/stylesheets/pages/clusters.scss
index 98074f8af29..d233adbf3d2 100644
--- a/app/assets/stylesheets/pages/clusters.scss
+++ b/app/assets/stylesheets/pages/clusters.scss
@@ -87,6 +87,20 @@
width: 145px;
}
+ .empty-state--agent {
+ .text-content {
+ @include gl-max-w-full;
+ @include media-breakpoint-up(lg) {
+ max-width: 70%;
+ }
+ }
+
+ .gl-alert-actions {
+ @include gl-mt-0;
+ @include gl-flex-wrap;
+ }
+ }
+
.top-area .nav-controls > .btn.btn-add-cluster {
margin-right: 0;
}
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index aaa6edcd0cf..c2026d01df7 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -1619,7 +1619,7 @@
:urgency: :low
:resource_boundary: :unknown
:weight: 5
- :idempotent:
+ :idempotent: true
:tags: []
- :name: pipeline_processing:pipeline_process
:worker_name: PipelineProcessWorker
diff --git a/app/workers/ci/resource_groups/assign_resource_from_resource_group_worker.rb b/app/workers/ci/resource_groups/assign_resource_from_resource_group_worker.rb
index 15ed89fd00e..ad0ed3d16f1 100644
--- a/app/workers/ci/resource_groups/assign_resource_from_resource_group_worker.rb
+++ b/app/workers/ci/resource_groups/assign_resource_from_resource_group_worker.rb
@@ -2,7 +2,10 @@
module Ci
module ResourceGroups
- class AssignResourceFromResourceGroupWorker # rubocop:disable Scalability/IdempotentWorker
+ # This worker is to assign a resource to a pipeline job from a resource group
+ # and enqueue the job to be executed by a runner.
+ # See https://docs.gitlab.com/ee/ci/yaml/#resource_group for more information.
+ class AssignResourceFromResourceGroupWorker
include ApplicationWorker
sidekiq_options retry: 3
@@ -11,6 +14,13 @@ module Ci
queue_namespace :pipeline_processing
feature_category :continuous_delivery
+ # This worker is idempotent that it produces the same result
+ # as long as the same resource group id is passed as an argument.
+ # Therefore, we can deduplicate the sidekiq jobs until the on-going
+ # assignment process has been finished.
+ idempotent!
+ deduplicate :until_executed
+
def perform(resource_group_id)
::Ci::ResourceGroup.find_by_id(resource_group_id).try do |resource_group|
Ci::ResourceGroups::AssignResourceFromResourceGroupService.new(resource_group.project, nil)
diff --git a/config/webpack.config.js b/config/webpack.config.js
index 422f60736e7..f4324ffafc7 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -398,7 +398,9 @@ module.exports = {
new VueLoaderPlugin(),
// automatically configure monaco editor web workers
- new MonacoWebpackPlugin(),
+ new MonacoWebpackPlugin({
+ globalAPI: true,
+ }),
// fix legacy jQuery plugins which depend on globals
new webpack.ProvidePlugin({
diff --git a/doc/administration/geo/replication/version_specific_updates.md b/doc/administration/geo/replication/version_specific_updates.md
index b8f847d163c..e193fc630b9 100644
--- a/doc/administration/geo/replication/version_specific_updates.md
+++ b/doc/administration/geo/replication/version_specific_updates.md
@@ -11,6 +11,26 @@ Review this page for update instructions for your version. These steps
accompany the [general steps](updating_the_geo_nodes.md#general-update-steps)
for updating Geo nodes.
+## Updating to GitLab 13.12
+
+We found an issue where [secondary nodes re-download all LFS files](https://gitlab.com/gitlab-org/gitlab/-/issues/334550) upon update. This bug:
+
+- Only applies to Geo secondary sites that have replicated LFS objects.
+- Is _not_ a data loss risk.
+- Causes churn and wasted bandwidth re-downloading all LFS objects.
+- May impact performance for GitLab installations with a large number of LFS files.
+
+If you don't have many LFS objects or can stand a bit of churn, then it is safe to let the secondary sites re-download LFS objects.
+If you do have many LFS objects, or many Geo secondary sites, or limited bandwidth, or a combination of them all, then we recommend you skip GitLab 13.12.0 through 13.12.6 and update to GitLab 13.12.7 or newer.
+
+### If you have already updated to an affected version, and the re-sync is ongoing
+
+You can manually migrate the legacy sync state to the new state column by running the following command in a [Rails console](../../operations/rails_console.md). It should take under a minute:
+
+```ruby
+Geo::LfsObjectRegistry.where(state: 0, success: true).update_all(state: 2)
+```
+
## Updating to GitLab 13.11
We found an [issue with Git clone/pull through HTTP(s)](https://gitlab.com/gitlab-org/gitlab/-/issues/330787) on Geo secondaries and on any GitLab instance if maintenance mode is enabled. This was caused by a regression in GitLab Workhorse. This is fixed in the [GitLab 13.11.4 patch release](https://about.gitlab.com/releases/2021/05/14/gitlab-13-11-4-released/). To avoid this issue, upgrade to GitLab 13.11.4 or later.
diff --git a/doc/api/graphql/custom_emoji.md b/doc/api/graphql/custom_emoji.md
new file mode 100644
index 00000000000..a4d0acda8e7
--- /dev/null
+++ b/doc/api/graphql/custom_emoji.md
@@ -0,0 +1,111 @@
+---
+stage: Plan
+group: Project Management
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Use custom emojis with GraphQL **(FREE SELF)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37911) in GitLab 13.6
+> - [Deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
+> - Enabled on GitLab.com.
+> - Recommended for production use.
+> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-custom-emoji-api). **(FREE SELF)**
+
+This in-development feature might not be available for your use. There can be
+[risks when enabling features still in development](../../user/feature_flags.md#risks-when-enabling-features-still-in-development).
+Refer to this feature's version history for more details.
+
+To use custom emoji in comments and descriptions, you can add them to a group using the GraphQL API.
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| :----------- | :------------- | :--------------------- | :------------------------------------------------------------------------ |
+| `group_path` | integer/string | **{check-circle}** Yes | ID or [URL-encoded path of the group](../index.md#namespaced-path-encoding) |
+| `name` | string | **{check-circle}** Yes | Name of the custom emoji. |
+| `file` | string | **{check-circle}** Yes | URL of the custom emoji image. |
+
+## Create a custom emoji
+
+```graphql
+mutation CreateCustomEmoji($groupPath: ID!) {
+ createCustomEmoji(input: {groupPath: $groupPath, name: "party-parrot", file: "https://cultofthepartyparrot.com/parrots/hd/parrot.gif", external: true}) {
+ clientMutationId
+ name
+ errors
+ }
+}
+```
+
+After adding custom emoji to the group, members can use it in the same way as other emoji in the comments.
+
+## Get custom emoji for a group
+
+```graphql
+query GetCustomEmoji($groupPath: ID!) {
+ group(fullPath: $groupPath) {
+ id
+ customEmoji {
+ nodes {
+ name
+ }
+ }
+ }
+}
+```
+
+## Set up the GraphiQL explorer
+
+This procedure presents a substantive example that you can copy and paste into GraphiQL
+explorer. GraphiQL explorer is available for:
+
+- GitLab.com users at [https://gitlab.com/-/graphql-explorer](https://gitlab.com/-/graphql-explorer).
+- Self-managed users at `https://gitlab.example.com/-/graphql-explorer`.
+
+1. Copy the following code excerpt:
+
+ ```graphql
+ query GetCustomEmoji {
+ group(fullPath: "gitlab-org") {
+ id
+ customEmoji {
+ nodes {
+ name,
+ url
+ }
+ }
+ }
+ }
+ ```
+
+1. Open the [GraphiQL explorer tool](https://gitlab.com/-/graphql-explorer).
+1. Paste the `query` listed above into the left window of your GraphiQL explorer tool.
+1. Click Play to get the result shown here:
+
+![GraphiQL explore custom emoji query](img/custom_emoji_query_example.png)
+
+For more information on:
+
+- GraphQL specific entities, such as Fragments and Interfaces, see the official
+ [GraphQL documentation](https://graphql.org/learn/).
+- Individual attributes, see the [GraphQL API Resources](reference/index.md).
+
+## Enable or disable custom emoji API **(FREE SELF)**
+
+Custom emoji is under development and but ready for production use. It is
+deployed behind a feature flag that is **disabled by default**.
+[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
+can enable it.
+
+To enable it:
+
+```ruby
+Feature.enable(:custom_emoji)
+```
+
+To disable it:
+
+```ruby
+Feature.disable(:custom_emoji)
+```
diff --git a/doc/api/graphql/img/custom_emoji_query_example.png b/doc/api/graphql/img/custom_emoji_query_example.png
new file mode 100644
index 00000000000..2caccd6cd10
--- /dev/null
+++ b/doc/api/graphql/img/custom_emoji_query_example.png
Binary files differ
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index 2966c35e771..fc278007463 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -412,6 +412,10 @@ A table of contents is an unordered list that links to subheadings in the docume
To add a table of contents to a Markdown file, wiki page, issue request, or merge request
description, add the `[[_TOC_]]` tag on its own line.
+NOTE:
+You can add a table of contents to issues and merge requests, but you can't add one
+to notes or comments.
+
```markdown
This is an intro sentence to my Wiki page.
@@ -507,8 +511,8 @@ This example links to `<wiki_root>/miscellaneous.md`:
GitLab Flavored Markdown renders GitLab-specific references. For example, you can reference
an issue, a commit, a team member, or even an entire project team. GitLab Flavored Markdown turns
-that reference into a link so you can navigate between them. All references to namespaces or
-projects must use lower-case characters.
+that reference into a link so you can navigate between them. All references to projects should use the
+**project slug** rather than the project name.
Additionally, GitLab Flavored Markdown recognizes certain cross-project references and also has a shorthand
version to reference other projects from the same namespace.
@@ -520,7 +524,7 @@ GitLab Flavored Markdown recognizes the following:
| specific user | `@user_name` | | |
| specific group | `@group_name` | | |
| entire team | `@all` | | |
-| project | `namespace/project>` | | |
+| project | `namespace/project` | | |
| issue | ``#123`` | `namespace/project#123` | `project#123` |
| merge request | `!123` | `namespace/project!123` | `project!123` |
| snippet | `$123` | `namespace/project$123` | `project$123` |
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index e7f8a8d3208..cd59ac3cf24 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -6958,6 +6958,9 @@ msgstr ""
msgid "ClusterAgents|Description"
msgstr ""
+msgid "ClusterAgents|Go to the repository"
+msgstr ""
+
msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
msgstr ""
@@ -6979,6 +6982,9 @@ msgstr ""
msgid "ClusterAgents|Never"
msgstr ""
+msgid "ClusterAgents|Read more about getting started"
+msgstr ""
+
msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
msgstr ""
@@ -6988,6 +6994,9 @@ msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
+msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgstr ""
+
msgid "ClusterAgents|Unknown user"
msgstr ""
@@ -32817,7 +32826,7 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations. Indexing must remain paused until the migrations are completed."
+msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
msgstr ""
msgid "There are running deployments on the environment. Please retry later."
diff --git a/package.json b/package.json
index 72338e8d712..9a8180b92ec 100644
--- a/package.json
+++ b/package.json
@@ -144,8 +144,8 @@
"mathjax": "3",
"mermaid": "^8.10.2",
"minimatch": "^3.0.4",
- "monaco-editor": "^0.20.0",
- "monaco-editor-webpack-plugin": "^1.9.1",
+ "monaco-editor": "^0.25.2",
+ "monaco-editor-webpack-plugin": "^4.0.0",
"monaco-yaml": "^2.5.1",
"mousetrap": "1.6.5",
"pdfjs-dist": "^2.0.943",
@@ -247,6 +247,8 @@
"nodemon": "^2.0.4",
"postcss": "^7.0.14",
"prettier": "2.2.1",
+ "prosemirror-schema-basic": "^1.1.2",
+ "prosemirror-test-builder": "^1.0.4",
"purgecss": "^4.0.3",
"purgecss-from-html": "^4.0.3",
"readdir-enhanced": "^2.2.4",
@@ -263,7 +265,7 @@
},
"resolutions": {
"chokidar": "^3.4.0",
- "monaco-editor": "0.20.0"
+ "monaco-editor": "0.24.0"
},
"engines": {
"node": ">=10.13.0",
diff --git a/spec/frontend/commit/pipelines/pipelines_table_spec.js b/spec/frontend/commit/pipelines/pipelines_table_spec.js
index 4bf6727af3b..1defb3d586c 100644
--- a/spec/frontend/commit/pipelines/pipelines_table_spec.js
+++ b/spec/frontend/commit/pipelines/pipelines_table_spec.js
@@ -66,7 +66,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
describe('with pipelines', () => {
beforeEach(async () => {
- mock.onGet('endpoint.json').reply(200, [pipeline]);
+ mock.onGet('endpoint.json').reply(200, [pipeline], { 'x-total': 10 });
createComponent();
@@ -110,7 +110,7 @@ describe('Pipelines table in Commits and Merge requests', () => {
document.body.appendChild(element);
element.addEventListener('update-pipelines-count', (event) => {
- expect(event.detail.pipelines).toEqual([pipeline]);
+ expect(event.detail.pipelineCount).toEqual(10);
done();
});
diff --git a/spec/frontend/content_editor/extensions/hard_break_spec.js b/spec/frontend/content_editor/extensions/hard_break_spec.js
new file mode 100644
index 00000000000..ebd58e60b0c
--- /dev/null
+++ b/spec/frontend/content_editor/extensions/hard_break_spec.js
@@ -0,0 +1,46 @@
+import { tiptapExtension as HardBreak } from '~/content_editor/extensions/hard_break';
+import { createTestEditor, createDocBuilder } from '../test_utils';
+
+describe('content_editor/extensions/hard_break', () => {
+ let tiptapEditor;
+ let eq;
+ let doc;
+ let p;
+ let hardBreak;
+
+ beforeEach(() => {
+ tiptapEditor = createTestEditor({ extensions: [HardBreak] });
+
+ ({
+ builders: { doc, p, hardBreak },
+ eq,
+ } = createDocBuilder({
+ tiptapEditor,
+ names: { hardBreak: { nodeType: HardBreak.name } },
+ }));
+ });
+
+ describe('Shift-Enter shortcut', () => {
+ it('inserts a hard break when shortcut is executed', () => {
+ const initialDoc = doc(p(''));
+ const expectedDoc = doc(p(hardBreak()));
+
+ tiptapEditor.commands.setContent(initialDoc.toJSON());
+ tiptapEditor.commands.keyboardShortcut('Shift-Enter');
+
+ expect(eq(tiptapEditor.state.doc, expectedDoc)).toBe(true);
+ });
+ });
+
+ describe('Mod-Enter shortcut', () => {
+ it('does not insert a hard break when shortcut is executed', () => {
+ const initialDoc = doc(p(''));
+ const expectedDoc = initialDoc;
+
+ tiptapEditor.commands.setContent(initialDoc.toJSON());
+ tiptapEditor.commands.keyboardShortcut('Mod-Enter');
+
+ expect(eq(tiptapEditor.state.doc, expectedDoc)).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/content_editor/test_utils.js b/spec/frontend/content_editor/test_utils.js
index e4f2754f4c0..090e1d92218 100644
--- a/spec/frontend/content_editor/test_utils.js
+++ b/spec/frontend/content_editor/test_utils.js
@@ -3,6 +3,16 @@ import { Document } from '@tiptap/extension-document';
import { Paragraph } from '@tiptap/extension-paragraph';
import { Text } from '@tiptap/extension-text';
import { Editor } from '@tiptap/vue-2';
+import { builders, eq } from 'prosemirror-test-builder';
+
+export const createDocBuilder = ({ tiptapEditor, names = {} }) => {
+ const docBuilders = builders(tiptapEditor.schema, {
+ p: { nodeType: 'paragraph' },
+ ...names,
+ });
+
+ return { eq, builders: docBuilders };
+};
/**
* Creates an instance of the Tiptap Editor class
diff --git a/spec/frontend/editor/source_editor_spec.js b/spec/frontend/editor/source_editor_spec.js
index cf3e2c025e4..d87d373c952 100644
--- a/spec/frontend/editor/source_editor_spec.js
+++ b/spec/frontend/editor/source_editor_spec.js
@@ -246,7 +246,7 @@ describe('Base editor', () => {
let editorEl2;
let inst1;
let inst2;
- const readOnlyIndex = '68'; // readOnly option has the internal index of 68 in the editor's options
+ const readOnlyIndex = '78'; // readOnly option has the internal index of 78 in the editor's options
beforeEach(() => {
setFixtures('<div id="editor1"></div><div id="editor2"></div>');
diff --git a/spec/frontend/environment.js b/spec/frontend/environment.js
index d1bc11538a3..9cebe2d1e01 100644
--- a/spec/frontend/environment.js
+++ b/spec/frontend/environment.js
@@ -67,6 +67,24 @@ class CustomEnvironment extends JSDOMEnvironment {
getEntriesByName: () => [],
});
+ //
+ // Monaco-related environment variables
+ //
+ this.global.MonacoEnvironment = { globalAPI: true };
+ Object.defineProperty(this.global, 'matchMedia', {
+ writable: true,
+ value: (query) => ({
+ matches: false,
+ media: query,
+ onchange: null,
+ addListener: () => null, // deprecated
+ removeListener: () => null, // deprecated
+ addEventListener: () => null,
+ removeEventListener: () => null,
+ dispatchEvent: () => null,
+ }),
+ });
+
this.global.PerformanceObserver = class {
/* eslint-disable no-useless-constructor, no-unused-vars, no-empty-function, class-methods-use-this */
constructor(callback) {}
diff --git a/spec/frontend_integration/ide/helpers/ide_helper.js b/spec/frontend_integration/ide/helpers/ide_helper.js
index 6c09b44d891..56b2e298aa3 100644
--- a/spec/frontend_integration/ide/helpers/ide_helper.js
+++ b/spec/frontend_integration/ide/helpers/ide_helper.js
@@ -7,6 +7,7 @@ import {
screen,
findByText,
} from '@testing-library/dom';
+import { editor as monacoEditor } from 'monaco-editor';
const isFolderRowOpen = (row) => row.matches('.folder.is-open');
@@ -23,7 +24,10 @@ export const switchLeftSidebarTab = (name) => {
export const getStatusBar = () => document.querySelector('.ide-status-bar');
export const waitForMonacoEditor = () =>
- new Promise((resolve) => window.monaco.editor.onDidCreateEditor(resolve));
+ new Promise((resolve) => monacoEditor.onDidCreateEditor(resolve));
+
+export const waitForEditorDispose = (instance) =>
+ new Promise((resolve) => instance.onDidDispose(resolve));
export const waitForEditorModelChange = (instance) =>
new Promise((resolve) => instance.onDidChangeModel(resolve));
@@ -38,14 +42,14 @@ export const findAndSetEditorValue = async (value) => {
const editor = await findMonacoEditor();
const uri = editor.getAttribute('data-uri');
- window.monaco.editor.getModel(uri).setValue(value);
+ monacoEditor.getModel(uri).setValue(value);
};
export const getEditorValue = async () => {
const editor = await findMonacoEditor();
const uri = editor.getAttribute('data-uri');
- return window.monaco.editor.getModel(uri).getValue();
+ return monacoEditor.getModel(uri).getValue();
};
const findTreeBody = () => screen.findByTestId('ide-tree-body');
diff --git a/spec/workers/ci/resource_groups/assign_resource_from_resource_group_worker_spec.rb b/spec/workers/ci/resource_groups/assign_resource_from_resource_group_worker_spec.rb
index f9914a7cecb..650be1e84a9 100644
--- a/spec/workers/ci/resource_groups/assign_resource_from_resource_group_worker_spec.rb
+++ b/spec/workers/ci/resource_groups/assign_resource_from_resource_group_worker_spec.rb
@@ -5,15 +5,23 @@ require 'spec_helper'
RSpec.describe Ci::ResourceGroups::AssignResourceFromResourceGroupWorker do
let(:worker) { described_class.new }
+ it 'has the `until_executed` deduplicate strategy' do
+ expect(described_class.get_deduplicate_strategy).to eq(:until_executed)
+ end
+
describe '#perform' do
subject { worker.perform(resource_group_id) }
- context 'when resource group exists' do
- let(:resource_group) { create(:ci_resource_group) }
- let(:resource_group_id) { resource_group.id }
+ let(:resource_group) { create(:ci_resource_group) }
+ let(:resource_group_id) { resource_group.id }
+ include_examples 'an idempotent worker' do
+ let(:job_args) { [resource_group_id] }
+ end
+
+ context 'when resource group exists' do
it 'executes AssignResourceFromResourceGroupService' do
- expect_next_instance_of(Ci::ResourceGroups::AssignResourceFromResourceGroupService, resource_group.project, nil) do |service|
+ expect_next_instances_of(Ci::ResourceGroups::AssignResourceFromResourceGroupService, 2, resource_group.project, nil) do |service|
expect(service).to receive(:execute).with(resource_group)
end
@@ -22,7 +30,7 @@ RSpec.describe Ci::ResourceGroups::AssignResourceFromResourceGroupWorker do
end
context 'when build does not exist' do
- let(:resource_group_id) { 123 }
+ let(:resource_group_id) { non_existing_record_id }
it 'does not execute AssignResourceFromResourceGroupService' do
expect(Ci::ResourceGroups::AssignResourceFromResourceGroupService).not_to receive(:new)
diff --git a/yarn.lock b/yarn.lock
index 04a00f24d95..d5af76e8829 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8560,17 +8560,22 @@ moment-mini@^2.22.1:
resolved "https://registry.yarnpkg.com/moment-mini/-/moment-mini-2.22.1.tgz#bc32d73e43a4505070be6b53494b17623183420d"
integrity sha512-OUCkHOz7ehtNMYuZjNciXUfwTuz8vmF1MTbAy59ebf+ZBYZO5/tZKuChVWCX+uDo+4idJBpGltNfV8st+HwsGw==
-monaco-editor-webpack-plugin@^1.9.1:
- version "1.9.1"
- resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-1.9.1.tgz#eb4bbb1c5e5bfb554541c1ae1542e74c2a9f43fd"
- integrity sha512-x7fx1w3i/uwZERIgztHAAK3VQMsL8+ku0lFXXbO81hKDg8IieACqjGEa2mqEueg0c/fX+wd0oI+75wB19KJAsA==
+monaco-editor-webpack-plugin@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-4.0.0.tgz#95be3f48f4220999b909266a9997727f0deab947"
+ integrity sha512-4BT9XDRQXraMQjxEUjR+uuubRe3RIPkvVoGw8zwWG++s7wq6TAiXaSOMdkdS9TrjCREgSnygCOlVzY6MS8RPuA==
dependencies:
- loader-utils "^1.2.3"
+ loader-utils "^2.0.0"
-monaco-editor@0.20.0, monaco-editor@^0.20.0:
- version "0.20.0"
- resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.20.0.tgz#5d5009343a550124426cb4d965a4d27a348b4dea"
- integrity sha512-hkvf4EtPJRMQlPC3UbMoRs0vTAFAYdzFQ+gpMb8A+9znae1c43q8Mab9iVsgTcg/4PNiLGGn3SlDIa8uvK1FIQ==
+monaco-editor@0.24.0:
+ version "0.24.0"
+ resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.24.0.tgz#990b55096bcc95d08d8d28e55264c6eb17707269"
+ integrity sha512-o1f0Lz6ABFNTtnEqqqvlY9qzNx24rQZx1RgYNQ8SkWkE+Ka63keHH/RqxQ4QhN4fs/UYOnvAtEUZsPrzccH++A==
+
+monaco-editor@^0.25.2:
+ version "0.25.2"
+ resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.25.2.tgz#119e2b15bbd968a1a99c03cac9c329316d7c37e9"
+ integrity sha512-5iylzSJevCnzJn9UVsW8yOZ3yHjmAs4TfvH3zsbftKiFKmHG0xirGN6DK9Kk04VSWxYCZZAIafYJoNJJMAU1KA==
monaco-yaml@^2.5.1:
version "2.5.1"
@@ -9726,13 +9731,20 @@ prosemirror-markdown@^1.5.1:
markdown-it "^10.0.0"
prosemirror-model "^1.0.0"
-prosemirror-model@^1.0.0, prosemirror-model@^1.1.0, prosemirror-model@^1.13.1, prosemirror-model@^1.13.3, prosemirror-model@^1.14.1, prosemirror-model@^1.8.1:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.14.1.tgz#d784c67f95a5d66b853e82ff9a87a50353ef9cd5"
- integrity sha512-vZcbI+24VloFefKZkDnMaEpipL/vSKKPdFiik4KOnTzq3e6AO7+CAOixZ2G/SsfRaYC965XvnOIEbhIQdgki7w==
+prosemirror-model@^1.0.0, prosemirror-model@^1.1.0, prosemirror-model@^1.13.1, prosemirror-model@^1.13.3, prosemirror-model@^1.14.1, prosemirror-model@^1.2.0, prosemirror-model@^1.8.1:
+ version "1.14.2"
+ resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.14.2.tgz#4e8c39cfff4e097631af4495e125d9a8a9773116"
+ integrity sha512-TwkACyEiSi8FJiRhg2ffbzmQRy5DR+aTwAr7trNQNZL24HJR8ouxy4qCkG99PnWK0xZ0AjSMtPXSU6hnxAiP7Q==
dependencies:
orderedmap "^1.1.0"
+prosemirror-schema-basic@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/prosemirror-schema-basic/-/prosemirror-schema-basic-1.1.2.tgz#4bde5c339c845e0d08ec8fe473064e372ca51ae3"
+ integrity sha512-G4q8WflNsR1Q33QAV4MQO0xWrHLOJ+BQcKswGXMy626wlQj6c/1n1v4eC9ns+h2y1r/fJHZEgSZnsNhm9lbrDw==
+ dependencies:
+ prosemirror-model "^1.2.0"
+
prosemirror-schema-list@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/prosemirror-schema-list/-/prosemirror-schema-list-1.1.4.tgz#471f9caf2d2bed93641d2e490434c0d2d4330df1"
@@ -9760,6 +9772,11 @@ prosemirror-tables@^1.1.1:
prosemirror-transform "^1.2.1"
prosemirror-view "^1.13.3"
+prosemirror-test-builder@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/prosemirror-test-builder/-/prosemirror-test-builder-1.0.4.tgz#68d1d1cedcd90cc2fdd976d736ce87b7a5f1e873"
+ integrity sha512-d5ZwYcf+vd1YI0tgoB7UZ2B2iwb4jmxLGzkHz6ZbkAmPwAY48WpS1frv9BofC2m/MRIMp5SERhISNIANYPsVTg==
+
prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transform@^1.2.1, prosemirror-transform@^1.2.8, prosemirror-transform@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/prosemirror-transform/-/prosemirror-transform-1.3.2.tgz#5620ebe7379e6fae4f34ecc881886cb22ce96579"