summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gemfile5
-rw-r--r--Gemfile.lock13
-rw-r--r--Gemfile.rails5.lock13
-rw-r--r--app/assets/javascripts/diffs/components/app.vue9
-rw-r--r--app/assets/javascripts/diffs/store/actions.js1
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue9
-rw-r--r--app/assets/javascripts/notes/components/note_body.vue12
-rw-r--r--app/assets/javascripts/notes/components/noteable_note.vue1
-rw-r--r--app/assets/javascripts/notes/components/notes_app.vue2
-rw-r--r--app/assets/javascripts/notes/stores/actions.js19
-rw-r--r--app/models/project.rb1
-rw-r--r--app/models/project_services/discord_service.rb57
-rw-r--r--app/models/service.rb1
-rw-r--r--changelogs/unreleased/blackst0ne-add-discord-service.yml5
-rw-r--r--changelogs/unreleased/discussion-perf-improvement.yml5
-rw-r--r--danger/documentation/Dangerfile29
-rw-r--r--doc/administration/git_protocol.md4
-rw-r--r--doc/api/services.md36
-rw-r--r--doc/development/documentation/index.md503
-rw-r--r--doc/development/documentation/styleguide.md245
-rw-r--r--doc/user/markdown.md30
-rw-r--r--doc/user/project/import/manifest.md10
-rw-r--r--doc/user/project/integrations/discord_notifications.md29
-rw-r--r--doc/user/project/integrations/project_services.md1
-rw-r--r--lib/api/services.rb9
-rwxr-xr-xscripts/review_apps/review-apps.sh1
-rw-r--r--spec/features/issues/user_views_issue_spec.rb6
-rw-r--r--spec/javascripts/notes/stores/actions_spec.js3
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml1
-rw-r--r--spec/models/project_services/discord_service_spec.rb11
-rw-r--r--spec/models/project_services/hangouts_chat_service_spec.rb249
-rw-r--r--spec/models/project_spec.rb1
-rw-r--r--spec/support/shared_examples/models/chat_service_spec.rb242
33 files changed, 935 insertions, 628 deletions
diff --git a/Gemfile b/Gemfile
index c7efa790cfd..80949178ea6 100644
--- a/Gemfile
+++ b/Gemfile
@@ -124,7 +124,7 @@ gem 'seed-fu', '~> 2.3.7'
# Markdown and HTML processing
gem 'html-pipeline', '~> 2.8'
gem 'deckar01-task_list', '2.0.0'
-gem 'gitlab-markup', '~> 1.6.4'
+gem 'gitlab-markup', '~> 1.6.5'
gem 'github-markup', '~> 1.7.0', require: 'github/markup'
gem 'redcarpet', '~> 3.4'
gem 'commonmarker', '~> 0.17'
@@ -204,6 +204,9 @@ gem 'redis-rails', '~> 5.0.2'
gem 'redis', '~> 3.2'
gem 'connection_pool', '~> 2.0'
+# Discord integration
+gem 'discordrb-webhooks-blackst0ne', '~> 3.3', require: false
+
# HipChat integration
gem 'hipchat', '~> 1.5.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index 50e3ddef1e1..8570fabb72f 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -162,6 +162,8 @@ GEM
rotp (~> 2.0)
diff-lcs (1.3)
diffy (3.1.0)
+ discordrb-webhooks-blackst0ne (3.3.0)
+ rest-client (~> 2.0)
docile (1.1.5)
domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0)
@@ -272,7 +274,7 @@ GEM
gitaly-proto (0.123.0)
grpc (~> 1.0)
github-markup (1.7.0)
- gitlab-markup (1.6.4)
+ gitlab-markup (1.6.5)
gitlab-sidekiq-fetcher (0.3.0)
sidekiq (~> 5)
gitlab-styles (2.4.1)
@@ -596,7 +598,7 @@ GEM
get_process_mem (~> 0.2)
puma (>= 2.7, < 4)
pyu-ruby-sasl (0.0.3.3)
- rack (1.6.10)
+ rack (1.6.11)
rack-accept (0.4.5)
rack (>= 0.4)
rack-attack (4.4.1)
@@ -608,7 +610,7 @@ GEM
httpclient (>= 2.4)
multi_json (>= 1.3.6)
rack (>= 1.1)
- rack-protection (2.0.3)
+ rack-protection (2.0.4)
rack
rack-proxy (0.6.0)
rack
@@ -802,7 +804,7 @@ GEM
rack
shoulda-matchers (3.1.2)
activesupport (>= 4.0.0)
- sidekiq (5.2.1)
+ sidekiq (5.2.3)
connection_pool (~> 2.2, >= 2.2.2)
rack-protection (>= 1.5.0)
redis (>= 3.3.5, < 5)
@@ -965,6 +967,7 @@ DEPENDENCIES
devise (~> 4.4)
devise-two-factor (~> 3.0.0)
diffy (~> 3.1.0)
+ discordrb-webhooks-blackst0ne (~> 3.3)
doorkeeper (~> 4.3)
doorkeeper-openid_connect (~> 1.5)
ed25519 (~> 1.2)
@@ -995,7 +998,7 @@ DEPENDENCIES
gettext_i18n_rails_js (~> 1.3)
gitaly-proto (~> 0.123.0)
github-markup (~> 1.7.0)
- gitlab-markup (~> 1.6.4)
+ gitlab-markup (~> 1.6.5)
gitlab-sidekiq-fetcher
gitlab-styles (~> 2.4)
gitlab_omniauth-ldap (~> 2.0.4)
diff --git a/Gemfile.rails5.lock b/Gemfile.rails5.lock
index 181f2db95b0..247ce6c254e 100644
--- a/Gemfile.rails5.lock
+++ b/Gemfile.rails5.lock
@@ -165,6 +165,8 @@ GEM
rotp (~> 2.0)
diff-lcs (1.3)
diffy (3.1.0)
+ discordrb-webhooks-blackst0ne (3.3.0)
+ rest-client (~> 2.0)
docile (1.1.5)
domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0)
@@ -275,7 +277,7 @@ GEM
gitaly-proto (0.123.0)
grpc (~> 1.0)
github-markup (1.7.0)
- gitlab-markup (1.6.4)
+ gitlab-markup (1.6.5)
gitlab-sidekiq-fetcher (0.3.0)
sidekiq (~> 5)
gitlab-styles (2.4.1)
@@ -544,7 +546,7 @@ GEM
orm_adapter (0.5.0)
os (1.0.0)
parallel (1.12.1)
- parser (2.5.1.2)
+ parser (2.5.3.0)
ast (~> 2.4.0)
parslet (1.8.2)
peek (1.0.1)
@@ -612,7 +614,7 @@ GEM
httpclient (>= 2.4)
multi_json (>= 1.3.6)
rack (>= 1.1)
- rack-protection (2.0.3)
+ rack-protection (2.0.4)
rack
rack-proxy (0.6.0)
rack
@@ -810,7 +812,7 @@ GEM
rack
shoulda-matchers (3.1.2)
activesupport (>= 4.0.0)
- sidekiq (5.2.1)
+ sidekiq (5.2.3)
connection_pool (~> 2.2, >= 2.2.2)
rack-protection (>= 1.5.0)
redis (>= 3.3.5, < 5)
@@ -974,6 +976,7 @@ DEPENDENCIES
devise (~> 4.4)
devise-two-factor (~> 3.0.0)
diffy (~> 3.1.0)
+ discordrb-webhooks-blackst0ne (~> 3.3)
doorkeeper (~> 4.3)
doorkeeper-openid_connect (~> 1.5)
ed25519 (~> 1.2)
@@ -1004,7 +1007,7 @@ DEPENDENCIES
gettext_i18n_rails_js (~> 1.3)
gitaly-proto (~> 0.123.0)
github-markup (~> 1.7.0)
- gitlab-markup (~> 1.6.4)
+ gitlab-markup (~> 1.6.5)
gitlab-sidekiq-fetcher
gitlab-styles (~> 2.4)
gitlab_omniauth-ldap (~> 2.0.4)
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index 7c60fb3da42..f80e20a4391 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -128,6 +128,7 @@ export default {
eventHub.$once('fetchedNotesData', this.setDiscussions);
},
methods: {
+ ...mapActions(['startTaskList']),
...mapActions('diffs', [
'setBaseConfig',
'fetchDiffFiles',
@@ -157,7 +158,13 @@ export default {
if (this.isNotesFetched && !this.assignedDiscussions && !this.isLoading) {
this.assignedDiscussions = true;
- requestIdleCallback(() => this.assignDiscussionsToDiff(), { timeout: 1000 });
+ requestIdleCallback(
+ () =>
+ this.assignDiscussionsToDiff()
+ .then(this.$nextTick)
+ .then(this.startTaskList),
+ { timeout: 1000 },
+ );
}
},
adjustView() {
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index d3e9c7c88f0..41256fdd27a 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -190,6 +190,7 @@ export const saveDiffDiscussion = ({ dispatch }, { note, formData }) => {
.then(result => dispatch('updateDiscussion', result.discussion, { root: true }))
.then(discussion => dispatch('assignDiscussionsToDiff', [discussion]))
.then(() => dispatch('closeDiffFileCommentForm', formData.diffFile.fileHash))
+ .then(() => dispatch('startTaskList', null, { root: true }))
.catch(() => createFlash(s__('MergeRequests|Saving the comment failed')));
};
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index 754c6e79ee4..10e80883c00 100644
--- a/app/assets/javascripts/notes/components/comment_form.vue
+++ b/app/assets/javascripts/notes/components/comment_form.vue
@@ -6,7 +6,6 @@ import Autosize from 'autosize';
import { __, sprintf } from '~/locale';
import Flash from '../../flash';
import Autosave from '../../autosave';
-import TaskList from '../../task_list';
import {
capitalizeFirstCharacter,
convertToCamelCase,
@@ -146,7 +145,6 @@ export default {
});
this.initAutoSave();
- this.initTaskList();
},
methods: {
...mapActions([
@@ -298,13 +296,6 @@ Please check your network connection and try again.`;
]);
}
},
- initTaskList() {
- return new TaskList({
- dataType: 'note',
- fieldName: 'note',
- selector: '.notes',
- });
- },
resizeTextarea() {
this.$nextTick(() => {
Autosize.update(this.$refs.textarea);
diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue
index cf4c35de42c..9375627359c 100644
--- a/app/assets/javascripts/notes/components/note_body.vue
+++ b/app/assets/javascripts/notes/components/note_body.vue
@@ -4,7 +4,6 @@ import noteEditedText from './note_edited_text.vue';
import noteAwardsList from './note_awards_list.vue';
import noteAttachment from './note_attachment.vue';
import noteForm from './note_form.vue';
-import TaskList from '../../task_list';
import autosave from '../mixins/autosave';
export default {
@@ -37,14 +36,12 @@ export default {
},
mounted() {
this.renderGFM();
- this.initTaskList();
if (this.isEditing) {
this.initAutoSave(this.note);
}
},
updated() {
- this.initTaskList();
this.renderGFM();
if (this.isEditing) {
@@ -59,15 +56,6 @@ export default {
renderGFM() {
$(this.$refs['note-body']).renderGFM();
},
- initTaskList() {
- if (this.canEdit) {
- this.taskList = new TaskList({
- dataType: 'note',
- fieldName: 'note',
- selector: '.notes',
- });
- }
- },
handleFormUpdate(note, parentElement, callback) {
this.$emit('handleFormUpdate', note, parentElement, callback);
},
diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue
index e302a89ee95..9ab91e2abe5 100644
--- a/app/assets/javascripts/notes/components/noteable_note.vue
+++ b/app/assets/javascripts/notes/components/noteable_note.vue
@@ -46,6 +46,7 @@ export default {
'is-requesting being-posted': this.isRequesting,
'disabled-content': this.isDeleting,
target: this.isTarget,
+ 'is-editable': this.note.current_user.can_edit,
};
},
canResolve() {
diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue
index e555279a6ac..69ddfd751e0 100644
--- a/app/assets/javascripts/notes/components/notes_app.vue
+++ b/app/assets/javascripts/notes/components/notes_app.vue
@@ -122,6 +122,7 @@ export default {
setTargetNoteHash: 'setTargetNoteHash',
toggleDiscussion: 'toggleDiscussion',
setNotesFetchedState: 'setNotesFetchedState',
+ startTaskList: 'startTaskList',
}),
getComponentName(discussion) {
if (discussion.isSkeletonNote) {
@@ -157,6 +158,7 @@ export default {
this.isFetching = false;
})
.then(() => this.$nextTick())
+ .then(() => this.startTaskList())
.then(() => this.checkLocationHash())
.catch(() => {
this.setLoadingState(false);
diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js
index 88739ffb083..a4ab079d258 100644
--- a/app/assets/javascripts/notes/stores/actions.js
+++ b/app/assets/javascripts/notes/stores/actions.js
@@ -1,6 +1,8 @@
+import Vue from 'vue';
import $ from 'jquery';
import axios from '~/lib/utils/axios_utils';
import Visibility from 'visibilityjs';
+import TaskList from '../../task_list';
import Flash from '../../flash';
import Poll from '../../lib/utils/poll';
import * as types from './mutation_types';
@@ -58,12 +60,13 @@ export const deleteNote = ({ commit, dispatch }, note) =>
dispatch('updateMergeRequestWidget');
});
-export const updateNote = ({ commit }, { endpoint, note }) =>
+export const updateNote = ({ commit, dispatch }, { endpoint, note }) =>
service
.updateNote(endpoint, note)
.then(res => res.json())
.then(res => {
commit(types.UPDATE_NOTE, res);
+ dispatch('startTaskList');
});
export const replyToDiscussion = ({ commit }, { endpoint, data }) =>
@@ -85,6 +88,7 @@ export const createNewNote = ({ commit, dispatch }, { endpoint, data }) =>
commit(types.ADD_NEW_NOTE, res);
dispatch('updateMergeRequestWidget');
+ dispatch('startTaskList');
}
return res;
});
@@ -260,6 +264,8 @@ const pollSuccessCallBack = (resp, commit, state, getters, dispatch) => {
commit(types.ADD_NEW_NOTE, note);
}
});
+
+ dispatch('startTaskList');
}
commit(types.SET_LAST_FETCHED_AT, resp.last_fetched_at);
@@ -368,5 +374,16 @@ export const setCommentsDisabled = ({ commit }, data) => {
commit(types.DISABLE_COMMENTS, data);
};
+export const startTaskList = ({ dispatch }) =>
+ Vue.nextTick(
+ () =>
+ new TaskList({
+ dataType: 'note',
+ fieldName: 'note',
+ selector: '.notes .is-editable',
+ onSuccess: () => dispatch('startTaskList'),
+ }),
+ );
+
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
diff --git a/app/models/project.rb b/app/models/project.rb
index 48905547ab4..d87fc1e4b86 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -135,6 +135,7 @@ class Project < ActiveRecord::Base
# Project services
has_one :campfire_service
+ has_one :discord_service
has_one :drone_ci_service
has_one :emails_on_push_service
has_one :pipelines_email_service
diff --git a/app/models/project_services/discord_service.rb b/app/models/project_services/discord_service.rb
new file mode 100644
index 00000000000..21afd14dbff
--- /dev/null
+++ b/app/models/project_services/discord_service.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require "discordrb/webhooks"
+
+class DiscordService < ChatNotificationService
+ def title
+ "Discord Notifications"
+ end
+
+ def description
+ "Receive event notifications in Discord"
+ end
+
+ def self.to_param
+ "discord"
+ end
+
+ def help
+ "This service sends notifications about project events to Discord channels.<br />
+ To set up this service:
+ <ol>
+ <li><a href='https://support.discordapp.com/hc/en-us/articles/228383668-Intro-to-Webhooks'>Setup a custom Incoming Webhook</a>.</li>
+ <li>Paste the <strong>Webhook URL</strong> into the field below.</li>
+ <li>Select events below to enable notifications.</li>
+ </ol>"
+ end
+
+ def event_field(event)
+ # No-op.
+ end
+
+ def default_channel_placeholder
+ # No-op.
+ end
+
+ def default_fields
+ [
+ { type: "text", name: "webhook", placeholder: "e.g. https://discordapp.com/api/webhooks/…" },
+ { type: "checkbox", name: "notify_only_broken_pipelines" },
+ { type: "checkbox", name: "notify_only_default_branch" }
+ ]
+ end
+
+ private
+
+ def notify(message, opts)
+ client = Discordrb::Webhooks::Client.new(url: webhook)
+
+ client.execute do |builder|
+ builder.content = message.pretext
+ end
+ end
+
+ def custom_data(data)
+ super(data).merge(markdown: true)
+ end
+end
diff --git a/app/models/service.rb b/app/models/service.rb
index 4dbda7acab6..5b8bf6e7cf0 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -253,6 +253,7 @@ class Service < ActiveRecord::Base
bugzilla
campfire
custom_issue_tracker
+ discord
drone_ci
emails_on_push
external_wiki
diff --git a/changelogs/unreleased/blackst0ne-add-discord-service.yml b/changelogs/unreleased/blackst0ne-add-discord-service.yml
new file mode 100644
index 00000000000..85dedf6d81f
--- /dev/null
+++ b/changelogs/unreleased/blackst0ne-add-discord-service.yml
@@ -0,0 +1,5 @@
+---
+title: Add Discord integration
+merge_request: 22684
+author: "@blackst0ne"
+type: added
diff --git a/changelogs/unreleased/discussion-perf-improvement.yml b/changelogs/unreleased/discussion-perf-improvement.yml
new file mode 100644
index 00000000000..defff8a55f5
--- /dev/null
+++ b/changelogs/unreleased/discussion-perf-improvement.yml
@@ -0,0 +1,5 @@
+---
+title: Improve initial discussion rendering performance
+merge_request: 22607
+author:
+type: changed
diff --git a/danger/documentation/Dangerfile b/danger/documentation/Dangerfile
index fe819ee250c..1ee025f0972 100644
--- a/danger/documentation/Dangerfile
+++ b/danger/documentation/Dangerfile
@@ -24,9 +24,32 @@ The following files require a review from the Documentation team:
* #{docs_paths_to_review.map { |path| "`#{path}`" }.join("\n* ")}
-To make sure these changes are reviewed, mention `@gl-docsteam` in a separate
-comment, and explain what needs to be reviewed by the team. Please don't mention
-the team until your changes are ready for review.
+When your content is ready for review, mention a technical writer in a separate
+comment and explain what needs to be reviewed.
+
+You are welcome to mention them sooner if you have questions about writing or updating
+the documentation. GitLabbers are also welcome to use the [#docs](https://gitlab.slack.com/archives/C16HYA2P5) channel on Slack.
+
+Who to ping [based on DevOps stages](https://about.gitlab.com/handbook/product/categories/#devops-stages):
+
+| Stage | Tech writer |
+| ------------- | ----------- |
+| ~Create | `@marcia` |
+| ~Configure | `@eread` |
+| ~Distribution | `@axil` |
+| ~Geo | `@eread` |
+| ~Gitaly | `@axil` |
+| ~Gitter | `@axil` |
+| ~Manage | `@eread` |
+| ~Monitoring | `@axil` |
+| ~Packaging | `@axil` |
+| ~Plan | `@mikelewis`|
+| ~Release | `marcia` |
+| ~Secure | `@axil` |
+| ~Verify | `@eread` |
+
+If you are not sure which category the change falls within, or the change is not
+part of one of these categories, you can mention the whole team with `@gl-docsteam`.
MARKDOWN
unless gitlab.mr_labels.include?('Documentation')
diff --git a/doc/administration/git_protocol.md b/doc/administration/git_protocol.md
index 6b82771baf9..b1be078d672 100644
--- a/doc/administration/git_protocol.md
+++ b/doc/administration/git_protocol.md
@@ -4,9 +4,7 @@ description: "Set and configure Git protocol v2"
# Configuring Git Protocol v2
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/46555) in GitLab 11.4.
-
----
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/46555) in GitLab 11.4.
Git protocol v2 improves the v1 wire protocol in several ways and is
enabled by default in GitLab for HTTP requests. In order to enable SSH,
diff --git a/doc/api/services.md b/doc/api/services.md
index 741ea83070f..f122bac6f1f 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -10,7 +10,7 @@ Asana - Teamwork without email
Set Asana service for a project.
-> This service adds commit messages as comments to Asana tasks. Once enabled, commit messages are checked for Asana task URLs (for example, `https://app.asana.com/0/123456/987654`) or task IDs starting with # (for example, `#987654`). Every task ID found will get the commit comment added to it. You can also close a task with a message containing: `fix #123456`. You can find your Api Keys here: https://asana.com/developers/documentation/getting-started/auth#api-key
+> This service adds commit messages as comments to Asana tasks. Once enabled, commit messages are checked for Asana task URLs (for example, `https://app.asana.com/0/123456/987654`) or task IDs starting with # (for example, `#987654`). Every task ID found will get the commit comment added to it. You can also close a task with a message containing: `fix #123456`. You can find your Api Keys here: <https://asana.com/developers/documentation/getting-started/auth#api-key>.
```
PUT /projects/:id/services/asana
@@ -92,7 +92,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `bamboo_url` | string | true | Bamboo root URL like https://bamboo.example.com |
+| `bamboo_url` | string | true | Bamboo root URL. For example, `https://bamboo.example.com`. |
| `build_key` | string | true | Bamboo build plan key like KEY |
| `username` | string | true | A user with API access, if applicable |
| `password` | string | true | Password of the user |
@@ -117,7 +117,7 @@ GET /projects/:id/services/bamboo
Bugzilla Issue Tracker
-### Create/Edit Buildkite service
+### Create/Edit Bugzilla service
Set Bugzilla service for a project.
@@ -168,7 +168,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `token` | string | true | Buildkite project GitLab token |
-| `project_url` | string | true | https://buildkite.com/example/project |
+| `project_url` | string | true | `https://buildkite.com/example/project` |
| `enable_ssl_verification` | boolean | false | Enable SSL verification |
### Delete Buildkite service
@@ -278,7 +278,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `token` | string | true | Drone CI project specific token |
-| `drone_url` | string | true | http://drone.example.com |
+| `drone_url` | string | true | `http://drone.example.com` |
| `enable_ssl_verification` | boolean | false | Enable SSL verification |
### Delete Drone CI service
@@ -421,7 +421,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `webhook` | string | true | The Hangouts Chat webhook. e.g. https://chat.googleapis.com/v1/spaces... |
+| `webhook` | string | true | The Hangouts Chat webhook. For example, `https://chat.googleapis.com/v1/spaces...`. |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
| `notify_only_default_branch` | boolean | false | Send notifications only for the default branch |
| `push_events` | boolean | false | Enable notifications for push events |
@@ -470,7 +470,7 @@ Parameters:
| `notify` | boolean | false | Enable notifications |
| `room` | string | false |Room name or ID |
| `api_version` | string | false | Leave blank for default (v2) |
-| `server` | string | false | Leave blank for default. https://hipchat.example.com |
+| `server` | string | false | Leave blank for default. For example, `https://hipchat.example.com`. |
### Delete HipChat service
@@ -496,7 +496,7 @@ Send IRC messages, on update, to a list of recipients through an Irker gateway.
Set Irker (IRC gateway) service for a project.
-> NOTE: Irker does NOT have built-in authentication, which makes it vulnerable to spamming IRC channels if it is hosted outside of a firewall. Please make sure you run the daemon within a secured network to prevent abuse. For more details, read: http://www.catb.org/~esr/irker/security.html.
+> NOTE: Irker does NOT have built-in authentication, which makes it vulnerable to spamming IRC channels if it is hosted outside of a firewall. Please make sure you run the daemon within a secured network to prevent abuse. For more details, read: <http://www.catb.org/~esr/irker/security.html>.
```
PUT /projects/:id/services/irker
@@ -546,7 +546,7 @@ Set JIRA service for a project.
> **Notes:**
> - Starting with GitLab 8.14, `api_url`, `issues_url`, `new_issue_url` and
-> `project_url` are replaced by `project_key`, `url`. If you are using an
+> `project_url` are replaced by `project_key`, `url`. If you are using an
> older version, [follow this documentation][old-jira-api].
```
@@ -557,7 +557,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `url` | string | yes | The URL to the JIRA project which is being linked to this GitLab project, e.g., `https://jira.example.com`. |
+| `url` | string | yes | The URL to the JIRA project which is being linked to this GitLab project. For example, `https://jira.example.com`. |
| `project_key` | string | yes | The short identifier for your JIRA project, all uppercase, e.g., `PROJ`. |
| `username` | string | yes | The username of the user created to be used with GitLab/JIRA. |
| `password` | string | yes | The password of the user created to be used with GitLab/JIRA. |
@@ -589,7 +589,7 @@ PUT /projects/:id/services/kubernetes
Parameters:
- `namespace` (**required**) - The Kubernetes namespace to use
-- `api_url` (**required**) - The URL to the Kubernetes cluster API, e.g., https://kubernetes.example.com
+- `api_url` (**required**) - The URL to the Kubernetes cluster API. For example, `https://kubernetes.example.com`
- `token` (**required**) - The service token to authenticate against the Kubernetes cluster with
- `ca_pem` (optional) - A custom certificate authority bundle to verify the Kubernetes cluster with (PEM format)
@@ -658,7 +658,6 @@ Parameters:
| --------- | ---- | -------- | ----------- |
| `token` | string | yes | The Slack token |
-
### Delete Slack slash command service
Delete Slack slash command service for a project.
@@ -823,7 +822,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `api_url` | string | true | Prometheus API Base URL, like http://prometheus.example.com/ |
+| `api_url` | string | true | Prometheus API Base URL. For example, `http://prometheus.example.com/`. |
### Delete Prometheus service
@@ -934,7 +933,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `webhook` | string | true | https://hooks.slack.com/services/... |
+| `webhook` | string | true | `https://hooks.slack.com/services/...` |
| `username` | string | false | username |
| `channel` | string | false | Default channel to use if others are not configured |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
@@ -988,7 +987,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `webhook` | string | true | The Microsoft Teams webhook. e.g. https://outlook.office.com/webhook/... |
+| `webhook` | string | true | The Microsoft Teams webhook. For example, `https://outlook.office.com/webhook/...` |
### Delete Microsoft Teams service
@@ -1024,7 +1023,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `webhook` | string | true | The Mattermost webhook. e.g. http://mattermost_host/hooks/... |
+| `webhook` | string | true | The Mattermost webhook. For example, `http://mattermost_host/hooks/...` |
| `username` | string | false | username |
| `channel` | string | false | Default channel to use if others are not configured |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
@@ -1080,7 +1079,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `teamcity_url` | string | true | TeamCity root URL like https://teamcity.example.com |
+| `teamcity_url` | string | true | TeamCity root URL. For example, `https://teamcity.example.com` |
| `build_type` | string | true | Build configuration ID |
| `username` | string | true | A user with permissions to trigger a manual build |
| `password` | string | true | The password of the user |
@@ -1104,7 +1103,6 @@ GET /projects/:id/services/teamcity
[jira-doc]: ../user/project/integrations/jira.md
[old-jira-api]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-13-stable/doc/api/services.md#jira
-
## MockCI
Mock an external CI. See [`gitlab-org/gitlab-mock-ci-service`](https://gitlab.com/gitlab-org/gitlab-mock-ci-service) for an example of a companion mock service.
@@ -1123,7 +1121,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `mock_service_url` | string | true | http://localhost:4004 |
+| `mock_service_url` | string | true | `http://localhost:4004` |
### Delete MockCI service
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index 154ede087cc..b8b86ac1bf5 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -41,9 +41,11 @@ how to structure GitLab docs.
## Markdown and styles
-Currently GitLab docs use [Kramdown](https://gitlab.com/gitlab-com/gitlab-docs/issues/50) as the [markdown](../../user/markdown.md) engine.
+[GitLab docs](https://gitlab.com/gitlab-com/gitlab-docs) uses [GitLab Kramdown](https://gitlab.com/gitlab-org/gitlab_kramdown)
+as markdown engine. Check the [GitLab Markdown Kramdown Guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/)
+for a complete Kramdown reference.
-All the docs follow the [documentation style guidelines](styleguide.md). See [Linting](#linting) for help to follow the guidelines.
+Follow the [documentation style guidelines](styleguide.md) strictly.
## Documentation directory structure
@@ -198,6 +200,11 @@ redirect_to: '../path/to/file/README.md'
It supports both full and relative URLs, e.g. `https://docs.gitlab.com/ee/path/to/file.html`, `../path/to/file.html`, `path/to/file.md`. Note that any `*.md` paths will be compiled to `*.html`.
+NOTE: **Note:**
+This redirection method will not provide a redirect fallback on GitLab `/help`. When using
+it, make sure to add a link to the new page on the doc, otherwise it's a dead end for users that
+land on the doc via `/help`.
+
### Redirections for pages with Disqus comments
If the documentation page being relocated already has any Disqus comments,
@@ -223,145 +230,6 @@ redirect_from: 'https://docs.gitlab.com/my-old-location/README.html'
Note: it is necessary to include the file name in the `redirect_from` URL,
even if it's `index.html` or `README.html`.
-## Linting
-
-To help adhere to the [documentation style guidelines](styleguide.md), and to improve the content
-added to documentation, consider locally installing and running documentation linters. This will
-help you catch common issues before raising merge requests for review of documentation.
-
-The following are some suggested linters you can install locally and sample configuration:
-
-- [`proselint`](#proselint)
-- [`markdownlint`](#markdownlint)
-
-NOTE: **Note:**
-This list does not limit what other linters you can add to your local documentation writing toolchain.
-
-### `proselint`
-
-`proselint` checks for common problems with English prose. It provides a
- [plethora of checks](http://proselint.com/checks/) that are helpful for technical writing.
-
-`proselint` can be used [on the command line](http://proselint.com/utility/), either on a single
- Markdown file or on all Markdown files in a project. For example, to run `proselint` on all
- documentation in the [`gitlab-ce` project](https://gitlab.com/gitlab-org/gitlab-ce), run the
- following commands from within the `gitlab-ce` project:
-
-```sh
-cd doc
-proselint **/*.md
-```
-
-`proselint` can also be run from within editors using plugins. For example, the following plugins
- are available:
-
-- [Sublime Text](https://packagecontrol.io/packages/SublimeLinter-contrib-proselint)
-- [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=PatrykPeszko.vscode-proselint)
-- [Others](https://github.com/amperser/proselint#plugins-for-other-software)
-
-#### Sample `proselint` configuration
-
-All of the checks are good to use. However, excluding the `typography.symbols` and `misc.phrasal_adjectives` checks will reduce
-noise. The following sample `proselint` configuration disables these checks:
-
-```json
-{
- "checks": {
- "typography.symbols": false,
- "misc.phrasal_adjectives": false
- }
-}
-```
-
-A file with `proselint` configuration must be placed in a
-[valid location](https://github.com/amperser/proselint#checks). For example, `~/.config/proselint/config`.
-
-### `markdownlint`
-
-`markdownlint` checks that certain rules ([example](https://github.com/DavidAnson/markdownlint/blob/master/README.md#rules--aliases))
- are followed for Markdown syntax. Our [style guidelines](styleguide.md) elaborate on which choices
- must be made when selecting Markdown syntax for GitLab documentation and this tool helps
- catch deviations from those guidelines.
-
-`markdownlint` can be used [on the command line](https://github.com/igorshubovych/markdownlint-cli#markdownlint-cli--),
- either on a single Markdown file or on all Markdown files in a project. For example, to run
- `markdownlint` on all documentation in the [`gitlab-ce` project](https://gitlab.com/gitlab-org/gitlab-ce),
- run the following commands from within the `gitlab-ce` project:
-
-```sh
-cd doc
-markdownlint **/*.md
-```
-
-`markdownlint` can also be run from within editors using plugins. For example, the following plugins
- are available:
-
-- [Sublime Text](https://packagecontrol.io/packages/SublimeLinter-contrib-markdownlint)
-- [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint)
-- [Others](https://github.com/DavidAnson/markdownlint#related)
-
-#### Sample `markdownlint` configuration
-
-The following sample `markdownlint` configuration modifies the available default rules to:
-
-- Adhere to the [style guidelines](styleguide.md).
-- Apply conventions found in the GitLab documentation.
-- Allow the flexibility of using some inline HTML.
-
-```json
-{
- "default": true,
- "header-style": { "style": "atx" },
- "ul-style": { "style": "dash" },
- "line-length": false,
- "no-trailing-punctuation": false,
- "ol-prefix": { "style": "one" },
- "blanks-around-fences": false,
- "no-inline-html": {
- "allowed_elements": [
- "table",
- "tbody",
- "tr",
- "td",
- "ul",
- "ol",
- "li",
- "br",
- "img",
- "a",
- "strong",
- "i",
- "div"
- ]
- },
- "hr-style": { "style": "---" },
- "fenced-code-language": false
-}
-```
-
-For [`markdownlint`](https://github.com/DavidAnson/markdownlint/), this configuration must be
-placed in a [valid location](https://github.com/igorshubovych/markdownlint-cli#configuration). For
-example, `~/.markdownlintrc`.
-
-## Testing
-
-We treat documentation as code, thus have implemented some testing.
-Currently, the following tests are in place:
-
-1. `docs lint`: Check that all internal (relative) links work correctly and
- that all cURL examples in API docs use the full switches. It's recommended
- to [check locally](#previewing-locally) before pushing to GitLab by executing the command
- `bundle exec nanoc check internal_links` on your local
- [`gitlab-docs`](https://gitlab.com/gitlab-com/gitlab-docs) directory.
-1. [`ee_compat_check`](../automatic_ce_ee_merge.md#avoiding-ce-gt-ee-merge-conflicts-beforehand) (runs on CE only):
- When you submit a merge request to GitLab Community Edition (CE),
- there is this additional job that runs against Enterprise Edition (EE)
- and checks if your changes can apply cleanly to the EE codebase.
- If that job fails, read the instructions in the job log for what to do next.
- As CE is merged into EE once a day, it's important to avoid merge conflicts.
- Submitting an EE-equivalent merge request cherry-picking all commits from CE to EE is
- essential to avoid them.
-
## Branch naming
If your contribution contains **only** documentation changes, you can speed up
@@ -377,15 +245,6 @@ choices:
If your branch name matches any of the above, it will run only the docs
tests. If it doesn't, the whole test suite will run (including docs).
-## Danger bot
-
-GitLab uses [danger bot](https://github.com/danger/danger) for some elements in
-code review. For docs changes in merge requests, the following actions are taken:
-
-1. Whenever a change under `/doc` is made, the bot leaves a comment for the
- author to mention `@gl-docsteam`, so that the docs can be properly
- reviewed.
-
## Merge requests for GitLab documentation
Before getting started, make sure you read the introductory section
@@ -428,105 +287,6 @@ Follow this [method for cherry-picking from CE to EE](../automatic_ce_ee_merge.m
additionally to the CE MR. If there are many EE-only changes though, start a new MR
to EE only.
-## Previewing the changes live
-
-NOTE: **Note:**
-To preview your changes to documentation locally, follow this
-[development guide](https://gitlab.com/gitlab-com/gitlab-docs/blob/master/README.md#development-when-contributing-to-gitlab-documentation) or [these instructions for GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/gitlab_docs.md).
-
-The live preview is currently enabled for the following projects:
-
-- <https://gitlab.com/gitlab-org/gitlab-ce>
-- <https://gitlab.com/gitlab-org/gitlab-ee>
-- <https://gitlab.com/gitlab-org/gitlab-runner>
-
-If your branch contains only documentation changes, you can use
-[special branch names](#branch-naming) to avoid long running pipelines.
-
-For [docs-only changes](#branch-naming), the review app is run automatically.
-For all other branches, you can use the manual `review-docs-deploy-manual` job
-in your merge request. You will need at least Maintainer permissions to be able
-to run it. In the mini pipeline graph, you should see an `>>` icon. Clicking on it will
-reveal the `review-docs-deploy-manual` job. Hit the play button for the job to start.
-
-![Manual trigger a docs build](img/manual_build_docs.png)
-
-NOTE: **Note:**
-You will need to push a branch to those repositories, it doesn't work for forks.
-
-The `review-docs-deploy*` job will:
-
-1. Create a new branch in the [gitlab-docs](https://gitlab.com/gitlab-com/gitlab-docs)
- project named after the scheme: `$DOCS_GITLAB_REPO_SUFFIX-$CI_ENVIRONMENT_SLUG`,
- where `DOCS_GITLAB_REPO_SUFFIX` is the suffix for each product, e.g, `ce` for
- CE, etc.
-1. Trigger a cross project pipeline and build the docs site with your changes
-
-After a few minutes, the Review App will be deployed and you will be able to
-preview the changes. The docs URL can be found in two places:
-
-- In the merge request widget
-- In the output of the `review-docs-deploy*` job, which also includes the
- triggered pipeline so that you can investigate whether something went wrong
-
-TIP: **Tip:**
-Someone that has no merge rights to the CE/EE projects (think of forks from
-contributors) will not be able to run the manual job. In that case, you can
-ask someone from the GitLab team who has the permissions to do that for you.
-
-NOTE: **Note:**
-Make sure that you always delete the branch of the merge request you were
-working on. If you don't, the remote docs branch won't be removed either,
-and the server where the Review Apps are hosted will eventually be out of
-disk space.
-
-### Troubleshooting review apps
-
-In case the review app URL returns 404, follow these steps to debug:
-
-1. **Did you follow the URL from the merge request widget?** If yes, then check if
- the link is the same as the one in the job output.
-1. **Did you follow the URL from the job output?** If yes, then it means that
- either the site is not yet deployed or something went wrong with the remote
- pipeline. Give it a few minutes and it should appear online, otherwise you
- can check the status of the remote pipeline from the link in the job output.
- If the pipeline failed or got stuck, drop a line in the `#docs` chat channel.
-
-### Technical aspects
-
-If you want to know the hot details, here's what's really happening:
-
-1. You manually run the `review-docs-deploy` job in a CE/EE merge request.
-1. The job runs the [`scripts/trigger-build-docs`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/trigger-build-docs)
- script with the `deploy` flag, which in turn:
- 1. Takes your branch name and applies the following:
- - The slug of the branch name is used to avoid special characters since
- ultimately this will be used by NGINX.
- - The `preview-` prefix is added to avoid conflicts if there's a remote branch
- with the same name that you created in the merge request.
- - The final branch name is truncated to 42 characters to avoid filesystem
- limitations with long branch names (> 63 chars).
- 1. The remote branch is then created if it doesn't exist (meaning you can
- re-run the manual job as many times as you want and this step will be skipped).
- 1. A new cross-project pipeline is triggered in the docs project.
- 1. The preview URL is shown both at the job output and in the merge request
- widget. You also get the link to the remote pipeline.
-1. In the docs project, the pipeline is created and it
- [skips the test jobs](https://gitlab.com/gitlab-com/gitlab-docs/blob/8d5d5c750c602a835614b02f9db42ead1c4b2f5e/.gitlab-ci.yml#L50-55)
- to lower the build time.
-1. Once the docs site is built, the HTML files are uploaded as artifacts.
-1. A specific Runner tied only to the docs project, runs the Review App job
- that downloads the artifacts and uses `rsync` to transfer the files over
- to a location where NGINX serves them.
-
-The following GitLab features are used among others:
-
-- [Manual actions](../../ci/yaml/README.md#manual-actions)
-- [Multi project pipelines](https://docs.gitlab.com/ee/ci/multi_project_pipeline_graphs.html)
-- [Review Apps](../../ci/review_apps/index.md)
-- [Artifacts](../../ci/yaml/README.md#artifacts)
-- [Specific Runner](../../ci/runners/README.md#locking-a-specific-runner-from-being-enabled-for-other-projects)
-
## GitLab `/help`
Every GitLab instance includes the documentation, which is available from `/help`
@@ -678,5 +438,250 @@ date: 2017-02-01
Use the [writing method](https://about.gitlab.com/handbook/product/technical-writing/#writing-method) defined by the Technical Writing team.
+## Previewing the changes live
+
+NOTE: **Note:**
+To preview your changes to documentation locally, follow this
+[development guide](https://gitlab.com/gitlab-com/gitlab-docs/blob/master/README.md#development-when-contributing-to-gitlab-documentation) or [these instructions for GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/gitlab_docs.md).
+
+The live preview is currently enabled for the following projects:
+
+- <https://gitlab.com/gitlab-org/gitlab-ce>
+- <https://gitlab.com/gitlab-org/gitlab-ee>
+- <https://gitlab.com/gitlab-org/gitlab-runner>
+
+If your branch contains only documentation changes, you can use
+[special branch names](#branch-naming) to avoid long running pipelines.
+
+For [docs-only changes](#branch-naming), the review app is run automatically.
+For all other branches, you can use the manual `review-docs-deploy-manual` job
+in your merge request. You will need at least Maintainer permissions to be able
+to run it. In the mini pipeline graph, you should see an `>>` icon. Clicking on it will
+reveal the `review-docs-deploy-manual` job. Hit the play button for the job to start.
+
+![Manual trigger a docs build](img/manual_build_docs.png)
+
+NOTE: **Note:**
+You will need to push a branch to those repositories, it doesn't work for forks.
+
+The `review-docs-deploy*` job will:
+
+1. Create a new branch in the [gitlab-docs](https://gitlab.com/gitlab-com/gitlab-docs)
+ project named after the scheme: `$DOCS_GITLAB_REPO_SUFFIX-$CI_ENVIRONMENT_SLUG`,
+ where `DOCS_GITLAB_REPO_SUFFIX` is the suffix for each product, e.g, `ce` for
+ CE, etc.
+1. Trigger a cross project pipeline and build the docs site with your changes
+
+After a few minutes, the Review App will be deployed and you will be able to
+preview the changes. The docs URL can be found in two places:
+
+- In the merge request widget
+- In the output of the `review-docs-deploy*` job, which also includes the
+ triggered pipeline so that you can investigate whether something went wrong
+
+TIP: **Tip:**
+Someone that has no merge rights to the CE/EE projects (think of forks from
+contributors) will not be able to run the manual job. In that case, you can
+ask someone from the GitLab team who has the permissions to do that for you.
+
+NOTE: **Note:**
+Make sure that you always delete the branch of the merge request you were
+working on. If you don't, the remote docs branch won't be removed either,
+and the server where the Review Apps are hosted will eventually be out of
+disk space.
+
+### Troubleshooting review apps
+
+In case the review app URL returns 404, follow these steps to debug:
+
+1. **Did you follow the URL from the merge request widget?** If yes, then check if
+ the link is the same as the one in the job output.
+1. **Did you follow the URL from the job output?** If yes, then it means that
+ either the site is not yet deployed or something went wrong with the remote
+ pipeline. Give it a few minutes and it should appear online, otherwise you
+ can check the status of the remote pipeline from the link in the job output.
+ If the pipeline failed or got stuck, drop a line in the `#docs` chat channel.
+
+### Technical aspects
+
+If you want to know the in-depth details, here's what's really happening:
+
+1. You manually run the `review-docs-deploy` job in a CE/EE merge request.
+1. The job runs the [`scripts/trigger-build-docs`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/trigger-build-docs)
+ script with the `deploy` flag, which in turn:
+ 1. Takes your branch name and applies the following:
+ - The slug of the branch name is used to avoid special characters since
+ ultimately this will be used by NGINX.
+ - The `preview-` prefix is added to avoid conflicts if there's a remote branch
+ with the same name that you created in the merge request.
+ - The final branch name is truncated to 42 characters to avoid filesystem
+ limitations with long branch names (> 63 chars).
+ 1. The remote branch is then created if it doesn't exist (meaning you can
+ re-run the manual job as many times as you want and this step will be skipped).
+ 1. A new cross-project pipeline is triggered in the docs project.
+ 1. The preview URL is shown both at the job output and in the merge request
+ widget. You also get the link to the remote pipeline.
+1. In the docs project, the pipeline is created and it
+ [skips the test jobs](https://gitlab.com/gitlab-com/gitlab-docs/blob/8d5d5c750c602a835614b02f9db42ead1c4b2f5e/.gitlab-ci.yml#L50-55)
+ to lower the build time.
+1. Once the docs site is built, the HTML files are uploaded as artifacts.
+1. A specific Runner tied only to the docs project, runs the Review App job
+ that downloads the artifacts and uses `rsync` to transfer the files over
+ to a location where NGINX serves them.
+
+The following GitLab features are used among others:
+
+- [Manual actions](../../ci/yaml/README.md#manual-actions)
+- [Multi project pipelines](https://docs.gitlab.com/ee/ci/multi_project_pipeline_graphs.html)
+- [Review Apps](../../ci/review_apps/index.md)
+- [Artifacts](../../ci/yaml/README.md#artifacts)
+- [Specific Runner](../../ci/runners/README.md#locking-a-specific-runner-from-being-enabled-for-other-projects)
+
+## Testing
+
+We treat documentation as code, thus have implemented some testing.
+Currently, the following tests are in place:
+
+1. `docs lint`: Check that all internal (relative) links work correctly and
+ that all cURL examples in API docs use the full switches. It's recommended
+ to [check locally](#previewing-locally) before pushing to GitLab by executing the command
+ `bundle exec nanoc check internal_links` on your local
+ [`gitlab-docs`](https://gitlab.com/gitlab-com/gitlab-docs) directory.
+1. [`ee_compat_check`](../automatic_ce_ee_merge.md#avoiding-ce-gt-ee-merge-conflicts-beforehand) (runs on CE only):
+ When you submit a merge request to GitLab Community Edition (CE),
+ there is this additional job that runs against Enterprise Edition (EE)
+ and checks if your changes can apply cleanly to the EE codebase.
+ If that job fails, read the instructions in the job log for what to do next.
+ As CE is merged into EE once a day, it's important to avoid merge conflicts.
+ Submitting an EE-equivalent merge request cherry-picking all commits from CE to EE is
+ essential to avoid them.
+
+### Linting
+
+To help adhere to the [documentation style guidelines](styleguide.md), and to improve the content
+added to documentation, consider locally installing and running documentation linters. This will
+help you catch common issues before raising merge requests for review of documentation.
+
+The following are some suggested linters you can install locally and sample configuration:
+
+- [`proselint`](#proselint)
+- [`markdownlint`](#markdownlint)
+
+NOTE: **Note:**
+This list does not limit what other linters you can add to your local documentation writing toolchain.
+
+#### `proselint`
+
+`proselint` checks for common problems with English prose. It provides a
+ [plethora of checks](http://proselint.com/checks/) that are helpful for technical writing.
+
+`proselint` can be used [on the command line](http://proselint.com/utility/), either on a single
+ Markdown file or on all Markdown files in a project. For example, to run `proselint` on all
+ documentation in the [`gitlab-ce` project](https://gitlab.com/gitlab-org/gitlab-ce), run the
+ following commands from within the `gitlab-ce` project:
+
+```sh
+cd doc
+proselint **/*.md
+```
+
+`proselint` can also be run from within editors using plugins. For example, the following plugins
+ are available:
+
+- [Sublime Text](https://packagecontrol.io/packages/SublimeLinter-contrib-proselint)
+- [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=PatrykPeszko.vscode-proselint)
+- [Others](https://github.com/amperser/proselint#plugins-for-other-software)
+
+##### Sample `proselint` configuration
+
+All of the checks are good to use. However, excluding the `typography.symbols` and `misc.phrasal_adjectives` checks will reduce
+noise. The following sample `proselint` configuration disables these checks:
+
+```json
+{
+ "checks": {
+ "typography.symbols": false,
+ "misc.phrasal_adjectives": false
+ }
+}
+```
+
+A file with `proselint` configuration must be placed in a
+[valid location](https://github.com/amperser/proselint#checks). For example, `~/.config/proselint/config`.
+
+#### `markdownlint`
+
+`markdownlint` checks that certain rules ([example](https://github.com/DavidAnson/markdownlint/blob/master/README.md#rules--aliases))
+ are followed for Markdown syntax. Our [style guidelines](styleguide.md) elaborate on which choices
+ must be made when selecting Markdown syntax for GitLab documentation and this tool helps
+ catch deviations from those guidelines.
+
+`markdownlint` can be used [on the command line](https://github.com/igorshubovych/markdownlint-cli#markdownlint-cli--),
+ either on a single Markdown file or on all Markdown files in a project. For example, to run
+ `markdownlint` on all documentation in the [`gitlab-ce` project](https://gitlab.com/gitlab-org/gitlab-ce),
+ run the following commands from within the `gitlab-ce` project:
+
+```sh
+cd doc
+markdownlint **/*.md
+```
+
+`markdownlint` can also be run from within editors using plugins. For example, the following plugins
+ are available:
+
+- [Sublime Text](https://packagecontrol.io/packages/SublimeLinter-contrib-markdownlint)
+- [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint)
+- [Others](https://github.com/DavidAnson/markdownlint#related)
+
+##### Sample `markdownlint` configuration
+
+The following sample `markdownlint` configuration modifies the available default rules to:
+
+- Adhere to the [style guidelines](styleguide.md).
+- Apply conventions found in the GitLab documentation.
+- Allow the flexibility of using some inline HTML.
+
+```json
+{
+ "default": true,
+ "header-style": { "style": "atx" },
+ "ul-style": { "style": "dash" },
+ "line-length": false,
+ "no-trailing-punctuation": false,
+ "ol-prefix": { "style": "one" },
+ "blanks-around-fences": false,
+ "no-inline-html": {
+ "allowed_elements": [
+ "table",
+ "tbody",
+ "tr",
+ "td",
+ "ul",
+ "ol",
+ "li",
+ "br",
+ "img",
+ "a",
+ "strong",
+ "i",
+ "div"
+ ]
+ },
+ "hr-style": { "style": "---" },
+ "fenced-code-language": false
+}
+```
+
+For [`markdownlint`](https://github.com/DavidAnson/markdownlint/), this configuration must be
+placed in a [valid location](https://github.com/igorshubovych/markdownlint-cli#configuration). For
+example, `~/.markdownlintrc`.
+
+## Danger bot
+
+GitLab uses [danger bot](https://github.com/danger/danger) for some elements in
+code review. For docs changes in merge requests, whenever a change under `/doc`
+is made, the bot leaves a comment for the author to mention `@gl-docsteam`, so
+that the docs can be properly reviewed.
+
[gitlab-map]: https://gitlab.com/gitlab-org/gitlab-design/raw/master/production/resources/gitlab-map.png
[graffle]: https://gitlab.com/gitlab-org/gitlab-design/blob/d8d39f4a87b90fb9ae89ca12dc565347b4900d5e/production/resources/gitlab-map.graffle
diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md
index 97b1b890836..8309ba9a72c 100644
--- a/doc/development/documentation/styleguide.md
+++ b/doc/development/documentation/styleguide.md
@@ -10,17 +10,15 @@ GitLab documentation. Check the
Check the GitLab handbook for the [writing styles guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines).
-For help adhering to the guidelines, see [Linting](index.md#linting).
+For help adhering to the guidelines, see [linting](index.md#linting).
## Files
- [Directory structure](index.md#location-and-naming-documents): place the docs
- in the correct location.
+in the correct location.
- [Documentation files](index.md#documentation-files): name the files accordingly.
-- [Markdown](../../user/markdown.md): use the GitLab Flavored Markdown in the
- documentation.
-NOTE: **Note:**
+DANGER: **Attention:**
**Do not** use capital letters, spaces, or special chars in file names,
branch names, directory names, headings, or in anything that generates a path.
@@ -28,65 +26,144 @@ NOTE: **Note:**
**Do not** create new `README.md` files, name them `index.md` instead. There's
a test that will fail if it spots a new `README.md` file.
-## Text
+### Markdown
+
+The [documentation website](https://docs.gitlab.com) had its markdown engine migrated from [Redcarpet to GitLab Kramdown](https://gitlab.com/gitlab-com/gitlab-docs/merge_requests/108)
+in October, 2018.
+
+The [`gitlab-kramdown`](https://gitlab.com/gitlab-org/gitlab_kramdown)
+gem will support all [GFM markup](../../user/markdown.md) in the future. For now,
+use regular markdown markup, following the rules on this style guide. For a complete
+Kramdown reference, check the [GiLab Markdown Kramdown Guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/).
+Use Kramdown markup wisely: do not overuse its specific markup (e.g., `{:.class}`) as it will not render properly in
+[`/help`](#gitlab-help).
+
+## Content
-- Split up long lines (wrap text), this makes it much easier to review and edit. Only
- double line breaks are shown as a full line break in [GitLab markdown][gfm].
- 80-100 characters is a good line length.
- Make sure that the documentation is added in the correct
- [directory](index.md#documentation-directory-structure) and that
- there's a link to it somewhere useful.
+ [directory](index.md#documentation-directory-structure), linked from its
+ higher-level index, and linked from other related pages.
- Do not duplicate information.
- Be brief and clear.
-- Unless there's a logical reason not to, add documents in alphabetical order.
+- Unless there's a logical reason not to, structure the document in alphabetical order
+(headings, tables, and lists).
- Write in US English.
-- Use [single spaces][] instead of double spaces.
-- Jump a line between different markups (e.g., after every paragraph, header, list, etc)
- Capitalize "G" and "L" in GitLab.
-- Use sentence case for titles, headings, labels, menu items, and buttons.
- Use title case when referring to [features](https://about.gitlab.com/features/) or
- [products](https://about.gitlab.com/pricing/) (e.g., GitLab Runner, Geo,
- Issue Boards, GitLab Core, Git, Prometheus, Kubernetes, etc), and methods or methodologies
- (e.g., Continuous Integration, Continuous Deployment, Scrum, Agile, etc). Note that
- some features are also objects (e.g. "Merge Requests" and "merge requests").
+[products](https://about.gitlab.com/pricing/) (e.g., GitLab Runner, Geo,
+Issue Boards, GitLab Core, Git, Prometheus, Kubernetes, etc), and methods or methodologies
+(e.g., Continuous Integration, Continuous Deployment, Scrum, Agile, etc). Note that
+some features are also objects (e.g. "GitLab's Merge Requests support X." and "Create a new merge request for Z.").
-## Formatting
+## Text
+
+- Split up long lines (wrap text), this makes it much easier to review and edit. Only
+ double line breaks are shown as a full line break by creating new paragraphs.
+ 80-100 characters is the recommended line length.
+- Use sentence case for titles, headings, labels, menu items, and buttons.
+- Jump a line between different markups (e.g., after every paragraph, header, list, etc). Example:
-- Use double asterisks (`**`) to mark a word or text in bold (`**bold**`).
-- Use undescore (`_`) for text in italics (`_italic_`).
-- Put an empty line between different markups. For example:
```md
## Header
Paragraph.
- - List item
- - List item
+ - List item 1
+ - List item 2
```
-### Punctuation
+## Emphasis
-For punctuation rules, please refer to the [GitLab UX guide](https://design.gitlab.com/content/punctuation/).
+- Use double asterisks (`**`) to mark a word or text in bold (`**bold**`).
+- Use undescore (`_`) for text in italics (`_italic_`).
+- Use greater than (`>`) for blockquotes.
+
+## Punctuation
+
+Check the general punctuation rules for the GitLab documentation on the table below.
+Check specific punctuation rules for [list items](#list-items) below.
+
+| Rule | Example |
+| ---- | ------- |
+| Always end full sentences with a period. | _For a complete overview, read through this document._|
+| Always add a space after a period when beginning a new sentence | _For a complete overview, check this doc. For other references, check out this guide._ |
+| Do not use double spaces. | --- |
+| Do not use tabs for indentation. Use spaces instead. You can configure your code editor to output spaces instead of tabs when pressing the tab key. | --- |
+| Use serial commas ("Oxford commas") before the final 'and/or' in a list. | _You can create new issues, merge requests, and milestones._ |
+| Always add a space before and after dashes when using it in a sentence (for replacing a comma, for example). | _You should try this - or not._ |
+| Always use lowercase after a colon. | _Related Issues: a way to create a relationship between issues._ |
+
+## List items
+
+- Always start list items with a capital letter.
+- Always leave a blank line before and after a list.
+- Begin a line with spaces (not tabs) to denote a subitem.
+- To nest subitems, indent them with two spaces.
+- To nest code blocks, indent them with four spaces.
+- Only use ordered lists when their items describe a sequence of steps to follow.
-### Ordered and unordered lists
+**Markup:**
-- Use dashes (`-`) for unordered lists instead of asterisks (`*`).
-- Use the number one (`1`) for ordered lists.
+- Use dashes (`- `) for unordered lists instead of asterisks (`* `).
+- Use the number one (`1`) for each item in an ordered list.
+When rendered, the list items will appear with sequential numbering.
+
+**Punctuation:**
+
+- Do not add commas (`,`) or semicolons (`;`) to the end of a list item.
+- Only add periods to the end of a list item if the item consists of a complete sentence. The [definition of full sentence](https://www2.le.ac.uk/offices/ld/resources/writing/grammar/grammar-guides/sentence) is: _"a complete sentence always contains a verb, expresses a complete idea, and makes sense standing alone"_.
+- Be consistent throughout the list: if the majority of the items do not end in a period, do not end any of the items in a period, even if they consist of a complete sentence. The opposite is also valid: if the majority of the items end with a period, end all with a period.
- Separate list items from explanatory text with a colon (`:`). For example:
+
```md
The list is as follows:
- - First item: This explains the first item.
- - Second item: This explains the second item.
+ - First item: this explains the first item.
+ - Second item: this explains the second item.
```
-- For further guidance on punctuation in bullet lists, please refer to the [GitLab UX guide](https://design.gitlab.com/content/punctuation/).
+
+**Examples:**
+
+Do:
+
+- First list item
+- Second list item
+- Third list item
+
+Don't:
+
+- First list item
+- Second list item
+- Third list item.
+
+Do:
+
+- Let's say this is a complete sentence.
+- Let's say this is also a complete sentence.
+- Not a complete sentence.
+
+Don't:
+
+- Let's say this is a complete sentence.
+- Let's say this is also a complete sentence.
+- Not a complete sentence
+
+## Quotes
+
+Valid for markdown content only, not for frontmatter entries:
+
+- Standard quotes: double quotes (`"`). Example: "This is wrapped in double quotes".
+- Quote within a quote: double quotes (`"`) wrap single quotes (`'`). Example: "I am 'quoting' something within a quote".
+
+For other punctuation rules, please refer to the
+[GitLab UX guide](https://design.gitlab.com/content/punctuation/).
## Headings
- Add **only one H1** in each document, by adding `#` at the beginning of
it (when using markdown). The `h1` will be the document `<title>`.
-- Start with an h2 (`##`), and respect the order h2 > h3 > h4 > h5 > h6.
- Never skip the hierarchy level, such as h2 > h4
+- Start with an `h2` (`##`), and respect the order `h2` > `h3` > `h4` > `h5` > `h6`.
+ Never skip the hierarchy level, such as `h2` > `h4`
- Avoid putting numbers in headings. Numbers shift, hence documentation anchor
links shift too, which eventually leads to dead links. If you think it is
compelling to add numbers in headings, make sure to at least discuss it with
@@ -96,21 +173,19 @@ For punctuation rules, please refer to the [GitLab UX guide](https://design.gitl
- Avoid adding things that show ephemeral statuses. For example, if a feature is
considered beta or experimental, put this info in a note, not in the heading.
- When introducing a new document, be careful for the headings to be
- grammatically and syntactically correct. Mention one or all
- of the following GitLab members for a review: `@axil` or `@marcia`.
+ grammatically and syntactically correct. Mention an [assigned technical writer (TW)](https://about.gitlab.com/handbook/product/categories/)
+ for review.
This is to ensure that no document with wrong heading is going
live without an audit, thus preventing dead links and redirection issues when
corrected.
- Leave exactly one new line after a heading.
+- Do not use links in headings.
+- Add the corresponding [product badge](#product-badges) according to the tier the feature belongs.
## Links
-- Use the regular inline link markdown markup `[Text](https://example.com)`.
- It's easier to read, review, and maintain.
-- If there's a link that repeats several times through the same document,
- you can use `[Text][identifier]` and at the bottom of the section or the
- document add: `[identifier]: https://example.com`, in which case, we do
- encourage you to also add an alternative text: `[identifier]: https://example.com "Alternative text"` that appears when hovering your mouse on a link.
+- Use inline link markdown markup `[Text](https://example.com)`.
+ It's easier to read, review, and maintain. **Do not** use `[Text][identifier]`.
- To link to internal documentation, use relative links, not full URLs. Use `../` to
navigate tp high-level directories, and always add the file name `file.md` at the
end of the link with the `.md` extension, not `.html`.
@@ -128,11 +203,12 @@ For punctuation rules, please refer to the [GitLab UX guide](https://design.gitl
To indicate the steps of navigation through the UI:
+
- Use the exact word as shown in the UI, including any capital letters as-is.
-- Use bold text for navigation items and the char `>` as separator
- (e.g., `Navigate to your project's **Settings > CI/CD**` ).
+- Use bold text for navigation items and the char "greater than" (`>`) as separator
+(e.g., `Navigate to your project's **Settings > CI/CD**` ).
- If there are any expandable menus, make sure to mention that the user
- needs to expand the tab to find the settings you're referring to.
+needs to expand the tab to find the settings you're referring to (e.g., `Navigate to your project's **Settings > CI/CD** and expand **General pipelines**`).
## Images
@@ -141,13 +217,13 @@ To indicate the steps of navigation through the UI:
names with the name of the document that they will be included in. For
example, if there is a document called `twitter.md`, then a valid image name
could be `twitter_login_screen.png`.
-- Images should have a specific, non-generic name that will differentiate them.
+- Images should have a specific, non-generic name that will differentiate and describe them properly.
- Keep all file names in lower case.
- Consider using PNG images instead of JPEG.
- Compress all images with <https://tinypng.com/> or similar tool.
- Compress gifs with <https://ezgif.com/optimize> or similar tool.
- Images should be used (only when necessary) to _illustrate_ the description
- of a process, not to _replace_ it.
+of a process, not to _replace_ it.
- Max image size: 100KB (gifs included).
- The GitLab docs do not support videos yet.
@@ -164,13 +240,39 @@ Inside the document:
- If a heading is placed right after an image, always add three dashes (`---`)
between the image and the heading.
+## Code blocks
+
+- Always wrap code added to a sentence in inline code blocks (``` ` ```).
+E.g., `.gitlab-ci.yml`, `git add .`, `CODEOWNERS`, `only: master`.
+File names, commands, entries, and anything that refers to code should be added to code blocks.
+To make things easier for the user, always add a full code block for things that can be
+useful to copy and paste, as they can easily do it with the button on code blocks.
+- For regular code blocks, always use a highlighting class corresponding to the
+language for better readability. Examples:
+
+ ```md
+ ```ruby
+ Ruby code
+ ```
+
+ ```js
+ JavaScript code
+ ```
+
+ ```md
+ Markdown code
+ ```
+ ```
+
+- For a complete reference on code blocks, check the [Kramdown guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/#code-blocks).
+
## Alert boxes
Whenever you want to call the attention to a particular sentence,
use the following markup for highlighting.
_Note that the alert boxes only work for one paragraph only. Multiple paragraphs,
-lists, headers, etc will not render correctly._
+lists, headers, etc will not render correctly. For multiple lines, use blockquotes instead._
### Note
@@ -234,6 +336,31 @@ which renders in docs.gitlab.com to:
If the text spans across multiple lines it's OK to split the line.
+For multiple paragraphs, use the symbol `>` before every line:
+
+```md
+> This is the first paragraph.
+>
+> This is the second paragraph.
+>
+> - This is a list item
+> - Second item in the list
+>
+> ### This is an `h3`
+```
+
+Which renders to:
+
+> This is the first paragraph.
+>
+> This is the second paragraph.
+>
+> - This is a list item
+> - Second item in the list
+>
+> ### This is an `h3`
+>{:.no_toc}
+
## Specific sections and terms
To mention and/or reference specific terms in GitLab, please follow the styles
@@ -290,18 +417,18 @@ feature availability:
To exclude GitLab.com tiers (when the feature is not available in GitLab.com), add the
keyword "only":
+- For GitLab Core: `**[CORE ONLY]**`.
- For GitLab Starter: `**[STARTER ONLY]**`.
- For GitLab Premium: `**[PREMIUM ONLY]**`.
- For GitLab Ultimate: `**[ULTIMATE ONLY]**`.
-- For GitLab Core: `**[CORE ONLY]**`.
The tier should be ideally added to headers, so that the full badge will be displayed.
However, it can be also mentioned from paragraphs, list items, and table cells. For these cases,
-the tier mention will be represented by an orange question mark.
+the tier mention will be represented by an orange question mark that will show the tiers on hover.
E.g., `**[STARTER]**` renders **[STARTER]**, `**[STARTER ONLY]**` renders **[STARTER ONLY]**.
The absence of tiers' mentions mean that the feature is available in GitLab Core,
-GitLab.com Free, and higher tiers.
+GitLab.com Free, and all higher tiers.
#### How it works
@@ -348,8 +475,8 @@ prefer to document it in the CE docs to avoid duplication.
Configuration settings include:
-- Settings that touch configuration files in `config/`.
-- NGINX settings and settings in `lib/support/` in general.
+1. Settings that touch configuration files in `config/`.
+1. NGINX settings and settings in `lib/support/` in general.
When there is a list of steps to perform, usually that entails editing the
configuration file and reconfiguring/restarting GitLab. In such case, follow
@@ -386,13 +513,13 @@ the style below as a guide:
In this case:
-- before each step list the installation method is declared in bold
-- three dashes (`---`) are used to create a horizontal line and separate the
+- Before each step list the installation method is declared in bold
+- Three dashes (`---`) are used to create a horizontal line and separate the
two methods
-- the code blocks are indented one or more spaces under the list item to render
+- The code blocks are indented one or more spaces under the list item to render
correctly
-- different highlighting languages are used for each config in the code block
-- the [references](#references) guide is used for reconfigure/restart
+- Different highlighting languages are used for each config in the code block
+- The [references](#references) guide is used for reconfigure/restart
### Fake tokens
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index 93aa41e9a98..6c6119a2691 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -1,6 +1,11 @@
-# Markdown
+# GitLab Markdown
-This markdown guide is valid for GitLab's system markdown entries and files.
+This markdown guide is **valid for GitLab's system markdown entries and files**.
+It is not valid for the [GitLab documentation website](https://docs.gitlab.com)
+nor [GitLab's main website](https://about.gitlab.com), as they both use
+[Kramdown](https://kramdown.gettalong.org) as their markdown engine.
+The documentation website uses an extended Kramdown gem, [GitLab Kramdown](https://gitlab.com/gitlab-org/gitlab_kramdown).
+Consult the [GitLab Kramdown Guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/) for a complete Kramdown reference._
## GitLab Flavored Markdown (GFM)
@@ -8,21 +13,21 @@ GitLab uses "GitLab Flavored Markdown" (GFM). It extends the [CommonMark specifi
You can use GFM in the following areas:
-- comments
-- issues
-- merge requests
-- milestones
-- snippets (the snippet must be named with a `.md` extension)
-- wiki pages
-- markdown documents inside the repository
+- Comments
+- Issues
+- Merge requests
+- Milestones
+- Snippets (the snippet must be named with a `.md` extension)
+- Wiki pages
+- Markdown documents inside repositories
You can also use other rich text files in GitLab. You might have to install a
dependency to do so. Please see the [`github-markup` gem readme](https://github.com/gitlabhq/markup#markups) for more information.
> **Notes:**
>
-> For the best result, we encourage you to check this document out as rendered
-> by GitLab itself: [markdown.md]
+> For the best result, we encourage you to check this document out as [rendered
+> by GitLab itself](markdown.md).
>
> As of 11.1, GitLab uses the [CommonMark Ruby Library][commonmarker] for Markdown
processing of all new issues, merge requests, comments, and other Markdown content
@@ -30,6 +35,9 @@ in the GitLab system. As of 11.3, wiki pages and Markdown files (`.md`) in the
repositories are also processed with CommonMark. Older content in issues/comments
are still processed using the [Redcarpet Ruby library][redcarpet].
>
+> The documentation website had its [markdown engine migrated from Redcarpet to Kramdown](https://gitlab.com/gitlab-com/gitlab-docs/merge_requests/108)
+in October 2018.
+>
> _Where there are significant differences, we will try to call them out in this document._
### Transitioning to CommonMark
diff --git a/doc/user/project/import/manifest.md b/doc/user/project/import/manifest.md
index 24bf6541a9d..baf410d9c9e 100644
--- a/doc/user/project/import/manifest.md
+++ b/doc/user/project/import/manifest.md
@@ -29,7 +29,7 @@ Below is a valid example of a manifest file:
```xml
<manifest>
- <remote review="https://android-review.googlesource.com/" />
+ <remote review="https://android.googlesource.com/" />
<project path="build/make" name="platform/build" />
<project path="build/blueprint" name="platform/build/blueprint" />
@@ -38,10 +38,10 @@ Below is a valid example of a manifest file:
As a result, the following projects will be created:
-| GitLab | Import URL |
-|---|---|
-| https://gitlab.com/YOUR_GROUP/build/make | https://android-review.googlesource.com/platform/build |
-| https://gitlab.com/YOUR_GROUP/build/blueprint | https://android-review.googlesource.com/platform/build/blueprint |
+| GitLab | Import URL |
+|:------------------------------------------------|:------------------------------------------------------------|
+| `https://gitlab.com/YOUR_GROUP/build/make` | <https://android.googlesource.com/platform/build> |
+| `https://gitlab.com/YOUR_GROUP/build/blueprint` | <https://android.googlesource.com/platform/build/blueprint> |
## Importing the repositories
diff --git a/doc/user/project/integrations/discord_notifications.md b/doc/user/project/integrations/discord_notifications.md
new file mode 100644
index 00000000000..e157f5cc106
--- /dev/null
+++ b/doc/user/project/integrations/discord_notifications.md
@@ -0,0 +1,29 @@
+# Discord Notifications service
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22684) in GitLab 11.5.
+
+The Discord Notifications service sends event notifications from GitLab to the channel for which the webhook was created.
+
+To send GitLab event notifications to a Discord channel, create a webhook in Discord and configure it in GitLab.
+
+## Create webhook
+
+1. Open the Discord channel you want to receive GitLab event notifications.
+1. From the channel menu, select **Edit channel**.
+1. Click on **Webhooks** menu item.
+1. Click the **Create Webhook** button and fill in the name of the bot that will post the messages. Optionally, edit the avatar.
+1. Note the URL from the **WEBHOOK URL** field.
+1. Click the **Save** button.
+
+## Configure created webhook in GitLab
+
+With the webhook URL created in the Discord channel, you can set up the Discord Notifications service in GitLab.
+
+1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services) in your project's settings. That is, **Project > Settings > Integrations**.
+1. Select the **Discord Notifications** project service to configure it.
+1. Check the **Active** checkbox to turn on the service.
+1. Check the checkboxes corresponding to the GitLab events for which you want to send notifications to Discord.
+1. Paste the webhook URL that you copied from the create Discord webhook step.
+1. Configure the remaining options and click the **Save changes** button.
+
+The Discord channel you created the webhook for will now receive notification of the GitLab events that were configured.
diff --git a/doc/user/project/integrations/project_services.md b/doc/user/project/integrations/project_services.md
index efb0381d7aa..be45ce46dfd 100644
--- a/doc/user/project/integrations/project_services.md
+++ b/doc/user/project/integrations/project_services.md
@@ -30,6 +30,7 @@ Click on the service links to see further configuration instructions and details
| [Bugzilla](bugzilla.md) | Bugzilla issue tracker |
| Campfire | Simple web-based real-time group chat |
| Custom Issue Tracker | Custom issue tracker |
+| [Discord Notifications](discord_notifications.md) | Receive event notifications in Discord |
| Drone CI | Continuous Integration platform built on Docker, written in Go |
| [Emails on push](emails_on_push.md) | Email the commits and diff of each push to a list of recipients |
| External Wiki | Replaces the link to the internal wiki with a link to an external wiki |
diff --git a/lib/api/services.rb b/lib/api/services.rb
index 0ae05ce08f1..1cb3b8a7277 100644
--- a/lib/api/services.rb
+++ b/lib/api/services.rb
@@ -298,6 +298,14 @@ module API
desc: 'Title'
}
],
+ 'discord' => [
+ {
+ required: true,
+ name: :webhook,
+ type: String,
+ desc: 'Discord webhook. e.g. https://discordapp.com/api/webhooks/…'
+ }
+ ],
'drone-ci' => [
{
required: true,
@@ -677,6 +685,7 @@ module API
BuildkiteService,
CampfireService,
CustomIssueTrackerService,
+ DiscordService,
DroneCiService,
EmailsOnPushService,
ExternalWikiService,
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
index 016682e5a3d..b180860899a 100755
--- a/scripts/review_apps/review-apps.sh
+++ b/scripts/review_apps/review-apps.sh
@@ -136,6 +136,7 @@ HELM_CMD=$(cat << EOF
helm upgrade --install \
--wait \
--timeout 600 \
+ --set global.appConfig.enableUsagePing=false \
--set releaseOverride="$CI_ENVIRONMENT_SLUG" \
--set global.hosts.hostSuffix="$HOST_SUFFIX" \
--set global.hosts.domain="$REVIEW_APPS_DOMAIN" \
diff --git a/spec/features/issues/user_views_issue_spec.rb b/spec/features/issues/user_views_issue_spec.rb
index 117e5986f29..330b6f0e77a 100644
--- a/spec/features/issues/user_views_issue_spec.rb
+++ b/spec/features/issues/user_views_issue_spec.rb
@@ -1,9 +1,9 @@
require "spec_helper"
describe "User views issue" do
- set(:project) { create(:project_empty_repo, :public) }
- set(:user) { create(:user) }
- set(:issue) { create(:issue, project: project, description: "# Description header", author: user) }
+ let(:project) { create(:project_empty_repo, :public) }
+ let(:user) { create(:user) }
+ let(:issue) { create(:issue, project: project, description: "# Description header", author: user) }
before do
project.add_developer(user)
diff --git a/spec/javascripts/notes/stores/actions_spec.js b/spec/javascripts/notes/stores/actions_spec.js
index 0c0bc45b201..fcdd834e4a0 100644
--- a/spec/javascripts/notes/stores/actions_spec.js
+++ b/spec/javascripts/notes/stores/actions_spec.js
@@ -396,6 +396,9 @@ describe('Actions Notes Store', () => {
{
type: 'updateMergeRequestWidget',
},
+ {
+ type: 'startTaskList',
+ },
],
done,
);
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index f4efa450cca..1d184375a52 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -198,6 +198,7 @@ project:
- last_event
- services
- campfire_service
+- discord_service
- drone_ci_service
- emails_on_push_service
- pipelines_email_service
diff --git a/spec/models/project_services/discord_service_spec.rb b/spec/models/project_services/discord_service_spec.rb
new file mode 100644
index 00000000000..be82f223478
--- /dev/null
+++ b/spec/models/project_services/discord_service_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+describe DiscordService do
+ it_behaves_like "chat service", "Discord notifications" do
+ let(:client) { Discordrb::Webhooks::Client }
+ let(:client_arguments) { { url: webhook_url } }
+ let(:content_key) { :content }
+ end
+end
diff --git a/spec/models/project_services/hangouts_chat_service_spec.rb b/spec/models/project_services/hangouts_chat_service_spec.rb
index cfa55188a64..0505ac9b49c 100644
--- a/spec/models/project_services/hangouts_chat_service_spec.rb
+++ b/spec/models/project_services/hangouts_chat_service_spec.rb
@@ -1,246 +1,11 @@
-require 'spec_helper'
+# frozen_string_literal: true
-describe HangoutsChatService do
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:webhook) }
- it_behaves_like 'issue tracker service URL attribute', :webhook
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:webhook) }
- end
- end
-
- describe '#execute' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
- let(:webhook_url) { 'https://example.gitlab.com/' }
-
- before do
- allow(subject).to receive_messages(
- project: project,
- project_id: project.id,
- service_hook: true,
- webhook: webhook_url
- )
-
- WebMock.stub_request(:post, webhook_url)
- end
-
- shared_examples 'Hangouts Chat service' do
- it 'calls Hangouts Chat API' do
- subject.execute(sample_data)
-
- expect(WebMock)
- .to have_requested(:post, webhook_url)
- .with { |req| req.body =~ /\A{"text":.+}\Z/ }
- .once
- end
- end
-
- context 'with push events' do
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build_sample(project, user)
- end
-
- it_behaves_like 'Hangouts Chat service'
-
- it 'specifies the webhook when it is configured' do
- expect(HangoutsChat::Sender).to receive(:new).with(webhook_url).and_return(double(:hangouts_chat_service).as_null_object)
-
- subject.execute(sample_data)
- end
-
- context 'with not default branch' do
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build(project, user, nil, nil, 'not-the-default-branch')
- end
-
- context 'when notify_only_default_branch enabled' do
- before do
- subject.notify_only_default_branch = true
- end
-
- it 'does not call the Hangouts Chat API' do
- result = subject.execute(sample_data)
-
- expect(result).to be_falsy
- end
- end
-
- context 'when notify_only_default_branch disabled' do
- before do
- subject.notify_only_default_branch = false
- end
-
- it_behaves_like 'Hangouts Chat service'
- end
- end
- end
-
- context 'with issue events' do
- let(:opts) { { title: 'Awesome issue', description: 'please fix' } }
- let(:sample_data) do
- service = Issues::CreateService.new(project, user, opts)
- issue = service.execute
- service.hook_data(issue, 'open')
- end
-
- it_behaves_like 'Hangouts Chat service'
- end
-
- context 'with merge events' do
- let(:opts) do
- {
- title: 'Awesome merge_request',
- description: 'please fix',
- source_branch: 'feature',
- target_branch: 'master'
- }
- end
-
- let(:sample_data) do
- service = MergeRequests::CreateService.new(project, user, opts)
- merge_request = service.execute
- service.hook_data(merge_request, 'open')
- end
-
- before do
- project.add_developer(user)
- end
+require "spec_helper"
- it_behaves_like 'Hangouts Chat service'
- end
-
- context 'with wiki page events' do
- let(:opts) do
- {
- title: 'Awesome wiki_page',
- content: 'Some text describing some thing or another',
- format: 'md',
- message: 'user created page: Awesome wiki_page'
- }
- end
- let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: opts) }
- let(:sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, 'create') }
-
- it_behaves_like 'Hangouts Chat service'
- end
-
- context 'with note events' do
- let(:sample_data) { Gitlab::DataBuilder::Note.build(note, user) }
-
- context 'with commit comment' do
- let(:note) do
- create(:note_on_commit, author: user,
- project: project,
- commit_id: project.repository.commit.id,
- note: 'a comment on a commit')
- end
-
- it_behaves_like 'Hangouts Chat service'
- end
-
- context 'with merge request comment' do
- let(:note) do
- create(:note_on_merge_request, project: project,
- note: 'merge request note')
- end
-
- it_behaves_like 'Hangouts Chat service'
- end
-
- context 'with issue comment' do
- let(:note) do
- create(:note_on_issue, project: project, note: 'issue note')
- end
-
- it_behaves_like 'Hangouts Chat service'
- end
-
- context 'with snippet comment' do
- let(:note) do
- create(:note_on_project_snippet, project: project,
- note: 'snippet note')
- end
-
- it_behaves_like 'Hangouts Chat service'
- end
- end
-
- context 'with pipeline events' do
- let(:pipeline) do
- create(:ci_pipeline,
- project: project, status: status,
- sha: project.commit.sha, ref: project.default_branch)
- end
- let(:sample_data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
-
- context 'with failed pipeline' do
- let(:status) { 'failed' }
-
- it_behaves_like 'Hangouts Chat service'
- end
-
- context 'with succeeded pipeline' do
- let(:status) { 'success' }
-
- context 'with default notify_only_broken_pipelines' do
- it 'does not call Hangouts Chat API' do
- result = subject.execute(sample_data)
-
- expect(result).to be_falsy
- end
- end
-
- context 'when notify_only_broken_pipelines is false' do
- before do
- subject.notify_only_broken_pipelines = false
- end
-
- it_behaves_like 'Hangouts Chat service'
- end
- end
-
- context 'with not default branch' do
- let(:pipeline) do
- create(:ci_pipeline, project: project, status: 'failed', ref: 'not-the-default-branch')
- end
-
- context 'when notify_only_default_branch enabled' do
- before do
- subject.notify_only_default_branch = true
- end
-
- it 'does not call the Hangouts Chat API' do
- result = subject.execute(sample_data)
-
- expect(result).to be_falsy
- end
- end
-
- context 'when notify_only_default_branch disabled' do
- before do
- subject.notify_only_default_branch = false
- end
-
- it_behaves_like 'Hangouts Chat service'
- end
- end
- end
+describe HangoutsChatService do
+ it_behaves_like "chat service", "Hangouts Chat" do
+ let(:client) { HangoutsChat::Sender }
+ let(:client_arguments) { webhook_url }
+ let(:content_key) { :text }
end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 471f19f9b7c..b2ca6e98068 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -33,6 +33,7 @@ describe Project do
it { is_expected.to have_one(:asana_service) }
it { is_expected.to have_many(:boards) }
it { is_expected.to have_one(:campfire_service) }
+ it { is_expected.to have_one(:discord_service) }
it { is_expected.to have_one(:drone_ci_service) }
it { is_expected.to have_one(:emails_on_push_service) }
it { is_expected.to have_one(:pipelines_email_service) }
diff --git a/spec/support/shared_examples/models/chat_service_spec.rb b/spec/support/shared_examples/models/chat_service_spec.rb
new file mode 100644
index 00000000000..cf1d52a9616
--- /dev/null
+++ b/spec/support/shared_examples/models/chat_service_spec.rb
@@ -0,0 +1,242 @@
+require "spec_helper"
+
+shared_examples_for "chat service" do |service_name|
+ describe "Associations" do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe "Validations" do
+ context "when service is active" do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:webhook) }
+ it_behaves_like "issue tracker service URL attribute", :webhook
+ end
+
+ context "when service is inactive" do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:webhook) }
+ end
+ end
+
+ describe "#execute" do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:webhook_url) { "https://example.gitlab.com/" }
+
+ before do
+ allow(subject).to receive_messages(
+ project: project,
+ project_id: project.id,
+ service_hook: true,
+ webhook: webhook_url
+ )
+
+ WebMock.stub_request(:post, webhook_url)
+ end
+
+ shared_examples "#{service_name} service" do
+ it "calls #{service_name} API" do
+ subject.execute(sample_data)
+
+ expect(WebMock).to have_requested(:post, webhook_url).with { |req| req.body =~ /\A{"#{content_key}":.+}\Z/ }.once
+ end
+ end
+
+ context "with push events" do
+ let(:sample_data) do
+ Gitlab::DataBuilder::Push.build_sample(project, user)
+ end
+
+ it_behaves_like "#{service_name} service"
+
+ it "specifies the webhook when it is configured" do
+ expect(client).to receive(:new).with(client_arguments).and_return(double(:chat_service).as_null_object)
+
+ subject.execute(sample_data)
+ end
+
+ context "with not default branch" do
+ let(:sample_data) do
+ Gitlab::DataBuilder::Push.build(project, user, nil, nil, "not-the-default-branch")
+ end
+
+ context "when notify_only_default_branch enabled" do
+ before do
+ subject.notify_only_default_branch = true
+ end
+
+ it "does not call the Discord Webhooks API" do
+ result = subject.execute(sample_data)
+
+ expect(result).to be_falsy
+ end
+ end
+
+ context "when notify_only_default_branch disabled" do
+ before do
+ subject.notify_only_default_branch = false
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+ end
+ end
+
+ context "with issue events" do
+ let(:opts) { { title: "Awesome issue", description: "please fix" } }
+ let(:sample_data) do
+ service = Issues::CreateService.new(project, user, opts)
+ issue = service.execute
+ service.hook_data(issue, "open")
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with merge events" do
+ let(:opts) do
+ {
+ title: "Awesome merge_request",
+ description: "please fix",
+ source_branch: "feature",
+ target_branch: "master"
+ }
+ end
+
+ let(:sample_data) do
+ service = MergeRequests::CreateService.new(project, user, opts)
+ merge_request = service.execute
+ service.hook_data(merge_request, "open")
+ end
+
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with wiki page events" do
+ let(:opts) do
+ {
+ title: "Awesome wiki_page",
+ content: "Some text describing some thing or another",
+ format: "md",
+ message: "user created page: Awesome wiki_page"
+ }
+ end
+ let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: opts) }
+ let(:sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, "create") }
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with note events" do
+ let(:sample_data) { Gitlab::DataBuilder::Note.build(note, user) }
+
+ context "with commit comment" do
+ let(:note) do
+ create(:note_on_commit,
+ author: user,
+ project: project,
+ commit_id: project.repository.commit.id,
+ note: "a comment on a commit")
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with merge request comment" do
+ let(:note) do
+ create(:note_on_merge_request, project: project, note: "merge request note")
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with issue comment" do
+ let(:note) do
+ create(:note_on_issue, project: project, note: "issue note")
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with snippet comment" do
+ let(:note) do
+ create(:note_on_project_snippet, project: project, note: "snippet note")
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+ end
+
+ context "with pipeline events" do
+ let(:pipeline) do
+ create(:ci_pipeline,
+ project: project, status: status,
+ sha: project.commit.sha, ref: project.default_branch)
+ end
+ let(:sample_data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
+
+ context "with failed pipeline" do
+ let(:status) { "failed" }
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with succeeded pipeline" do
+ let(:status) { "success" }
+
+ context "with default notify_only_broken_pipelines" do
+ it "does not call Discord Webhooks API" do
+ result = subject.execute(sample_data)
+
+ expect(result).to be_falsy
+ end
+ end
+
+ context "when notify_only_broken_pipelines is false" do
+ before do
+ subject.notify_only_broken_pipelines = false
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+ end
+
+ context "with not default branch" do
+ let(:pipeline) do
+ create(:ci_pipeline, project: project, status: "failed", ref: "not-the-default-branch")
+ end
+
+ context "when notify_only_default_branch enabled" do
+ before do
+ subject.notify_only_default_branch = true
+ end
+
+ it "does not call the Discord Webhooks API" do
+ result = subject.execute(sample_data)
+
+ expect(result).to be_falsy
+ end
+ end
+
+ context "when notify_only_default_branch disabled" do
+ before do
+ subject.notify_only_default_branch = false
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+ end
+ end
+ end
+end