Commit 3bc0a118 authored by Marcel Amirault's avatar Marcel Amirault Committed by Evan Read

Standardize markdown in dev and workflow

Delete trailing whitespace, fix blockquotes, fix note
boxes, with indentation, clean up tables, etc.
parent a749fcbe
...@@ -38,7 +38,7 @@ Advantages over [`spyOn()`]: ...@@ -38,7 +38,7 @@ Advantages over [`spyOn()`]:
- no need to create response objects - no need to create response objects
- does not allow call through (which we want to avoid) - does not allow call through (which we want to avoid)
- simple API to test error cases - simple API to test error cases
- provides `replyOnce()` to allow for different responses - provides `replyOnce()` to allow for different responses
We have also decided against using [axios interceptors] because they are not suitable for mocking. We have also decided against using [axios interceptors] because they are not suitable for mocking.
......
...@@ -21,31 +21,31 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/ ...@@ -21,31 +21,31 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/
1. **Never Ever EVER** disable eslint globally for a file 1. **Never Ever EVER** disable eslint globally for a file
```javascript ```javascript
// bad // bad
/* eslint-disable */ /* eslint-disable */
// better // better
/* eslint-disable some-rule, some-other-rule */ /* eslint-disable some-rule, some-other-rule */
// best // best
// nothing :) // nothing :)
``` ```
1. If you do need to disable a rule for a single violation, try to do it as locally as possible 1. If you do need to disable a rule for a single violation, try to do it as locally as possible
```javascript ```javascript
// bad // bad
/* eslint-disable no-new */ /* eslint-disable no-new */
import Foo from 'foo'; import Foo from 'foo';
new Foo(); new Foo();
// better // better
import Foo from 'foo'; import Foo from 'foo';
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
new Foo(); new Foo();
``` ```
1. There are few rules that we need to disable due to technical debt. Which are: 1. There are few rules that we need to disable due to technical debt. Which are:
...@@ -56,16 +56,16 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/ ...@@ -56,16 +56,16 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/
followed by any global declarations, then a blank newline prior to any imports or code. followed by any global declarations, then a blank newline prior to any imports or code.
```javascript ```javascript
// bad // bad
/* global Foo */ /* global Foo */
/* eslint-disable no-new */ /* eslint-disable no-new */
import Bar from './bar'; import Bar from './bar';
// good // good
/* eslint-disable no-new */ /* eslint-disable no-new */
/* global Foo */ /* global Foo */
import Bar from './bar'; import Bar from './bar';
``` ```
1. **Never** disable the `no-undef` rule. Declare globals with `/* global Foo */` instead. 1. **Never** disable the `no-undef` rule. Declare globals with `/* global Foo */` instead.
...@@ -73,23 +73,23 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/ ...@@ -73,23 +73,23 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/
1. When declaring multiple globals, always use one `/* global [name] */` line per variable. 1. When declaring multiple globals, always use one `/* global [name] */` line per variable.
```javascript ```javascript
// bad // bad
/* globals Flash, Cookies, jQuery */ /* globals Flash, Cookies, jQuery */
// good // good
/* global Flash */ /* global Flash */
/* global Cookies */ /* global Cookies */
/* global jQuery */ /* global jQuery */
``` ```
1. Use up to 3 parameters for a function or class. If you need more accept an Object instead. 1. Use up to 3 parameters for a function or class. If you need more accept an Object instead.
```javascript ```javascript
// bad // bad
fn(p1, p2, p3, p4) {} fn(p1, p2, p3, p4) {}
// good // good
fn(options) {} fn(options) {}
``` ```
#### Modules, Imports, and Exports #### Modules, Imports, and Exports
...@@ -97,32 +97,32 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/ ...@@ -97,32 +97,32 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/
1. Use ES module syntax to import modules 1. Use ES module syntax to import modules
```javascript ```javascript
// bad // bad
const SomeClass = require('some_class'); const SomeClass = require('some_class');
// good // good
import SomeClass from 'some_class'; import SomeClass from 'some_class';
// bad // bad
module.exports = SomeClass; module.exports = SomeClass;
// good // good
export default SomeClass; export default SomeClass;
``` ```
Import statements are following usual naming guidelines, for example object literals use camel case: Import statements are following usual naming guidelines, for example object literals use camel case:
```javascript ```javascript
// some_object file // some_object file
export default { export default {
key: 'value', key: 'value',
}; };
// bad // bad
import ObjectLiteral from 'some_object'; import ObjectLiteral from 'some_object';
// good // good
import objectLiteral from 'some_object'; import objectLiteral from 'some_object';
``` ```
1. Relative paths: when importing a module in the same directory, a child 1. Relative paths: when importing a module in the same directory, a child
...@@ -171,22 +171,22 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/ ...@@ -171,22 +171,22 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/
1. Avoid adding to the global namespace. 1. Avoid adding to the global namespace.
```javascript ```javascript
// bad // bad
window.MyClass = class { /* ... */ }; window.MyClass = class { /* ... */ };
// good // good
export default class MyClass { /* ... */ } export default class MyClass { /* ... */ }
``` ```
1. Side effects are forbidden in any script which contains export 1. Side effects are forbidden in any script which contains export
```javascript ```javascript
// bad // bad
export default class MyClass { /* ... */ } export default class MyClass { /* ... */ }
document.addEventListener("DOMContentLoaded", function(event) { document.addEventListener("DOMContentLoaded", function(event) {
new MyClass(); new MyClass();
} }
``` ```
#### Data Mutation and Pure functions #### Data Mutation and Pure functions
...@@ -257,17 +257,17 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/ ...@@ -257,17 +257,17 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/
`.reduce` or `.filter` `.reduce` or `.filter`
```javascript ```javascript
const users = [ { name: 'Foo' }, { name: 'Bar' } ]; const users = [ { name: 'Foo' }, { name: 'Bar' } ];
// bad // bad
users.forEach((user, index) => { users.forEach((user, index) => {
user.id = index; user.id = index;
}); });
// good // good
const usersWithId = users.map((user, index) => { const usersWithId = users.map((user, index) => {
return Object.assign({}, user, { id: index }); return Object.assign({}, user, { id: index });
}); });
``` ```
#### Parse Strings into Numbers #### Parse Strings into Numbers
...@@ -275,14 +275,14 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/ ...@@ -275,14 +275,14 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/
1. `parseInt()` is preferable over `Number()` or `+` 1. `parseInt()` is preferable over `Number()` or `+`
```javascript ```javascript
// bad // bad
+'10' // 10 +'10' // 10
// good // good
Number('10') // 10 Number('10') // 10
// better // better
parseInt('10', 10); parseInt('10', 10);
``` ```
#### CSS classes used for JavaScript #### CSS classes used for JavaScript
...@@ -290,15 +290,15 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/ ...@@ -290,15 +290,15 @@ See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/
1. If the class is being used in Javascript it needs to be prepend with `js-` 1. If the class is being used in Javascript it needs to be prepend with `js-`
```html ```html
// bad // bad
<button class="add-user"> <button class="add-user">
Add User Add User
</button> </button>
// good // good
<button class="js-add-user"> <button class="js-add-user">
Add User Add User
</button> </button>
``` ```
### Vue.js ### Vue.js
...@@ -315,41 +315,41 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation. ...@@ -315,41 +315,41 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
1. Use a function in the bundle file to instantiate the Vue component: 1. Use a function in the bundle file to instantiate the Vue component:
```javascript ```javascript
// bad // bad
class { class {
init() { init() {
new Component({}) new Component({})
}
} }
}
// good // good
document.addEventListener('DOMContentLoaded', () => new Vue({ document.addEventListener('DOMContentLoaded', () => new Vue({
el: '#element', el: '#element',
components: { components: {
componentName componentName
}, },
render: createElement => createElement('component-name'), render: createElement => createElement('component-name'),
})); }));
``` ```
1. Do not use a singleton for the service or the store 1. Do not use a singleton for the service or the store
```javascript ```javascript
// bad // bad
class Store { class Store {
constructor() { constructor() {
if (!this.prototype.singleton) { if (!this.prototype.singleton) {
// do something // do something
}
} }
} }
}
// good // good
class Store { class Store {
constructor() { constructor() {
// do something // do something
}
} }
}
``` ```
1. Use `.vue` for Vue templates. Do not use `%template` in HAML. 1. Use `.vue` for Vue templates. Do not use `%template` in HAML.
...@@ -360,36 +360,36 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation. ...@@ -360,36 +360,36 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
1. **Reference Naming**: Use PascalCase for their instances: 1. **Reference Naming**: Use PascalCase for their instances:
```javascript ```javascript
// bad // bad
import cardBoard from 'cardBoard.vue' import cardBoard from 'cardBoard.vue'
components: { components: {
cardBoard, cardBoard,
}; };
// good // good
import CardBoard from 'cardBoard.vue' import CardBoard from 'cardBoard.vue'
components: { components: {
CardBoard, CardBoard,
}; };
``` ```
1. **Props Naming:** Avoid using DOM component prop names. 1. **Props Naming:** Avoid using DOM component prop names.
1. **Props Naming:** Use kebab-case instead of camelCase to provide props in templates. 1. **Props Naming:** Use kebab-case instead of camelCase to provide props in templates.
```javascript ```javascript
// bad // bad
<component class="btn"> <component class="btn">
// good // good
<component css-class="btn"> <component css-class="btn">
// bad // bad
<component myProp="prop" /> <component myProp="prop" />
// good // good
<component my-prop="prop" /> <component my-prop="prop" />
``` ```
[#34371]: https://gitlab.com/gitlab-org/gitlab-ce/issues/34371 [#34371]: https://gitlab.com/gitlab-org/gitlab-ce/issues/34371
...@@ -401,37 +401,37 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation. ...@@ -401,37 +401,37 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
1. With more than one attribute, all attributes should be on a new line: 1. With more than one attribute, all attributes should be on a new line:
```javascript ```javascript
// bad // bad
<component v-if="bar" <component v-if="bar"
param="baz" /> param="baz" />
<button class="btn">Click me</button> <button class="btn">Click me</button>
// good // good
<component <component
v-if="bar" v-if="bar"
param="baz" param="baz"
/> />
<button class="btn"> <button class="btn">
Click me Click me
</button> </button>
``` ```
1. The tag can be inline if there is only one attribute: 1. The tag can be inline if there is only one attribute:
```javascript ```javascript
// good // good
<component bar="bar" /> <component bar="bar" />
// good // good
<component <component
bar="bar" bar="bar"
/> />
// bad // bad
<component <component
bar="bar" /> bar="bar" />
``` ```
#### Quotes #### Quotes
...@@ -439,15 +439,15 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation. ...@@ -439,15 +439,15 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
1. Always use double quotes `"` inside templates and single quotes `'` for all other JS. 1. Always use double quotes `"` inside templates and single quotes `'` for all other JS.
```javascript ```javascript
// bad // bad
template: ` template: `
<button :class='style'>Button</button> <button :class='style'>Button</button>
` `
// good // good
template: ` template: `
<button :class="style">Button</button> <button :class="style">Button</button>
` `
``` ```
#### Props #### Props
...@@ -455,37 +455,37 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation. ...@@ -455,37 +455,37 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
1. Props should be declared as an object 1. Props should be declared as an object
```javascript ```javascript
// bad // bad
props: ['foo'] props: ['foo']
// good // good
props: { props: {
foo: { foo: {
type: String, type: String,
required: false, required: false,
default: 'bar' default: 'bar'
}
} }
}
``` ```
1. Required key should always be provided when declaring a prop 1. Required key should always be provided when declaring a prop
```javascript ```javascript
// bad // bad
props: { props: {
foo: { foo: {
type: String, type: String,
}
} }
}
// good // good
props: { props: {
foo: { foo: {
type: String, type: String,
required: false, required: false,
default: 'bar' default: 'bar'
}
} }
}
``` ```
1. Default key should be provided if the prop is not required. 1. Default key should be provided if the prop is not required.
...@@ -493,30 +493,30 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation. ...@@ -493,30 +493,30 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
On those a default key should not be provided. On those a default key should not be provided.
```javascript ```javascript
// good // good
props: { props: {
foo: { foo: {
type: String, type: String,
required: false, required: false,
}
} }
}
// good // good
props: { props: {
foo: { foo: {
type: String, type: String,
required: false, required: false,
default: 'bar' default: 'bar'
}
} }
}
// good // good
props: { props: {
foo: { foo: {
type: String, type: String,
required: true required: true
}
} }
}
``` ```
#### Data #### Data
...@@ -524,17 +524,17 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation. ...@@ -524,17 +524,17 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
1. `data` method should always be a function 1. `data` method should always be a function
```javascript ```javascript
// bad // bad
data: { data: {
foo: 'foo' foo: 'foo'
} }
// good // good
data() { data() {
return { return {
foo: 'foo' foo: 'foo'
}; };
} }
``` ```
#### Directives #### Directives
...@@ -542,31 +542,31 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation. ...@@ -542,31 +542,31 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
1. Shorthand `@` is preferable over `v-on` 1. Shorthand `@` is preferable over `v-on`
```javascript ```javascript
// bad // bad
<component v-on:click="eventHandler"/> <component v-on:click="eventHandler"/>
// good // good
<component @click="eventHandler"/> <component @click="eventHandler"/>
``` ```
1. Shorthand `:` is preferable over `v-bind` 1. Shorthand `:` is preferable over `v-bind`
```javascript ```javascript
// bad // bad
<component v-bind:class="btn"/> <component v-bind:class="btn"/>
// good // good
<component :class="btn"/> <component :class="btn"/>
``` ```
1. Shorthand `#` is preferable over `v-slot` 1. Shorthand `#` is preferable over `v-slot`
```javascript ```javascript
// bad // bad
<template v-slot:header></template> <template v-slot:header></template>
// good // good
<template #header></template> <template #header></template>
``` ```
#### Closing tags #### Closing tags
...@@ -574,11 +574,11 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation. ...@@ -574,11 +574,11 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
1. Prefer self closing component tags 1. Prefer self closing component tags
```javascript ```javascript
// bad // bad
<component></component> <component></component>
// good // good
<component /> <component />
``` ```
#### Ordering #### Ordering
...@@ -610,48 +610,48 @@ When using `v-for` you need to provide a *unique* `:key` attribute for each item ...@@ -610,48 +610,48 @@ When using `v-for` you need to provide a *unique* `:key` attribute for each item
1. If the elements of the array being iterated have an unique `id` it is advised to use it: 1. If the elements of the array being iterated have an unique `id` it is advised to use it:
```html ```html
<div <div
v-for="item in items" v-for="item in items"
:key="item.id" :key="item.id"
> >
<!-- content --> <!-- content -->
</div> </div>
``` ```
1. When the elements being iterated don't have a unique id, you can use the array index as the `:key` attribute 1. When the elements being iterated don't have a unique id, you can use the array index as the `:key` attribute
```html ```html
<div <div
v-for="(item, index) in items" v-for="(item, index) in items"
:key="index" :key="index"
> >
<!-- content --> <!-- content -->
</div> </div>
``` ```
1. When using `v-for` with `template` and there is more than one child element, the `:key` values must be unique. It's advised to use `kebab-case` namespaces. 1. When using `v-for` with `template` and there is more than one child element, the `:key` values must be unique. It's advised to use `kebab-case` namespaces.
```html ```html
<template v-for="(item, index) in items"> <template v-for="(item, index) in items">
<span :key="`span-${index}`"></span> <span :key="`span-${index}`"></span>
<button :key="`button-${index}`"></button> <button :key="`button-${index}`"></button>
</template> </template>
``` ```
1. When dealing with nested `v-for` use the same guidelines as above. 1. When dealing with nested `v-for` use the same guidelines as above.
```html ```html
<div <div
v-for="item in items" v-for="item in items"
:key="item.id" :key="item.id"
>
<span
v-for="element in array"
:key="element.id"
> >
<span <!-- content -->
v-for="element in array" </span>
:key="element.id" </div>
>
<!-- content -->
</span>
</div>
``` ```
Useful links: Useful links:
...@@ -664,19 +664,19 @@ Useful links: ...@@ -664,19 +664,19 @@ Useful links:
1. Tooltips: Do not rely on `has-tooltip` class name for Vue components 1. Tooltips: Do not rely on `has-tooltip` class name for Vue components
```javascript ```javascript
// bad // bad
<span <span
class="has-tooltip" class="has-tooltip"
title="Some tooltip text"> title="Some tooltip text">
Text Text
</span> </span>
// good // good
<span <span
v-tooltip v-tooltip
title="Some tooltip text"> title="Some tooltip text">
Text Text
</span> </span>
``` ```
1. Tooltips: When using a tooltip, include the tooltip directive, `./app/assets/javascripts/vue_shared/directives/tooltip.js` 1. Tooltips: When using a tooltip, include the tooltip directive, `./app/assets/javascripts/vue_shared/directives/tooltip.js`
...@@ -684,13 +684,13 @@ Useful links: ...@@ -684,13 +684,13 @@ Useful links:
1. Don't change `data-original-title`. 1. Don't change `data-original-title`.
```javascript ```javascript
// bad // bad
<span data-original-title="tooltip text">Foo</span> <span data-original-title="tooltip text">Foo</span>
// good // good
<span title="tooltip text">Foo</span> <span title="tooltip text">Foo</span>
$('span').tooltip('_fixTitle'); $('span').tooltip('_fixTitle');
``` ```
### The Javascript/Vue Accord ### The Javascript/Vue Accord
......
...@@ -313,7 +313,7 @@ export default { ...@@ -313,7 +313,7 @@ export default {
1. Do not call a mutation directly. Always use an action to commit a mutation. Doing so will keep consistency throughout the application. From Vuex docs: 1. Do not call a mutation directly. Always use an action to commit a mutation. Doing so will keep consistency throughout the application. From Vuex docs:
> why don't we just call store.commit('action') directly? Well, remember that mutations must be synchronous? Actions aren't. We can perform asynchronous operations inside an action. > Why don't we just call store.commit('action') directly? Well, remember that mutations must be synchronous? Actions aren't. We can perform asynchronous operations inside an action.
```javascript ```javascript
// component.vue // component.vue
......
...@@ -9,8 +9,8 @@ when making _backend_ changes that might involve multiple features or [component ...@@ -9,8 +9,8 @@ when making _backend_ changes that might involve multiple features or [component
## Uploads ## Uploads
GitLab supports uploads to [object storage]. That means every feature and GitLab supports uploads to [object storage]. That means every feature and
change that affects uploads should also be tested against [object storage], change that affects uploads should also be tested against [object storage],
which is _not_ enabled by default in [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit). which is _not_ enabled by default in [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit).
When working on a related feature, make sure to enable and test it When working on a related feature, make sure to enable and test it
......
# Dirty Submit # Dirty Submit
> [Introduced][ce-21115] in GitLab 11.3. > [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21115) in GitLab 11.3.
> [dirty_submit][dirty-submit]
## Summary ## Summary
...@@ -9,6 +8,9 @@ Prevent submitting forms with no changes. ...@@ -9,6 +8,9 @@ Prevent submitting forms with no changes.
Currently handles `input`, `textarea` and `select` elements. Currently handles `input`, `textarea` and `select` elements.
Also, see [the code](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/javascripts/dirty_submit/)
within the GitLab project.
## Usage ## Usage
```js ```js
...@@ -18,6 +20,3 @@ new DirtySubmitForm(document.querySelector('form')); ...@@ -18,6 +20,3 @@ new DirtySubmitForm(document.querySelector('form'));
// or // or
new DirtySubmitForm(document.querySelectorAll('form')); new DirtySubmitForm(document.querySelectorAll('form'));
``` ```
[ce-21115]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21115
[dirty-submit]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/javascripts/dirty_submit/
\ No newline at end of file
...@@ -192,4 +192,4 @@ rules only if you are invoking/instantiating existing code modules. ...@@ -192,4 +192,4 @@ rules only if you are invoking/instantiating existing code modules.
- [class-method-use-this](http://eslint.org/docs/rules/class-methods-use-this) - [class-method-use-this](http://eslint.org/docs/rules/class-methods-use-this)
> Note: Disable these rules on a per line basis. This makes it easier to refactor > Note: Disable these rules on a per line basis. This makes it easier to refactor
in the future. E.g. use `eslint-disable-next-line` or `eslint-disable-line`. > in the future. E.g. use `eslint-disable-next-line` or `eslint-disable-line`.
...@@ -24,7 +24,8 @@ Having said all of the above, we recommend staying away from shell scripts ...@@ -24,7 +24,8 @@ Having said all of the above, we recommend staying away from shell scripts
as much as possible. A language like Ruby or Python (if required for as much as possible. A language like Ruby or Python (if required for
consistency with codebases that we leverage) is almost always a better choice. consistency with codebases that we leverage) is almost always a better choice.
The high-level interpreted languages have more readable syntax, offer much more The high-level interpreted languages have more readable syntax, offer much more
mature capabilities for unit-testing, linting, and error reporting. mature capabilities for unit-testing, linting, and error reporting.
Use shell scripts only if there's a strong restriction on project's Use shell scripts only if there's a strong restriction on project's
dependencies size or any other requirements that are more important dependencies size or any other requirements that are more important
in a particular case. in a particular case.
...@@ -48,12 +49,12 @@ that is: ...@@ -48,12 +49,12 @@ that is:
This section describes the tools that should be made a mandatory part of This section describes the tools that should be made a mandatory part of
a project's CI pipeline if it contains shell scripts. These tools a project's CI pipeline if it contains shell scripts. These tools
automate shell code formatting, checking for errors or vulnerabilities, etc. automate shell code formatting, checking for errors or vulnerabilities, etc.
### Linting ### Linting
We're using the [ShellCheck](https://www.shellcheck.net/) utility in its default configuration to lint our We're using the [ShellCheck](https://www.shellcheck.net/) utility in its default configuration to lint our
shell scripts. shell scripts.
All projects with shell scripts should use this GitLab CI/CD job: All projects with shell scripts should use this GitLab CI/CD job:
...@@ -98,7 +99,7 @@ NOTE: **Note:** ...@@ -98,7 +99,7 @@ NOTE: **Note:**
This is a work in progress. This is a work in progress.
It is an [ongoing effort](https://gitlab.com/gitlab-org/gitlab-ce/issues/64016) to evaluate different tools for the It is an [ongoing effort](https://gitlab.com/gitlab-org/gitlab-ce/issues/64016) to evaluate different tools for the
automated testing of shell scripts (like [BATS](https://github.com/sstephenson/bats)). automated testing of shell scripts (like [BATS](https://github.com/sstephenson/bats)).
## Code Review ## Code Review
......
...@@ -255,8 +255,8 @@ that a machine will hit the "too many mount points" problem in the future. ...@@ -255,8 +255,8 @@ that a machine will hit the "too many mount points" problem in the future.
thousands of unused Docker images.** thousands of unused Docker images.**
> We have to start somewhere and improve later. Also, we're using the > We have to start somewhere and improve later. Also, we're using the
CNG-mirror project to store these Docker images so that we can just wipe out > CNG-mirror project to store these Docker images so that we can just wipe out
the registry at some point, and use a new fresh, empty one. > the registry at some point, and use a new fresh, empty one.
**How do we secure this from abuse? Apps are open to the world so we need to **How do we secure this from abuse? Apps are open to the world so we need to
find a way to limit it to only us.** find a way to limit it to only us.**
......
...@@ -46,8 +46,7 @@ In `config/gitlab.yml`: ...@@ -46,8 +46,7 @@ In `config/gitlab.yml`:
## Storing LFS objects in remote object storage ## Storing LFS objects in remote object storage
> [Introduced][ee-2760] in [GitLab Premium][eep] 10.0. Brought to GitLab Core > [Introduced][ee-2760] in [GitLab Premium][eep] 10.0. Brought to GitLab Core in 10.7.
in 10.7.
It is possible to store LFS objects in remote object storage which allows you It is possible to store LFS objects in remote object storage which allows you
to offload local hard disk R/W operations, and free up disk space significantly. to offload local hard disk R/W operations, and free up disk space significantly.
...@@ -91,7 +90,7 @@ Here is a configuration example with S3. ...@@ -91,7 +90,7 @@ Here is a configuration example with S3.
| `aws_access_key_id` | AWS credentials, or compatible | `ABC123DEF456` | | `aws_access_key_id` | AWS credentials, or compatible | `ABC123DEF456` |
| `aws_secret_access_key` | AWS credentials, or compatible | `ABC123DEF456ABC123DEF456ABC123DEF456` | | `aws_secret_access_key` | AWS credentials, or compatible | `ABC123DEF456ABC123DEF456ABC123DEF456` |
| `aws_signature_version` | AWS signature version to use. 2 or 4 are valid options. Digital Ocean Spaces and other providers may need 2. | 4 | | `aws_signature_version` | AWS signature version to use. 2 or 4 are valid options. Digital Ocean Spaces and other providers may need 2. | 4 |
| `enable_signature_v4_streaming` | Set to true to enable HTTP chunked transfers with AWS v4 signatures (https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html). Oracle Cloud S3 needs this to be false | true | `enable_signature_v4_streaming` | Set to true to enable HTTP chunked transfers with [AWS v4 signatures](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html). Oracle Cloud S3 needs this to be false | true |
| `region` | AWS region | us-east-1 | | `region` | AWS region | us-east-1 |
| `host` | S3 compatible host for when not using AWS, e.g. `localhost` or `storage.example.com` | s3.amazonaws.com | | `host` | S3 compatible host for when not using AWS, e.g. `localhost` or `storage.example.com` | s3.amazonaws.com |
| `endpoint` | Can be used when configuring an S3 compatible service such as [Minio](https://www.minio.io), by entering a URL such as `http://127.0.0.1:9000` | (optional) | | `endpoint` | Can be used when configuring an S3 compatible service such as [Minio](https://www.minio.io), by entering a URL such as `http://127.0.0.1:9000` | (optional) |
...@@ -107,7 +106,9 @@ Here is a configuration example with GCS. ...@@ -107,7 +106,9 @@ Here is a configuration example with GCS.
| `google_client_email` | The email address of the service account | `foo@gcp-project-12345.iam.gserviceaccount.com` | | `google_client_email` | The email address of the service account | `foo@gcp-project-12345.iam.gserviceaccount.com` |
| `google_json_key_location` | The json key path | `/path/to/gcp-project-12345-abcde.json` | | `google_json_key_location` | The json key path | `/path/to/gcp-project-12345-abcde.json` |
_NOTE: The service account must have permission to access the bucket. [See more](https://cloud.google.com/storage/docs/authentication)_ NOTE: **Note:**
The service account must have permission to access the bucket.
[See more](https://cloud.google.com/storage/docs/authentication)
Here is a configuration example with Rackspace Cloud Files. Here is a configuration example with Rackspace Cloud Files.
...@@ -119,7 +120,13 @@ Here is a configuration example with Rackspace Cloud Files. ...@@ -119,7 +120,13 @@ Here is a configuration example with Rackspace Cloud Files.
| `rackspace_region` | The Rackspace storage region to use, a three letter code from the [list of service access endpoints](https://developer.rackspace.com/docs/cloud-files/v1/general-api-info/service-access/) | `iad` | | `rackspace_region` | The Rackspace storage region to use, a three letter code from the [list of service access endpoints](https://developer.rackspace.com/docs/cloud-files/v1/general-api-info/service-access/) | `iad` |
| `rackspace_temp_url_key` | The private key you have set in the Rackspace API for temporary URLs. Read more [here](https://developer.rackspace.com/docs/cloud-files/v1/use-cases/public-access-to-your-cloud-files-account/#tempurl) | `ABC123DEF456ABC123DEF456ABC123DE` | | `rackspace_temp_url_key` | The private key you have set in the Rackspace API for temporary URLs. Read more [here](https://developer.rackspace.com/docs/cloud-files/v1/use-cases/public-access-to-your-cloud-files-account/#tempurl) | `ABC123DEF456ABC123DEF456ABC123DE` |
_NOTES: Regardless of whether the container has public access enabled or disabled, Fog will use the TempURL method to grant access to LFS objects. If you see errors in logs referencing instantiating storage with a temp-url-key, ensure that you have set they key properly on the Rackspace API and in gitlab.rb. You can verify the value of the key Rackspace has set by sending a GET request with token header to the service access endpoint URL and comparing the output of the returned headers._ NOTE: **Note:**
Regardless of whether the container has public access enabled or disabled, Fog will
use the TempURL method to grant access to LFS objects. If you see errors in logs referencing
instantiating storage with a temp-url-key, ensure that you have set they key properly
on the Rackspace API and in gitlab.rb. You can verify the value of the key Rackspace
has set by sending a GET request with token header to the service access endpoint URL
and comparing the output of the returned headers.
### Manual uploading to an object storage ### Manual uploading to an object storage
...@@ -167,13 +174,13 @@ On Omnibus installations, the settings are prefixed by `lfs_object_store_`: ...@@ -167,13 +174,13 @@ On Omnibus installations, the settings are prefixed by `lfs_object_store_`:
1. Save the file and [reconfigure GitLab]s for the changes to take effect. 1. Save the file and [reconfigure GitLab]s for the changes to take effect.
1. Migrate any existing local LFS objects to the object storage: 1. Migrate any existing local LFS objects to the object storage:
```bash ```bash
gitlab-rake gitlab:lfs:migrate gitlab-rake gitlab:lfs:migrate
``` ```
This will migrate existing LFS objects to object storage. New LFS objects This will migrate existing LFS objects to object storage. New LFS objects
will be forwarded to object storage unless will be forwarded to object storage unless
`gitlab_rails['lfs_object_store_background_upload']` is set to false. `gitlab_rails['lfs_object_store_background_upload']` is set to false.
### S3 for installations from source ### S3 for installations from source
...@@ -203,13 +210,13 @@ For source installations the settings are nested under `lfs:` and then ...@@ -203,13 +210,13 @@ For source installations the settings are nested under `lfs:` and then
1. Save the file and [restart GitLab][] for the changes to take effect. 1. Save the file and [restart GitLab][] for the changes to take effect.
1. Migrate any existing local LFS objects to the object storage: 1. Migrate any existing local LFS objects to the object storage:
```bash ```bash
sudo -u git -H bundle exec rake gitlab:lfs:migrate RAILS_ENV=production sudo -u git -H bundle exec rake gitlab:lfs:migrate RAILS_ENV=production
``` ```
This will migrate existing LFS objects to object storage. New LFS objects This will migrate existing LFS objects to object storage. New LFS objects
will be forwarded to object storage unless `background_upload` is set to will be forwarded to object storage unless `background_upload` is set to
false. false.
## Storage statistics ## Storage statistics
......
...@@ -35,9 +35,10 @@ Documentation for GitLab instance administrators is under [LFS administration do ...@@ -35,9 +35,10 @@ Documentation for GitLab instance administrators is under [LFS administration do
- Git LFS always assumes HTTPS so if you have GitLab server on HTTP you will have - Git LFS always assumes HTTPS so if you have GitLab server on HTTP you will have
to add the URL to Git config manually (see [troubleshooting](#troubleshooting)) to add the URL to Git config manually (see [troubleshooting](#troubleshooting))
>**Note**: With 8.12 GitLab added LFS support to SSH. The Git LFS communication NOTE: **Note:**
still goes over HTTP, but now the SSH client passes the correct credentials With 8.12 GitLab added LFS support to SSH. The Git LFS communication
to the Git LFS client, so no action is required by the user. still goes over HTTP, but now the SSH client passes the correct credentials
to the Git LFS client, so no action is required by the user.
## Using Git LFS ## Using Git LFS
...@@ -61,12 +62,13 @@ git commit -am "Added Debian iso" # commit the file meta data ...@@ -61,12 +62,13 @@ git commit -am "Added Debian iso" # commit the file meta data
git push origin master # sync the git repo and large file to the GitLab server git push origin master # sync the git repo and large file to the GitLab server
``` ```
> **Note**: Make sure that `.gitattributes` is tracked by git. Otherwise Git NOTE: **Note:**
> LFS will not be working properly for people cloning the project. **Make sure** that `.gitattributes` is tracked by Git. Otherwise Git
> LFS will not be working properly for people cloning the project.
> ```bash
> git add .gitattributes ```bash
> ``` git add .gitattributes
```
Cloning the repository works the same as before. Git automatically detects the Cloning the repository works the same as before. Git automatically detects the
LFS-tracked files and clones them via HTTP. If you performed the git clone LFS-tracked files and clones them via HTTP. If you performed the git clone
...@@ -216,9 +218,10 @@ git config --add lfs.url "http://gitlab.example.com/group/project.git/info/lfs" ...@@ -216,9 +218,10 @@ git config --add lfs.url "http://gitlab.example.com/group/project.git/info/lfs"
### Credentials are always required when pushing an object ### Credentials are always required when pushing an object
>**Note**: With 8.12 GitLab added LFS support to SSH. The Git LFS communication NOTE: **Note:**
still goes over HTTP, but now the SSH client passes the correct credentials With 8.12 GitLab added LFS support to SSH. The Git LFS communication
to the Git LFS client, so no action is required by the user. still goes over HTTP, but now the SSH client passes the correct credentials
to the Git LFS client, so no action is required by the user.
Given that Git LFS uses HTTP Basic Authentication to authenticate the user pushing Given that Git LFS uses HTTP Basic Authentication to authenticate the user pushing
the LFS object on every push for every object, user HTTPS credentials are required. the LFS object on every push for every object, user HTTPS credentials are required.
......
...@@ -76,7 +76,7 @@ Here you'll find a guide on ...@@ -76,7 +76,7 @@ Here you'll find a guide on
Since Annex files are stored as objects with symlinks and cannot be directly Since Annex files are stored as objects with symlinks and cannot be directly
modified, we need to first remove those symlinks. modified, we need to first remove those symlinks.
>**Note:** NOTE: **Note:**
Make sure the you read about the [`direct` mode][annex-direct] as it contains Make sure the you read about the [`direct` mode][annex-direct] as it contains
useful information that may fit in your use case. Note that `annex direct` is useful information that may fit in your use case. Note that `annex direct` is
deprecated in Git Annex version 6, so you may need to upgrade your repository deprecated in Git Annex version 6, so you may need to upgrade your repository
......
...@@ -37,8 +37,7 @@ The following are some possible use cases for repository mirroring: ...@@ -37,8 +37,7 @@ The following are some possible use cases for repository mirroring:
## Pushing to a remote repository **(CORE)** ## Pushing to a remote repository **(CORE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/249) in GitLab Enterprise > [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/249) in GitLab Enterprise Edition 8.7. [Moved to GitLab Core](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18715) in 10.8.
> Edition 8.7. [Moved to GitLab Core](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18715) in 10.8.
For an existing project, you can set up push mirroring as follows: For an existing project, you can set up push mirroring as follows:
...@@ -67,8 +66,7 @@ section. ...@@ -67,8 +66,7 @@ section.
### Push only protected branches **(CORE)** ### Push only protected branches **(CORE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3350) in > [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3350) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3. [Moved to GitLab Core](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18715) in 10.8.
> [GitLab Starter](https://about.gitlab.com/pricing/) 10.3. [Moved to GitLab Core](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18715) in 10.8.
You can choose to only push your protected branches from GitLab to your remote repository. You can choose to only push your protected branches from GitLab to your remote repository.
...@@ -98,8 +96,7 @@ The repository will push soon. To force a push, click the appropriate button. ...@@ -98,8 +96,7 @@ The repository will push soon. To force a push, click the appropriate button.
## Pulling from a remote repository **(STARTER)** ## Pulling from a remote repository **(STARTER)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/51) in GitLab Enterprise Edition 8.2. > [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/51) in GitLab Enterprise Edition 8.2. [Added Git LFS support](https://gitlab.com/gitlab-org/gitlab-ee/issues/10871) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.11.
> [Added Git LFS support](https://gitlab.com/gitlab-org/gitlab-ee/issues/10871) in [GitLab Starter](https://about.gitlab.com/pricing/) 11.11.
NOTE: **Note:** This feature [is available for free](https://gitlab.com/gitlab-org/gitlab-ee/issues/10361) to NOTE: **Note:** This feature [is available for free](https://gitlab.com/gitlab-org/gitlab-ee/issues/10361) to
GitLab.com users until September 22nd, 2019. GitLab.com users until September 22nd, 2019.
...@@ -157,8 +154,7 @@ Repository mirrors are updated as Sidekiq becomes available to process them. If ...@@ -157,8 +154,7 @@ Repository mirrors are updated as Sidekiq becomes available to process them. If
### SSH authentication ### SSH authentication
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2551) for Pull mirroring in [GitLab Starter](https://about.gitlab.com/pricing/) 9.5. > [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2551) for Pull mirroring in [GitLab Starter](https://about.gitlab.com/pricing/) 9.5. [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22982) for Push mirroring in [GitLab Core](https://about.gitlab.com/pricing/) 11.6
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22982) for Push mirroring in [GitLab Core](https://about.gitlab.com/pricing/) 11.6
SSH authentication is mutual: SSH authentication is mutual:
...@@ -245,8 +241,7 @@ key to keep the mirror running. ...@@ -245,8 +241,7 @@ key to keep the mirror running.
### Overwrite diverged branches **(STARTER)** ### Overwrite diverged branches **(STARTER)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/4559) in > [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/4559) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6.
> [GitLab Starter](https://about.gitlab.com/pricing/) 10.6.
You can choose to always update your local branches with remote versions, even if they have You can choose to always update your local branches with remote versions, even if they have
diverged from the remote. diverged from the remote.
...@@ -258,8 +253,7 @@ To use this option, check the **Overwrite diverged branches** box when creating ...@@ -258,8 +253,7 @@ To use this option, check the **Overwrite diverged branches** box when creating
### Only mirror protected branches **(STARTER)** ### Only mirror protected branches **(STARTER)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3326) in > [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3326) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3.
> [GitLab Starter](https://about.gitlab.com/pricing/) 10.3.
You can choose to pull mirror only the protected branches from your remote repository to GitLab. You can choose to pull mirror only the protected branches from your remote repository to GitLab.
Non-protected branches are not mirrored and can diverge. Non-protected branches are not mirrored and can diverge.
...@@ -268,8 +262,7 @@ To use this option, check the **Only mirror protected branches** box when creati ...@@ -268,8 +262,7 @@ To use this option, check the **Only mirror protected branches** box when creati
### Hard failure **(STARTER)** ### Hard failure **(STARTER)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3117) in > [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3117) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.2.
> [GitLab Starter](https://about.gitlab.com/pricing/) 10.2.
Once the mirroring process is unsuccessfully retried 14 times in a row, it will get marked as hard Once the mirroring process is unsuccessfully retried 14 times in a row, it will get marked as hard
failed. This will become visible in either the: failed. This will become visible in either the:
...@@ -282,8 +275,7 @@ project mirroring again by [Forcing an update](#forcing-an-update-core). ...@@ -282,8 +275,7 @@ project mirroring again by [Forcing an update](#forcing-an-update-core).
### Trigger update using API **(STARTER)** ### Trigger update using API **(STARTER)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3453) in > [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3453) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3.
[GitLab Starter](https://about.gitlab.com/pricing/) 10.3.
Pull mirroring uses polling to detect new branches and commits added upstream, often minutes Pull mirroring uses polling to detect new branches and commits added upstream, often minutes
afterwards. If you notify GitLab by [API](../api/projects.md#start-the-pull-mirroring-process-for-a-project-starter), afterwards. If you notify GitLab by [API](../api/projects.md#start-the-pull-mirroring-process-for-a-project-starter),
...@@ -325,9 +317,10 @@ protected branches. ...@@ -325,9 +317,10 @@ protected branches.
### Preventing conflicts using a `pre-receive` hook ### Preventing conflicts using a `pre-receive` hook
> **Warning:** The solution proposed will negatively impact the performance of CAUTION: **Warning:**
> Git push operations because they will be proxied to the upstream Git The solution proposed will negatively impact the performance of
> repository. Git push operations because they will be proxied to the upstream Git
repository.
A server-side `pre-receive` hook can be used to prevent the race condition A server-side `pre-receive` hook can be used to prevent the race condition
described above by only accepting the push after first pushing the commit to described above by only accepting the push after first pushing the commit to
......
...@@ -35,8 +35,8 @@ A To Do displays on your To-Do List when: ...@@ -35,8 +35,8 @@ A To Do displays on your To-Do List when:
- You are `@mentioned` in a comment on a commit - You are `@mentioned` in a comment on a commit
- A job in the CI pipeline running for your merge request failed, but this - A job in the CI pipeline running for your merge request failed, but this
job is not allowed to fail job is not allowed to fail
- An open merge request becomes unmergeable due to conflict, and you are either: - An open merge request becomes unmergeable due to conflict, and you are either:
- The author - The author
- Have set it to automatically merge once the pipeline succeeds - Have set it to automatically merge once the pipeline succeeds
To-do triggers are not affected by [GitLab Notification Email settings](notifications.md). To-do triggers are not affected by [GitLab Notification Email settings](notifications.md).
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment