summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTING.md4
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--GITLAB_WORKHORSE_VERSION2
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock6
-rw-r--r--Gemfile.rails5.lock6
-rw-r--r--app/assets/javascripts/boards/components/modal/lists_dropdown.vue2
-rw-r--r--app/assets/javascripts/commons/gitlab_ui.js25
-rw-r--r--app/assets/javascripts/ide/components/ide.vue12
-rw-r--r--app/assets/javascripts/ide/components/ide_side_bar.vue2
-rw-r--r--app/assets/javascripts/ide/components/ide_tree_list.vue2
-rw-r--r--app/assets/javascripts/ide/components/panes/right.vue92
-rw-r--r--app/assets/javascripts/ide/index.js8
-rw-r--r--app/assets/javascripts/job.js4
-rw-r--r--app/assets/javascripts/jobs/components/empty_state.vue4
-rw-r--r--app/assets/javascripts/jobs/components/erased_block.vue49
-rw-r--r--app/assets/javascripts/jobs/components/job_log.vue4
-rw-r--r--app/assets/javascripts/jobs/components/job_log_controllers.vue76
-rw-r--r--app/assets/javascripts/jobs/components/stuck_block.vue6
-rw-r--r--app/assets/javascripts/jobs/job_details_bundle.js45
-rw-r--r--app/assets/javascripts/jobs/job_details_mediator.js65
-rw-r--r--app/assets/javascripts/jobs/services/job_service.js11
-rw-r--r--app/assets/javascripts/jobs/store/mutations.js3
-rw-r--r--app/assets/javascripts/jobs/stores/job_store.js11
-rw-r--r--app/assets/javascripts/lib/utils/logoutput_behaviours.js17
-rw-r--r--app/assets/javascripts/lib/utils/scroll_utils.js24
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue35
-rw-r--r--app/assets/javascripts/monitoring/components/graph.vue13
-rw-r--r--app/assets/javascripts/notes.js2
-rw-r--r--app/assets/javascripts/notes/components/diff_with_note.vue2
-rw-r--r--app/assets/javascripts/performance_bar/components/performance_bar_app.vue2
-rw-r--r--app/assets/javascripts/performance_bar/components/simple_metric.vue37
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue2
-rw-r--r--app/assets/stylesheets/framework/responsive_tables.scss2
-rw-r--r--app/assets/stylesheets/framework/typography.scss2
-rw-r--r--app/controllers/application_controller.rb7
-rw-r--r--app/controllers/dashboard_controller.rb2
-rw-r--r--app/models/clusters/applications/jupyter.rb5
-rw-r--r--app/serializers/build_details_entity.rb1
-rw-r--r--app/services/files/multi_service.rb2
-rw-r--r--app/services/quick_actions/interpret_service.rb3
-rw-r--r--app/views/import/gitlab_projects/new.html.haml2
-rw-r--r--app/views/layouts/nav/sidebar/_group.html.haml2
-rw-r--r--app/views/projects/_new_project_fields.html.haml2
-rw-r--r--app/views/shared/_event_filter.html.haml12
-rw-r--r--changelogs/unreleased/1801-allow-event_filter-to-be-set-in-the-url.yml5
-rw-r--r--changelogs/unreleased/43832-adds-chdmod-to-commits-actions-api.yml5
-rw-r--r--changelogs/unreleased/4907-improve-build-create-performance-for-license-management.yml5
-rw-r--r--changelogs/unreleased/50289-vendor-ci-yml-for-the-last-time.yml5
-rw-r--r--changelogs/unreleased/50904-update-scroll-utils.yml5
-rw-r--r--changelogs/unreleased/50904-use-vuex-store-job.yml5
-rw-r--r--changelogs/unreleased/51522-add-new-project-via-import-by-url-auto-populates-slug-but-not-project-name.yml5
-rw-r--r--changelogs/unreleased/51569-performance-bar.yml5
-rw-r--r--changelogs/unreleased/51925-expose-has_trace-in-job-api.yml5
-rw-r--r--changelogs/unreleased/feature-add-public-email-to-users-api.yml5
-rw-r--r--changelogs/unreleased/jivl-fix-monitoring-dashboard-resizing-navbar.yml5
-rw-r--r--changelogs/unreleased/more-table-widths.yml5
-rw-r--r--changelogs/unreleased/sh-guard-against-ldap-login-csrf-fail.yml5
-rw-r--r--changelogs/unreleased/toon-copy-meta-data-fix.yml5
-rw-r--r--changelogs/unreleased/winh-page-title-margin.yml5
-rw-r--r--config/initializers/warden.rb5
-rw-r--r--doc/administration/gitaly/index.md2
-rw-r--r--doc/administration/logs.md6
-rw-r--r--doc/administration/raketasks/maintenance.md6
-rw-r--r--doc/api/commits.md12
-rw-r--r--doc/api/deployments.md45
-rw-r--r--doc/api/jobs.md95
-rw-r--r--doc/api/keys.md8
-rw-r--r--doc/api/merge_requests.md5
-rw-r--r--doc/api/oauth2.md8
-rw-r--r--doc/api/runners.md1
-rw-r--r--doc/api/users.md4
-rw-r--r--doc/ci/docker/using_docker_build.md4
-rw-r--r--doc/ci/examples/test-scala-application.md2
-rw-r--r--doc/ci/yaml/README.md2
-rw-r--r--doc/development/contributing/community_roles.md12
-rw-r--r--doc/development/contributing/design.md53
-rw-r--r--doc/development/contributing/index.md39
-rw-r--r--doc/development/contributing/issue_workflow.md54
-rw-r--r--doc/development/contributing/merge_request_workflow.md17
-rw-r--r--doc/development/documentation/index.md107
-rw-r--r--doc/development/documentation/styleguide.md2
-rw-r--r--doc/development/gitaly.md2
-rw-r--r--doc/development/ux_guide/users.md4
-rw-r--r--doc/gitlab-basics/add-image.md2
-rw-r--r--doc/install/kubernetes/gitlab_chart.md2
-rw-r--r--doc/integration/github.md4
-rw-r--r--doc/raketasks/backup_restore.md3
-rw-r--r--doc/security/user_email_confirmation.md2
-rw-r--r--doc/university/README.md2
-rw-r--r--doc/user/gitlab_com/index.md2
-rw-r--r--doc/user/index.md2
-rw-r--r--doc/user/project/container_registry.md6
-rw-r--r--doc/user/project/integrations/webhooks.md2
-rw-r--r--lib/api/commits.rb21
-rw-r--r--lib/api/entities.rb2
-rw-r--r--lib/event_filter.rb86
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml18
-rw-r--r--lib/gitlab/ci/templates/Julia.gitlab-ci.yml54
-rw-r--r--lib/gitlab/ci/templates/Pages/Jigsaw.gitlab-ci.yml42
-rw-r--r--lib/gitlab/ci/templates/Swift.gitlab-ci.yml2
-rw-r--r--lib/gitlab/gitaly_client/operation_service.rb3
-rw-r--r--lib/tasks/gitlab/artifacts/migrate.rake2
-rw-r--r--locale/gitlab.pot3
-rw-r--r--package.json8
-rw-r--r--qa/qa/page/main/login.rb1
-rw-r--r--qa/qa/page/project/activity.rb2
-rw-r--r--spec/controllers/projects/jobs_controller_spec.rb16
-rw-r--r--spec/factories/events.rb2
-rw-r--r--spec/features/projects/activity/user_sees_activity_spec.rb12
-rw-r--r--spec/fixtures/api/schemas/job/job_details.json6
-rw-r--r--spec/javascripts/jobs/components/empty_state_spec.js2
-rw-r--r--spec/javascripts/jobs/components/erased_block_spec.js8
-rw-r--r--spec/javascripts/jobs/components/job_details_mediator_spec.js39
-rw-r--r--spec/javascripts/jobs/components/job_log_controllers_spec.js167
-rw-r--r--spec/javascripts/jobs/components/job_log_spec.js6
-rw-r--r--spec/javascripts/jobs/components/job_store_spec.js26
-rw-r--r--spec/javascripts/jobs/store/mutations_spec.js7
-rw-r--r--spec/javascripts/monitoring/dashboard_spec.js42
-rw-r--r--spec/javascripts/monitoring/graph_spec.js18
-rw-r--r--spec/lib/event_filter_spec.rb131
-rw-r--r--spec/models/clusters/applications/jupyter_spec.rb7
-rw-r--r--spec/models/event_collection_spec.rb2
-rw-r--r--spec/requests/api/commits_spec.rb80
-rw-r--r--spec/services/files/multi_service_spec.rb36
-rw-r--r--spec/services/quick_actions/interpret_service_spec.rb9
-rw-r--r--yarn.lock40
129 files changed, 1225 insertions, 895 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8596037afa3..81fc46c2b6f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -72,11 +72,13 @@ For a first-time step-by-step guide to the contribution process, please see
Looking for something to work on? Look for issues in the [Backlog (Accepting merge requests) milestone](#i-want-to-contribute).
-GitLab comes into two flavors, GitLab Community Edition (CE) our free and open
+GitLab comes in two flavors, GitLab Community Edition (CE) our free and open
source edition, and GitLab Enterprise Edition (EE) which is our commercial
edition. Throughout this guide you will see references to CE and EE for
abbreviation.
+To get an overview of GitLab community membership including those that would be reviewing or merging your contributions, please visit [the community roles page](doc/development/contributing/community_roles.md).
+
If you want to know how the GitLab [core team]
operates please see [the GitLab contributing process](PROCESS.md).
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 61825a7bf03..ee1e4d2aee5 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-0.121.0
+0.122.0
diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION
index dfda3e0b4f0..f3b5af39e43 100644
--- a/GITLAB_WORKHORSE_VERSION
+++ b/GITLAB_WORKHORSE_VERSION
@@ -1 +1 @@
-6.1.0
+6.1.1
diff --git a/Gemfile b/Gemfile
index 1b35e2110d5..35e83a530f0 100644
--- a/Gemfile
+++ b/Gemfile
@@ -89,7 +89,7 @@ gem 'gitlab-gollum-rugged_adapter', '~> 0.4.4', require: false
gem 'github-linguist', '~> 5.3.3', require: 'linguist'
# API
-gem 'grape', '~> 1.0'
+gem 'grape', '~> 1.1'
gem 'grape-entity', '~> 0.7.1'
gem 'rack-cors', '~> 1.0.0', require: 'rack/cors'
diff --git a/Gemfile.lock b/Gemfile.lock
index 4de78f3ec44..d8eaaac99b1 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -343,7 +343,7 @@ GEM
signet (~> 0.7)
gpgme (2.0.13)
mini_portile2 (~> 2.1)
- grape (1.0.3)
+ grape (1.1.0)
activesupport
builder
mustermann-grape (~> 1.0.0)
@@ -501,7 +501,7 @@ GEM
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
- mustermann (1.0.2)
+ mustermann (1.0.3)
mustermann-grape (1.0.0)
mustermann (~> 1.0.0)
mysql2 (0.4.10)
@@ -1043,7 +1043,7 @@ DEPENDENCIES
google-api-client (~> 0.23)
google-protobuf (= 3.5.1)
gpgme
- grape (~> 1.0)
+ grape (~> 1.1)
grape-entity (~> 0.7.1)
grape-path-helpers (~> 1.0)
grape_logging (~> 1.7)
diff --git a/Gemfile.rails5.lock b/Gemfile.rails5.lock
index 8f4e1550a52..ab35a4a399f 100644
--- a/Gemfile.rails5.lock
+++ b/Gemfile.rails5.lock
@@ -346,7 +346,7 @@ GEM
signet (~> 0.7)
gpgme (2.0.13)
mini_portile2 (~> 2.1)
- grape (1.0.3)
+ grape (1.1.0)
activesupport
builder
mustermann-grape (~> 1.0.0)
@@ -504,7 +504,7 @@ GEM
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
- mustermann (1.0.2)
+ mustermann (1.0.3)
mustermann-grape (1.0.0)
mustermann (~> 1.0.0)
mysql2 (0.4.10)
@@ -1052,7 +1052,7 @@ DEPENDENCIES
google-api-client (~> 0.23)
google-protobuf (= 3.5.1)
gpgme
- grape (~> 1.0)
+ grape (~> 1.1)
grape-entity (~> 0.7.1)
grape-path-helpers (~> 1.0)
grape_logging (~> 1.7)
diff --git a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue b/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
index 24f26169799..4f23e5db35c 100644
--- a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
+++ b/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
@@ -1,5 +1,5 @@
<script>
-import Link from '@gitlab-org/gitlab-ui/dist/components/base/link';
+import { Link } from '@gitlab-org/gitlab-ui';
import ModalStore from '../../stores/modal_store';
export default {
diff --git a/app/assets/javascripts/commons/gitlab_ui.js b/app/assets/javascripts/commons/gitlab_ui.js
index aed26adfa5c..1411f7ffd5e 100644
--- a/app/assets/javascripts/commons/gitlab_ui.js
+++ b/app/assets/javascripts/commons/gitlab_ui.js
@@ -1,16 +1,17 @@
import Vue from 'vue';
-import Pagination from '@gitlab-org/gitlab-ui/dist/components/base/pagination';
-import progressBar from '@gitlab-org/gitlab-ui/dist/components/base/progress_bar';
-import modal from '@gitlab-org/gitlab-ui/dist/components/base/modal';
-import loadingIcon from '@gitlab-org/gitlab-ui/dist/components/base/loading_icon';
-
-import dModal from '@gitlab-org/gitlab-ui/dist/directives/modal';
-import dTooltip from '@gitlab-org/gitlab-ui/dist/directives/tooltip';
+import {
+ Pagination,
+ ProgressBar,
+ Modal,
+ LoadingIcon,
+ ModalDirective,
+ TooltipDirective,
+} from '@gitlab-org/gitlab-ui';
Vue.component('gl-pagination', Pagination);
-Vue.component('gl-progress-bar', progressBar);
-Vue.component('gl-ui-modal', modal);
-Vue.component('gl-loading-icon', loadingIcon);
+Vue.component('gl-progress-bar', ProgressBar);
+Vue.component('gl-ui-modal', Modal);
+Vue.component('gl-loading-icon', LoadingIcon);
-Vue.directive('gl-modal', dModal);
-Vue.directive('gl-tooltip', dTooltip);
+Vue.directive('gl-modal', ModalDirective);
+Vue.directive('gl-tooltip', TooltipDirective);
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index a3add3b778f..ad6151e3bf6 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -1,4 +1,5 @@
<script>
+import Vue from 'vue';
import Mousetrap from 'mousetrap';
import { mapActions, mapState, mapGetters } from 'vuex';
import { __ } from '~/locale';
@@ -22,10 +23,16 @@ export default {
IdeStatusBar,
RepoEditor,
FindFile,
- RightPane,
ErrorMessage,
CommitEditorHeader,
},
+ props: {
+ rightPaneComponent: {
+ type: Vue.Component,
+ required: false,
+ default: () => RightPane,
+ },
+ },
computed: {
...mapState([
'openFiles',
@@ -143,7 +150,8 @@ export default {
</div>
</template>
</div>
- <right-pane
+ <component
+ :is="rightPaneComponent"
v-if="currentProjectId"
/>
</div>
diff --git a/app/assets/javascripts/ide/components/ide_side_bar.vue b/app/assets/javascripts/ide/components/ide_side_bar.vue
index 5620d6a6244..f99ff6d6da8 100644
--- a/app/assets/javascripts/ide/components/ide_side_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_side_bar.vue
@@ -1,6 +1,6 @@
<script>
import { mapState, mapGetters } from 'vuex';
-import SkeletonLoading from '@gitlab-org/gitlab-ui/dist/components/base/skeleton_loading';
+import { SkeletonLoading } from '@gitlab-org/gitlab-ui';
import IdeTree from './ide_tree.vue';
import ResizablePanel from './resizable_panel.vue';
import ActivityBar from './activity_bar.vue';
diff --git a/app/assets/javascripts/ide/components/ide_tree_list.vue b/app/assets/javascripts/ide/components/ide_tree_list.vue
index ff53314d275..cfe25084b42 100644
--- a/app/assets/javascripts/ide/components/ide_tree_list.vue
+++ b/app/assets/javascripts/ide/components/ide_tree_list.vue
@@ -1,7 +1,7 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import Icon from '~/vue_shared/components/icon.vue';
-import SkeletonLoading from '@gitlab-org/gitlab-ui/dist/components/base/skeleton_loading';
+import { SkeletonLoading } from '@gitlab-org/gitlab-ui';
import FileRow from '~/vue_shared/components/file_row.vue';
import NavDropdown from './nav_dropdown.vue';
import FileRowExtra from './file_row_extra.vue';
diff --git a/app/assets/javascripts/ide/components/panes/right.vue b/app/assets/javascripts/ide/components/panes/right.vue
index 79df225c432..75a9a9e9b8f 100644
--- a/app/assets/javascripts/ide/components/panes/right.vue
+++ b/app/assets/javascripts/ide/components/panes/right.vue
@@ -1,5 +1,6 @@
<script>
import { mapActions, mapState, mapGetters } from 'vuex';
+import { __ } from '~/locale';
import tooltip from '../../../vue_shared/directives/tooltip';
import Icon from '../../../vue_shared/components/icon.vue';
import { rightSidebarViews } from '../../constants';
@@ -21,6 +22,13 @@ export default {
MergeRequestInfo,
Clientside,
},
+ props: {
+ extensionTabs: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ },
computed: {
...mapState(['rightPane', 'currentMergeRequestId', 'clientsidePreviewEnabled']),
...mapGetters(['packageJson']),
@@ -33,6 +41,36 @@ export default {
showLivePreview() {
return this.packageJson && this.clientsidePreviewEnabled;
},
+ defaultTabs() {
+ return [
+ {
+ show: this.currentMergeRequestId,
+ title: __('Merge Request'),
+ isActive: this.rightPane === rightSidebarViews.mergeRequestInfo,
+ view: rightSidebarViews.mergeRequestInfo,
+ icon: 'text-description',
+ },
+ {
+ show: true,
+ title: __('Pipelines'),
+ isActive: this.pipelinesActive,
+ view: rightSidebarViews.pipelines,
+ icon: 'rocket',
+ },
+ {
+ show: this.showLivePreview,
+ title: __('Live preview'),
+ isActive: this.rightPane === rightSidebarViews.clientSidePreview,
+ view: rightSidebarViews.clientSidePreview,
+ icon: 'live-preview',
+ },
+ ];
+ },
+ tabs() {
+ return this.defaultTabs
+ .concat(this.extensionTabs)
+ .filter(tab => tab.show);
+ },
},
methods: {
...mapActions(['setRightPane']),
@@ -42,7 +80,6 @@ export default {
this.setRightPane(view);
},
},
- rightSidebarViews,
};
</script>
@@ -64,64 +101,25 @@ export default {
<nav class="ide-activity-bar">
<ul class="list-unstyled">
<li
- v-if="currentMergeRequestId"
+ v-for="tab of tabs"
+ :key="tab.title"
>
<button
v-tooltip
- :title="__('Merge Request')"
- :aria-label="__('Merge Request')"
- :class="{
- active: rightPane === $options.rightSidebarViews.mergeRequestInfo
- }"
- data-container="body"
- data-placement="left"
- class="ide-sidebar-link is-right"
- type="button"
- @click="clickTab($event, $options.rightSidebarViews.mergeRequestInfo)"
- >
- <icon
- :size="16"
- name="text-description"
- />
- </button>
- </li>
- <li>
- <button
- v-tooltip
- :title="__('Pipelines')"
- :aria-label="__('Pipelines')"
- :class="{
- active: pipelinesActive
- }"
- data-container="body"
- data-placement="left"
- class="ide-sidebar-link is-right"
- type="button"
- @click="clickTab($event, $options.rightSidebarViews.pipelines)"
- >
- <icon
- :size="16"
- name="rocket"
- />
- </button>
- </li>
- <li v-if="showLivePreview">
- <button
- v-tooltip
- :title="__('Live preview')"
- :aria-label="__('Live preview')"
+ :title="tab.title"
+ :aria-label="tab.title"
:class="{
- active: rightPane === $options.rightSidebarViews.clientSidePreview
+ active: tab.isActive
}"
data-container="body"
data-placement="left"
class="ide-sidebar-link is-right"
type="button"
- @click="clickTab($event, $options.rightSidebarViews.clientSidePreview)"
+ @click="clickTab($event, tab.view)"
>
<icon
:size="16"
- name="live-preview"
+ :name="tab.icon"
/>
</button>
</li>
diff --git a/app/assets/javascripts/ide/index.js b/app/assets/javascripts/ide/index.js
index c90f8694326..c0550116633 100644
--- a/app/assets/javascripts/ide/index.js
+++ b/app/assets/javascripts/ide/index.js
@@ -15,21 +15,21 @@ Vue.use(Translate);
* @param {Object} options - Extra options for the IDE (Used by EE).
* @param {(e:Element) => Object} options.extraInitialData -
* Function that returns extra properties to seed initial data.
+ * @param {Component} options.rootComponent -
+ * Component that overrides the root component.
*/
export function initIde(el, options = {}) {
if (!el) return null;
const {
extraInitialData = () => ({}),
+ rootComponent = ide,
} = options;
return new Vue({
el,
store,
router,
- components: {
- ide,
- },
created() {
this.setEmptyStateSvgs({
emptyStateSvgPath: el.dataset.emptyStateSvgPath,
@@ -51,7 +51,7 @@ export function initIde(el, options = {}) {
...mapActions(['setEmptyStateSvgs', 'setLinks', 'setInitialData']),
},
render(createElement) {
- return createElement('ide');
+ return createElement(rootComponent);
},
});
}
diff --git a/app/assets/javascripts/job.js b/app/assets/javascripts/job.js
index d4f2a3ef7d3..0e71e705c13 100644
--- a/app/assets/javascripts/job.js
+++ b/app/assets/javascripts/job.js
@@ -6,7 +6,7 @@ import { visitUrl } from './lib/utils/url_utility';
import bp from './breakpoints';
import { numberToHumanSize } from './lib/utils/number_utils';
import { setCiStatusFavicon } from './lib/utils/common_utils';
-import { isScrolledToBottom, scrollDown } from './lib/utils/scroll_utils';
+import { isScrolledToBottom, scrollDown, scrollUp } from './lib/utils/scroll_utils';
import LogOutputBehaviours from './lib/utils/logoutput_behaviours';
export default class Job extends LogOutputBehaviours {
@@ -80,7 +80,7 @@ export default class Job extends LogOutputBehaviours {
}
scrollToTop() {
- $(document).scrollTop(0);
+ scrollUp();
this.hasBeenScrolled = true;
this.toggleScroll();
}
diff --git a/app/assets/javascripts/jobs/components/empty_state.vue b/app/assets/javascripts/jobs/components/empty_state.vue
index 4faf08387fb..ff45a5b05f8 100644
--- a/app/assets/javascripts/jobs/components/empty_state.vue
+++ b/app/assets/javascripts/jobs/components/empty_state.vue
@@ -25,7 +25,7 @@
validator(value) {
return (
value === null ||
- (Object.prototype.hasOwnProperty.call(value, 'link') &&
+ (Object.prototype.hasOwnProperty.call(value, 'path') &&
Object.prototype.hasOwnProperty.call(value, 'method') &&
Object.prototype.hasOwnProperty.call(value, 'title'))
);
@@ -63,7 +63,7 @@
class="text-center"
>
<a
- :href="action.link"
+ :href="action.path"
:data-method="action.method"
class="js-job-empty-state-action btn btn-primary"
>
diff --git a/app/assets/javascripts/jobs/components/erased_block.vue b/app/assets/javascripts/jobs/components/erased_block.vue
index d688eebfa95..3d6d9ba4387 100644
--- a/app/assets/javascripts/jobs/components/erased_block.vue
+++ b/app/assets/javascripts/jobs/components/erased_block.vue
@@ -1,39 +1,36 @@
<script>
-import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+ import _ from 'underscore';
+ import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-export default {
- components: {
- TimeagoTooltip,
- },
- props: {
- erasedByUser: {
- type: Boolean,
- required: true,
+ export default {
+ components: {
+ TimeagoTooltip,
},
- username: {
- type: String,
- required: false,
- default: null,
+ props: {
+ user: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ erasedAt: {
+ type: String,
+ required: true,
+ },
},
- linkToUser: {
- type: String,
- required: false,
- default: null,
+ computed: {
+ isErasedByUser() {
+ return !_.isEmpty(this.user);
+ },
},
- erasedAt: {
- type: String,
- required: true,
- },
- },
-};
+ };
</script>
<template>
<div class="prepend-top-default js-build-erased">
<div class="erased alert alert-warning">
- <template v-if="erasedByUser">
+ <template v-if="isErasedByUser">
{{ s__("Job|Job has been erased by") }}
- <a :href="linkToUser">
- {{ username }}
+ <a :href="user.web_url">
+ {{ user.username }}
</a>
</template>
<template v-else>
diff --git a/app/assets/javascripts/jobs/components/job_log.vue b/app/assets/javascripts/jobs/components/job_log.vue
index 3c4749d996b..b12e963b60c 100644
--- a/app/assets/javascripts/jobs/components/job_log.vue
+++ b/app/assets/javascripts/jobs/components/job_log.vue
@@ -6,7 +6,7 @@
type: String,
required: true,
},
- isReceivingBuildTrace: {
+ isComplete: {
type: Boolean,
required: true,
},
@@ -22,7 +22,7 @@
</code>
<div
- v-if="isReceivingBuildTrace"
+ v-if="isComplete"
class="js-log-animation build-loader-animation"
>
<div class="dot"></div>
diff --git a/app/assets/javascripts/jobs/components/job_log_controllers.vue b/app/assets/javascripts/jobs/components/job_log_controllers.vue
index 2cbf0f85266..3e62ababea3 100644
--- a/app/assets/javascripts/jobs/components/job_log_controllers.vue
+++ b/app/assets/javascripts/jobs/components/job_log_controllers.vue
@@ -1,8 +1,9 @@
<script>
+ import { polyfillSticky } from '~/lib/utils/sticky';
import Icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import { numberToHumanSize } from '~/lib/utils/number_utils';
- import { s__, sprintf } from '~/locale';
+ import { sprintf } from '~/locale';
export default {
components: {
@@ -12,44 +13,48 @@
tooltip,
},
props: {
- canEraseJob: {
- type: Boolean,
- required: true,
+ erasePath: {
+ type: String,
+ required: false,
+ default: null,
},
size: {
type: Number,
required: true,
},
- rawTracePath: {
+ rawPath: {
type: String,
required: false,
default: null,
},
- canScrollToTop: {
+ isScrollTopDisabled: {
+ type: Boolean,
+ required: true,
+ },
+ isScrollBottomDisabled: {
+ type: Boolean,
+ required: true,
+ },
+ isScrollingDown: {
type: Boolean,
required: true,
},
- canScrollToBottom: {
+ isTraceSizeVisible: {
type: Boolean,
required: true,
},
},
computed: {
jobLogSize() {
- return sprintf('Showing last %{startSpanTag} %{size} %{endSpanTag} of log -', {
- startSpanTag: '<span class="s-truncated-info-size truncated-info-size">',
- endSpanTag: '</span>',
+ return sprintf('Showing last %{size} of log -', {
size: numberToHumanSize(this.size),
});
},
},
+ mounted() {
+ polyfillSticky(this.$el);
+ },
methods: {
- handleEraseJobClick() {
- // eslint-disable-next-line no-alert
- if (window.confirm(s__('Job|Are you sure you want to erase this job?'))) {
- this.$emit('eraseJob');
- }
- },
handleScrollToTop() {
this.$emit('scrollJobLogTop');
},
@@ -57,48 +62,52 @@
this.$emit('scrollJobLogBottom');
},
},
+
};
</script>
<template>
<div class="top-bar">
<!-- truncate information -->
<div class="js-truncated-info truncated-info d-none d-sm-block float-left">
- <p v-html="jobLogSize"></p>
+ <template v-if="isTraceSizeVisible">
+ {{ jobLogSize }}
- <a
- v-if="rawTracePath"
- :href="rawTracePath"
- class="js-raw-link raw-link"
- >
- {{ s__("Job|Complete Raw") }}
- </a>
+ <a
+ v-if="rawPath"
+ :href="rawPath"
+ class="js-raw-link raw-link"
+ >
+ {{ s__("Job|Complete Raw") }}
+ </a>
+ </template>
</div>
<!-- eo truncate information -->
<div class="controllers float-right">
<!-- links -->
<a
- v-if="rawTracePath"
+ v-if="rawPath"
v-tooltip
:title="s__('Job|Show complete raw')"
- :href="rawTracePath"
+ :href="rawPath"
class="js-raw-link-controller controllers-buttons"
data-container="body"
>
<icon name="doc-text" />
</a>
- <button
- v-if="canEraseJob"
+ <a
+ v-if="erasePath"
v-tooltip
:title="s__('Job|Erase job log')"
- type="button"
+ :href="erasePath"
+ data-confirm="__('Are you sure you want to erase this build?')"
class="js-erase-link controllers-buttons"
data-container="body"
- @click="handleEraseJobClick"
+ data-method="post"
>
<icon name="remove" />
- </button>
+ </a>
<!-- eo links -->
<!-- scroll buttons -->
@@ -109,7 +118,7 @@
data-container="body"
>
<button
- :disabled="!canScrollToTop"
+ :disabled="isScrollTopDisabled"
type="button"
class="js-scroll-top btn-scroll btn-transparent btn-blank"
@click="handleScrollToTop"
@@ -125,9 +134,10 @@
data-container="body"
>
<button
- :disabled="!canScrollToBottom"
+ :disabled="isScrollBottomDisabled"
type="button"
class="js-scroll-bottom btn-scroll btn-transparent btn-blank"
+ :class="{ animate: isScrollingDown }"
@click="handleScrollToBottom"
>
<icon name="scroll_down"/>
diff --git a/app/assets/javascripts/jobs/components/stuck_block.vue b/app/assets/javascripts/jobs/components/stuck_block.vue
index 18883fea950..a60643b2c65 100644
--- a/app/assets/javascripts/jobs/components/stuck_block.vue
+++ b/app/assets/javascripts/jobs/components/stuck_block.vue
@@ -24,14 +24,14 @@ export default {
<div class="bs-callout bs-callout-warning">
<p
v-if="hasNoRunnersForProject"
- class="js-stuck-no-runners"
+ class="js-stuck-no-runners append-bottom-0"
>
{{ s__(`Job|This job is stuck, because the project
doesn't have any runners online assigned to it.`) }}
</p>
<p
v-else-if="tags.length"
- class="js-stuck-with-tags"
+ class="js-stuck-with-tags append-bottom-0"
>
{{ s__(`This job is stuck, because you don't have
any active runners online with any of these tags assigned to them:`) }}
@@ -45,7 +45,7 @@ export default {
</p>
<p
v-else
- class="js-stuck-no-active-runner"
+ class="js-stuck-no-active-runner append-bottom-0"
>
{{ s__(`This job is stuck, because you don't
have any active runners that can run this job.`) }}
diff --git a/app/assets/javascripts/jobs/job_details_bundle.js b/app/assets/javascripts/jobs/job_details_bundle.js
index a84324f14b2..0136ec4d194 100644
--- a/app/assets/javascripts/jobs/job_details_bundle.js
+++ b/app/assets/javascripts/jobs/job_details_bundle.js
@@ -1,34 +1,36 @@
+import { mapState } from 'vuex';
import Vue from 'vue';
-import JobMediator from './job_details_mediator';
-import jobHeader from './components/header.vue';
-import detailsBlock from './components/sidebar_details_block.vue';
+import Job from '../job';
+import JobHeader from './components/header.vue';
+import DetailsBlock from './components/sidebar_details_block.vue';
+import createStore from './store';
export default () => {
const { dataset } = document.getElementById('js-job-details-vue');
- const mediator = new JobMediator({ endpoint: dataset.endpoint });
- mediator.fetchJob();
+ // eslint-disable-next-line no-new
+ new Job();
+
+ const store = createStore();
+ store.dispatch('setJobEndpoint', dataset.endpoint);
+ store.dispatch('fetchJob');
// Header
// eslint-disable-next-line no-new
new Vue({
el: '#js-build-header-vue',
components: {
- jobHeader,
- },
- data() {
- return {
- mediator,
- };
+ JobHeader,
},
- mounted() {
- this.mediator.initBuildClass();
+ store,
+ computed: {
+ ...mapState(['job', 'isLoading']),
},
render(createElement) {
return createElement('job-header', {
props: {
- isLoading: this.mediator.state.isLoading,
- job: this.mediator.store.state.job,
+ isLoading: this.isLoading,
+ job: this.job,
},
});
},
@@ -41,18 +43,17 @@ export default () => {
new Vue({
el: detailsBlockElement,
components: {
- detailsBlock,
+ DetailsBlock,
},
- data() {
- return {
- mediator,
- };
+ store,
+ computed: {
+ ...mapState(['job', 'isLoading']),
},
render(createElement) {
return createElement('details-block', {
props: {
- isLoading: this.mediator.state.isLoading,
- job: this.mediator.store.state.job,
+ isLoading: this.isLoading,
+ job: this.job,
runnerHelpUrl: dataset.runnerHelpUrl,
terminalPath: detailsBlockDataset.terminalPath,
},
diff --git a/app/assets/javascripts/jobs/job_details_mediator.js b/app/assets/javascripts/jobs/job_details_mediator.js
deleted file mode 100644
index 073e518baa0..00000000000
--- a/app/assets/javascripts/jobs/job_details_mediator.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import Visibility from 'visibilityjs';
-import Flash from '../flash';
-import Poll from '../lib/utils/poll';
-import JobStore from './stores/job_store';
-import JobService from './services/job_service';
-import Job from '../job';
-
-export default class JobMediator {
- constructor(options = {}) {
- this.options = options;
-
- this.store = new JobStore();
- this.service = new JobService(options.endpoint);
-
- this.state = {
- isLoading: false,
- };
- }
-
- initBuildClass() {
- this.build = new Job();
- }
-
- fetchJob() {
- this.poll = new Poll({
- resource: this.service,
- method: 'getJob',
- successCallback: response => this.successCallback(response),
- errorCallback: () => this.errorCallback(),
- });
-
- if (!Visibility.hidden()) {
- this.state.isLoading = true;
- this.poll.makeRequest();
- } else {
- this.getJob();
- }
-
- Visibility.change(() => {
- if (!Visibility.hidden()) {
- this.poll.restart();
- } else {
- this.poll.stop();
- }
- });
- }
-
- getJob() {
- return this.service
- .getJob()
- .then(response => this.successCallback(response))
- .catch(() => this.errorCallback());
- }
-
- successCallback(response) {
- this.state.isLoading = false;
- return this.store.storeJob(response.data);
- }
-
- errorCallback() {
- this.state.isLoading = false;
-
- return new Flash('An error occurred while fetching the job.');
- }
-}
diff --git a/app/assets/javascripts/jobs/services/job_service.js b/app/assets/javascripts/jobs/services/job_service.js
deleted file mode 100644
index b746489c45c..00000000000
--- a/app/assets/javascripts/jobs/services/job_service.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import axios from '../../lib/utils/axios_utils';
-
-export default class JobService {
- constructor(endpoint) {
- this.job = endpoint;
- }
-
- getJob() {
- return axios.get(this.job);
- }
-}
diff --git a/app/assets/javascripts/jobs/store/mutations.js b/app/assets/javascripts/jobs/store/mutations.js
index cd12ef87d40..c3f2359fa4d 100644
--- a/app/assets/javascripts/jobs/store/mutations.js
+++ b/app/assets/javascripts/jobs/store/mutations.js
@@ -1,6 +1,9 @@
import * as types from './mutation_types';
export default {
+ [types.SET_JOB_ENDPOINT](state, endpoint) {
+ state.jobEndpoint = endpoint;
+ },
[types.REQUEST_STATUS_FAVICON](state) {
state.fetchingStatusFavicon = true;
},
diff --git a/app/assets/javascripts/jobs/stores/job_store.js b/app/assets/javascripts/jobs/stores/job_store.js
deleted file mode 100644
index 766194b8387..00000000000
--- a/app/assets/javascripts/jobs/stores/job_store.js
+++ /dev/null
@@ -1,11 +0,0 @@
-export default class JobStore {
- constructor() {
- this.state = {
- job: {},
- };
- }
-
- storeJob(job = {}) {
- this.state.job = job;
- }
-}
diff --git a/app/assets/javascripts/lib/utils/logoutput_behaviours.js b/app/assets/javascripts/lib/utils/logoutput_behaviours.js
index 1bf99d935ef..41b57025cc9 100644
--- a/app/assets/javascripts/lib/utils/logoutput_behaviours.js
+++ b/app/assets/javascripts/lib/utils/logoutput_behaviours.js
@@ -1,5 +1,11 @@
import $ from 'jquery';
-import { canScroll, isScrolledToBottom, toggleDisableButton } from './scroll_utils';
+import {
+ canScroll,
+ isScrolledToBottom,
+ isScrolledToTop,
+ isScrolledToMiddle,
+ toggleDisableButton,
+} from './scroll_utils';
export default class LogOutputBehaviours {
constructor() {
@@ -12,18 +18,13 @@ export default class LogOutputBehaviours {
}
toggleScroll() {
- const $document = $(document);
- const currentPosition = $document.scrollTop();
- const scrollHeight = $document.height();
-
- const windowHeight = $(window).height();
if (canScroll()) {
- if (currentPosition > 0 && scrollHeight - currentPosition !== windowHeight) {
+ if (isScrolledToMiddle()) {
// User is in the middle of the log
toggleDisableButton(this.$scrollTopBtn, false);
toggleDisableButton(this.$scrollBottomBtn, false);
- } else if (currentPosition === 0) {
+ } else if (isScrolledToTop()) {
// User is at Top of Log
toggleDisableButton(this.$scrollTopBtn, true);
diff --git a/app/assets/javascripts/lib/utils/scroll_utils.js b/app/assets/javascripts/lib/utils/scroll_utils.js
index 9313b570863..b4da1e16f08 100644
--- a/app/assets/javascripts/lib/utils/scroll_utils.js
+++ b/app/assets/javascripts/lib/utils/scroll_utils.js
@@ -4,6 +4,7 @@ export const canScroll = () => $(document).height() > $(window).height();
/**
* Checks if the entire page is scrolled down all the way to the bottom
+ * @returns {Boolean}
*/
export const isScrolledToBottom = () => {
const $document = $(document);
@@ -16,11 +17,34 @@ export const isScrolledToBottom = () => {
return scrollHeight - currentPosition === windowHeight;
};
+/**
+ * Checks if page is scrolled to the top
+ * @returns {Boolean}
+ */
+export const isScrolledToTop = () => $(document).scrollTop() === 0;
+
export const scrollDown = () => {
const $document = $(document);
$document.scrollTop($document.height());
};
+export const scrollUp = () => {
+ $(document).scrollTop(0);
+};
+
+/**
+ * Checks if scroll position is in the middle of the page
+ * @returns {Boolean}
+ */
+export const isScrolledToMiddle = () => {
+ const $document = $(document);
+ const currentPosition = $document.scrollTop();
+ const scrollHeight = $document.height();
+ const windowHeight = $(window).height();
+
+ return currentPosition > 0 && scrollHeight - currentPosition !== windowHeight;
+};
+
export const toggleDisableButton = ($button, disable) => {
if (disable && $button.prop('disabled')) return;
$button.prop('disabled', disable);
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index a07a0ecfc76..67338aa96c3 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -97,33 +97,45 @@ export default {
store: new MonitoringStore(),
state: 'gettingStarted',
showEmptyState: true,
- updateAspectRatio: false,
- updatedAspectRatios: 0,
hoverData: {},
- resizeThrottled: {},
+ elWidth: 0,
};
},
+ computed: {
+ forceRedraw() {
+ return this.elWidth;
+ },
+ },
created() {
this.service = new MonitoringService({
metricsEndpoint: this.metricsEndpoint,
deploymentEndpoint: this.deploymentEndpoint,
environmentsEndpoint: this.environmentsEndpoint,
});
- eventHub.$on('toggleAspectRatio', this.toggleAspectRatio);
+ this.mutationObserverConfig = {
+ attributes: true,
+ childList: false,
+ subtree: false,
+ };
eventHub.$on('hoverChanged', this.hoverChanged);
},
beforeDestroy() {
- eventHub.$off('toggleAspectRatio', this.toggleAspectRatio);
eventHub.$off('hoverChanged', this.hoverChanged);
window.removeEventListener('resize', this.resizeThrottled, false);
+ this.sidebarMutationObserver.disconnect();
},
mounted() {
- this.resizeThrottled = _.throttle(this.resize, 600);
+ this.resizeThrottled = _.debounce(this.resize, 100);
if (!this.hasMetrics) {
this.state = 'gettingStarted';
} else {
this.getGraphsData();
window.addEventListener('resize', this.resizeThrottled, false);
+
+ const sidebarEl = document.querySelector('.nav-sidebar');
+ // The sidebar listener
+ this.sidebarMutationObserver = new MutationObserver(this.resizeThrottled);
+ this.sidebarMutationObserver.observe(sidebarEl, this.mutationObserverConfig);
}
},
methods: {
@@ -153,14 +165,7 @@ export default {
});
},
resize() {
- this.updateAspectRatio = true;
- },
- toggleAspectRatio() {
- this.updatedAspectRatios += 1;
- if (this.store.getMetricsCount() === this.updatedAspectRatios) {
- this.updateAspectRatio = !this.updateAspectRatio;
- this.updatedAspectRatios = 0;
- }
+ this.elWidth = this.$el.clientWidth;
},
hoverChanged(data) {
this.hoverData = data;
@@ -172,6 +177,7 @@ export default {
<template>
<div
v-if="!showEmptyState"
+ :key="forceRedraw"
class="prometheus-graphs prepend-top-default"
>
<div class="environments d-flex align-items-center">
@@ -218,7 +224,6 @@ export default {
:key="graphIndex"
:graph-data="graphData"
:hover-data="hoverData"
- :update-aspect-ratio="updateAspectRatio"
:deployment-data="store.deploymentData"
:project-path="projectPath"
:tags-path="tagsPath"
diff --git a/app/assets/javascripts/monitoring/components/graph.vue b/app/assets/javascripts/monitoring/components/graph.vue
index a13f30e6079..ff44f51b8f8 100644
--- a/app/assets/javascripts/monitoring/components/graph.vue
+++ b/app/assets/javascripts/monitoring/components/graph.vue
@@ -32,10 +32,6 @@ export default {
type: Object,
required: true,
},
- updateAspectRatio: {
- type: Boolean,
- required: true,
- },
deploymentData: {
type: Array,
required: true,
@@ -110,15 +106,6 @@ export default {
},
},
watch: {
- updateAspectRatio() {
- if (this.updateAspectRatio) {
- this.graphHeight = 450;
- this.graphWidth = 600;
- this.measurements = measurements.large;
- this.draw();
- eventHub.$emit('toggleAspectRatio');
- }
- },
hoverData() {
this.positionFlag();
},
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index e2f485e37eb..f301f093ef4 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -16,7 +16,7 @@ import 'vendor/jquery.atwho';
import AjaxCache from '~/lib/utils/ajax_cache';
import Vue from 'vue';
import syntaxHighlight from '~/syntax_highlight';
-import SkeletonLoading from '@gitlab-org/gitlab-ui/dist/components/base/skeleton_loading';
+import { SkeletonLoading } from '@gitlab-org/gitlab-ui';
import axios from './lib/utils/axios_utils';
import { getLocationHash } from './lib/utils/url_utility';
import Flash from './flash';
diff --git a/app/assets/javascripts/notes/components/diff_with_note.vue b/app/assets/javascripts/notes/components/diff_with_note.vue
index d9161210fe6..353aa790743 100644
--- a/app/assets/javascripts/notes/components/diff_with_note.vue
+++ b/app/assets/javascripts/notes/components/diff_with_note.vue
@@ -3,7 +3,7 @@ import { mapState, mapActions } from 'vuex';
import imageDiffHelper from '~/image_diff/helpers/index';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import DiffFileHeader from '~/diffs/components/diff_file_header.vue';
-import SkeletonLoading from '@gitlab-org/gitlab-ui/dist/components/base/skeleton_loading';
+import { SkeletonLoading } from '@gitlab-org/gitlab-ui';
import { trimFirstCharOfLineContent } from '~/diffs/store/utils';
export default {
diff --git a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
index 7836d4f3b09..1522e2227e4 100644
--- a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
+++ b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
@@ -42,7 +42,7 @@ export default {
keys: ['feature', 'request'],
},
],
- simpleMetrics: ['redis', 'sidekiq'],
+ simpleMetrics: ['redis'],
data() {
return { currentRequestId: '' };
},
diff --git a/app/assets/javascripts/performance_bar/components/simple_metric.vue b/app/assets/javascripts/performance_bar/components/simple_metric.vue
index b654bc66249..760ea8fe1e6 100644
--- a/app/assets/javascripts/performance_bar/components/simple_metric.vue
+++ b/app/assets/javascripts/performance_bar/components/simple_metric.vue
@@ -1,16 +1,29 @@
<script>
-export default {
- props: {
- currentRequest: {
- type: Object,
- required: true,
+ export default {
+ props: {
+ currentRequest: {
+ type: Object,
+ required: true,
+ },
+ metric: {
+ type: String,
+ required: true,
+ },
},
- metric: {
- type: String,
- required: true,
+ computed: {
+ duration() {
+ return (
+ this.currentRequest.details[this.metric] &&
+ this.currentRequest.details[this.metric].duration
+ );
+ },
+ calls() {
+ return (
+ this.currentRequest.details[this.metric] && this.currentRequest.details[this.metric].calls
+ );
+ },
},
- },
-};
+ };
</script>
<template>
<div
@@ -21,9 +34,9 @@ export default {
v-if="currentRequest.details"
class="bold"
>
- {{ currentRequest.details[metric].duration }}
+ {{ duration }}
/
- {{ currentRequest.details[metric].calls }}
+ {{ calls }}
</span>
{{ metric }}
</div>
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
index 27689a55b67..807e049caf6 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
@@ -2,7 +2,7 @@
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import $ from 'jquery';
-import SkeletonLoading from '@gitlab-org/gitlab-ui/dist/components/base/skeleton_loading';
+import { SkeletonLoading } from '@gitlab-org/gitlab-ui';
const { CancelToken } = axios;
let axiosSource;
diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
index 9d25003ccb7..c45dafa9807 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
@@ -1,5 +1,5 @@
<script>
- import Link from '@gitlab-org/gitlab-ui/dist/components/base/link';
+ import { Link } from '@gitlab-org/gitlab-ui';
export default {
components: {
diff --git a/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue b/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue
index f11a7699f27..1d9c9220469 100644
--- a/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue
@@ -1,5 +1,5 @@
<script>
-import SkeletonLoading from '@gitlab-org/gitlab-ui/dist/components/base/skeleton_loading';
+import { SkeletonLoading } from '@gitlab-org/gitlab-ui';
export default {
name: 'SkeletonNote',
diff --git a/app/assets/stylesheets/framework/responsive_tables.scss b/app/assets/stylesheets/framework/responsive_tables.scss
index fc185ccfaad..29a9c076cdf 100644
--- a/app/assets/stylesheets/framework/responsive_tables.scss
+++ b/app/assets/stylesheets/framework/responsive_tables.scss
@@ -39,7 +39,7 @@
.table-section {
white-space: nowrap;
- $section-widths: 5 10 15 20 25 30 40 50 100;
+ $section-widths: 5 10 15 20 25 30 40 50 60 100;
@each $width in $section-widths {
&.section-#{$width} {
flex: 0 0 #{$width + '%'};
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index 0c1b8b92de3..6d891e21556 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -286,7 +286,7 @@ body {
}
.page-title {
- margin-top: $gl-padding;
+ margin: #{2 * $grid-size} 0;
line-height: 1.3;
font-size: 1.25em;
font-weight: $gl-font-weight-bold;
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index fb2808edf47..b87034d10b6 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -273,9 +273,10 @@ class ApplicationController < ActionController::Base
end
def event_filter
- # Split using comma to maintain backward compatibility Ex/ "filter1,filter2"
- filters = cookies['event_filter'].split(',')[0] if cookies['event_filter'].present?
- @event_filter ||= EventFilter.new(filters)
+ @event_filter ||=
+ EventFilter.new(params[:event_filter].presence || cookies[:event_filter]).tap do |new_event_filter|
+ cookies[:event_filter] = new_event_filter.filter
+ end
end
# JSON for infinite scroll via Pager object
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 241753a505a..c032fb2efb5 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -40,7 +40,7 @@ class DashboardController < Dashboard::ApplicationController
end
@events = EventCollection
- .new(projects, offset: params[:offset].to_i, filter: @event_filter)
+ .new(projects, offset: params[:offset].to_i, filter: event_filter)
.to_a
Events::RenderService.new(current_user).execute(@events)
diff --git a/app/models/clusters/applications/jupyter.rb b/app/models/clusters/applications/jupyter.rb
index 3d84eeed5a8..7be6a14f585 100644
--- a/app/models/clusters/applications/jupyter.rb
+++ b/app/models/clusters/applications/jupyter.rb
@@ -73,6 +73,11 @@ module Clusters
"clientSecret" => oauth_application.secret,
"callbackUrl" => callback_url
}
+ },
+ "singleuser" => {
+ "extraEnv" => {
+ "GITLAB_CLUSTER_ID" => cluster.id
+ }
}
}
end
diff --git a/app/serializers/build_details_entity.rb b/app/serializers/build_details_entity.rb
index 00a441a9a1e..c85b1790e73 100644
--- a/app/serializers/build_details_entity.rb
+++ b/app/serializers/build_details_entity.rb
@@ -7,6 +7,7 @@ class BuildDetailsEntity < JobEntity
expose :coverage, :erased_at, :duration
expose :tag_list, as: :tags
+ expose :has_trace?, as: :has_trace
expose :user, using: UserEntity
expose :runner, using: RunnerEntity
expose :pipeline, using: PipelineEntity
diff --git a/app/services/files/multi_service.rb b/app/services/files/multi_service.rb
index 08088f8c592..c9d3ee31d82 100644
--- a/app/services/files/multi_service.rb
+++ b/app/services/files/multi_service.rb
@@ -2,7 +2,7 @@
module Files
class MultiService < Files::BaseService
- UPDATE_FILE_ACTIONS = %w(update move delete).freeze
+ UPDATE_FILE_ACTIONS = %w(update move delete chmod).freeze
def create_commit!
transformer = Lfs::FileTransformer.new(project, @branch_name)
diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb
index ceb01c8dc73..8933bef29ee 100644
--- a/app/services/quick_actions/interpret_service.rb
+++ b/app/services/quick_actions/interpret_service.rb
@@ -286,8 +286,7 @@ module QuickActions
end
params '#issue | !merge_request'
condition do
- issuable.persisted? &&
- current_user.can?(:"update_#{issuable.to_ability_name}", issuable)
+ current_user.can?(:"update_#{issuable.to_ability_name}", issuable)
end
parse_params do |issuable_param|
extract_references(issuable_param, :issue).first ||
diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml
index 877d945a09b..5e4595d930b 100644
--- a/app/views/import/gitlab_projects/new.html.haml
+++ b/app/views/import/gitlab_projects/new.html.haml
@@ -10,7 +10,7 @@
.row
.form-group.project-name.col-sm-12
= label_tag :name, _('Project name'), class: 'label-bold'
- = text_field_tag :name, @name, placeholder: "My awesome project", class: "js-project-name form-control input-lg", autofocus: true, required: true
+ = text_field_tag :name, @name, placeholder: "My awesome project", class: "js-project-name form-control input-lg", autofocus: true
.form-group.col-12.col-sm-6
= label_tag :namespace_id, _('Project URL'), class: 'label-bold'
.form-group
diff --git a/app/views/layouts/nav/sidebar/_group.html.haml b/app/views/layouts/nav/sidebar/_group.html.haml
index 4158bb69452..43170587797 100644
--- a/app/views/layouts/nav/sidebar/_group.html.haml
+++ b/app/views/layouts/nav/sidebar/_group.html.haml
@@ -109,7 +109,7 @@
= link_to edit_group_path(@group) do
.nav-icon-container
= sprite_icon('settings')
- %span.nav-item-name
+ %span.nav-item-name.qa-settings-item
= _('Settings')
%ul.sidebar-sub-level-items
= nav_link(path: %w[groups#projects groups#edit badges#index ci_cd#show], html_options: { class: "fly-out-top-item" } ) do
diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml
index db07c475866..cbf89fa8f02 100644
--- a/app/views/projects/_new_project_fields.html.haml
+++ b/app/views/projects/_new_project_fields.html.haml
@@ -7,7 +7,7 @@
.form-group.project-name.col-sm-12
= f.label :name, class: 'label-bold' do
%span= _("Project name")
- = f.text_field :name, placeholder: "My awesome project", class: "form-control input-lg", autofocus: true, required: true
+ = f.text_field :name, placeholder: "My awesome project", class: "form-control input-lg", autofocus: true
.form-group.project-path.col-sm-6
= f.label :namespace_id, class: 'label-bold' do
%span= s_("Project URL")
diff --git a/app/views/shared/_event_filter.html.haml b/app/views/shared/_event_filter.html.haml
index 7afb7b3a93b..6612497e7e2 100644
--- a/app/views/shared/_event_filter.html.haml
+++ b/app/views/shared/_event_filter.html.haml
@@ -2,13 +2,13 @@
.fade-left= icon('angle-left')
.fade-right= icon('angle-right')
%ul.nav-links.event-filter.scrolling-tabs.nav.nav-tabs
- = event_filter_link EventFilter.all, _('All'), s_('EventFilterBy|Filter by all')
+ = event_filter_link EventFilter::ALL, _('All'), s_('EventFilterBy|Filter by all')
- if event_filter_visible(:repository)
- = event_filter_link EventFilter.push, _('Push events'), s_('EventFilterBy|Filter by push events')
+ = event_filter_link EventFilter::PUSH, _('Push events'), s_('EventFilterBy|Filter by push events')
- if event_filter_visible(:merge_requests)
- = event_filter_link EventFilter.merged, _('Merge events'), s_('EventFilterBy|Filter by merge events')
+ = event_filter_link EventFilter::MERGED, _('Merge events'), s_('EventFilterBy|Filter by merge events')
- if event_filter_visible(:issues)
- = event_filter_link EventFilter.issue, _('Issue events'), s_('EventFilterBy|Filter by issue events')
+ = event_filter_link EventFilter::ISSUE, _('Issue events'), s_('EventFilterBy|Filter by issue events')
- if comments_visible?
- = event_filter_link EventFilter.comments, _('Comments'), s_('EventFilterBy|Filter by comments')
- = event_filter_link EventFilter.team, _('Team'), s_('EventFilterBy|Filter by team')
+ = event_filter_link EventFilter::COMMENTS, _('Comments'), s_('EventFilterBy|Filter by comments')
+ = event_filter_link EventFilter::TEAM, _('Team'), s_('EventFilterBy|Filter by team')
diff --git a/changelogs/unreleased/1801-allow-event_filter-to-be-set-in-the-url.yml b/changelogs/unreleased/1801-allow-event_filter-to-be-set-in-the-url.yml
new file mode 100644
index 00000000000..4ceaa7e3139
--- /dev/null
+++ b/changelogs/unreleased/1801-allow-event_filter-to-be-set-in-the-url.yml
@@ -0,0 +1,5 @@
+---
+title: "Allow events filter to be set in the URL in addition to cookie"
+merge_request: 21557
+author: Igor @igas
+type: added
diff --git a/changelogs/unreleased/43832-adds-chdmod-to-commits-actions-api.yml b/changelogs/unreleased/43832-adds-chdmod-to-commits-actions-api.yml
new file mode 100644
index 00000000000..cea1436ae8b
--- /dev/null
+++ b/changelogs/unreleased/43832-adds-chdmod-to-commits-actions-api.yml
@@ -0,0 +1,5 @@
+---
+title: Allows to chmod file with commits API
+merge_request: 21866
+author: Jacopo Beschi @jacopo-beschi
+type: added
diff --git a/changelogs/unreleased/4907-improve-build-create-performance-for-license-management.yml b/changelogs/unreleased/4907-improve-build-create-performance-for-license-management.yml
new file mode 100644
index 00000000000..e82bda6819f
--- /dev/null
+++ b/changelogs/unreleased/4907-improve-build-create-performance-for-license-management.yml
@@ -0,0 +1,5 @@
+---
+title: Dont create license_management build when not included in license
+merge_request: 21958
+author:
+type: performance
diff --git a/changelogs/unreleased/50289-vendor-ci-yml-for-the-last-time.yml b/changelogs/unreleased/50289-vendor-ci-yml-for-the-last-time.yml
new file mode 100644
index 00000000000..7aee8720888
--- /dev/null
+++ b/changelogs/unreleased/50289-vendor-ci-yml-for-the-last-time.yml
@@ -0,0 +1,5 @@
+---
+title: Update all gitlab CI templates from gitlab-org/gitlab-ci-yml
+merge_request: 21929
+author:
+type: added
diff --git a/changelogs/unreleased/50904-update-scroll-utils.yml b/changelogs/unreleased/50904-update-scroll-utils.yml
new file mode 100644
index 00000000000..e301de1a40b
--- /dev/null
+++ b/changelogs/unreleased/50904-update-scroll-utils.yml
@@ -0,0 +1,5 @@
+---
+title: Extracts scroll position check into reusable functions
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/50904-use-vuex-store-job.yml b/changelogs/unreleased/50904-use-vuex-store-job.yml
new file mode 100644
index 00000000000..5b1112a4f5b
--- /dev/null
+++ b/changelogs/unreleased/50904-use-vuex-store-job.yml
@@ -0,0 +1,5 @@
+---
+title: Uses Vuex store in job details page and removes old mediator pattern
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/51522-add-new-project-via-import-by-url-auto-populates-slug-but-not-project-name.yml b/changelogs/unreleased/51522-add-new-project-via-import-by-url-auto-populates-slug-but-not-project-name.yml
new file mode 100644
index 00000000000..06b7c9c7b34
--- /dev/null
+++ b/changelogs/unreleased/51522-add-new-project-via-import-by-url-auto-populates-slug-but-not-project-name.yml
@@ -0,0 +1,5 @@
+---
+title: Removes the 'required' attribute from the 'project name' field
+merge_request: 21770
+author:
+type: other
diff --git a/changelogs/unreleased/51569-performance-bar.yml b/changelogs/unreleased/51569-performance-bar.yml
new file mode 100644
index 00000000000..ab62e7d3b3e
--- /dev/null
+++ b/changelogs/unreleased/51569-performance-bar.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes performance bar looking for a key in a undefined prop
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/51925-expose-has_trace-in-job-api.yml b/changelogs/unreleased/51925-expose-has_trace-in-job-api.yml
new file mode 100644
index 00000000000..eade86d97ac
--- /dev/null
+++ b/changelogs/unreleased/51925-expose-has_trace-in-job-api.yml
@@ -0,0 +1,5 @@
+---
+title: Expose has_trace in job API
+merge_request: 21950
+author:
+type: other
diff --git a/changelogs/unreleased/feature-add-public-email-to-users-api.yml b/changelogs/unreleased/feature-add-public-email-to-users-api.yml
new file mode 100644
index 00000000000..1f5d3fb113d
--- /dev/null
+++ b/changelogs/unreleased/feature-add-public-email-to-users-api.yml
@@ -0,0 +1,5 @@
+---
+title: Adds the user's public_email attribute to the API
+merge_request: 21909
+author: Alexis Reigel
+type: added
diff --git a/changelogs/unreleased/jivl-fix-monitoring-dashboard-resizing-navbar.yml b/changelogs/unreleased/jivl-fix-monitoring-dashboard-resizing-navbar.yml
new file mode 100644
index 00000000000..c21301bf6b3
--- /dev/null
+++ b/changelogs/unreleased/jivl-fix-monitoring-dashboard-resizing-navbar.yml
@@ -0,0 +1,5 @@
+---
+title: Fix resizing of monitoring dashboard
+merge_request: 21730
+author:
+type: fixed
diff --git a/changelogs/unreleased/more-table-widths.yml b/changelogs/unreleased/more-table-widths.yml
new file mode 100644
index 00000000000..61956e7068e
--- /dev/null
+++ b/changelogs/unreleased/more-table-widths.yml
@@ -0,0 +1,5 @@
+---
+title: Adds an extra width to the responsive tables
+merge_request: 21928
+author:
+type: other
diff --git a/changelogs/unreleased/sh-guard-against-ldap-login-csrf-fail.yml b/changelogs/unreleased/sh-guard-against-ldap-login-csrf-fail.yml
new file mode 100644
index 00000000000..7233f6f3d7b
--- /dev/null
+++ b/changelogs/unreleased/sh-guard-against-ldap-login-csrf-fail.yml
@@ -0,0 +1,5 @@
+---
+title: Guard against a login attempt with invalid CSRF token
+merge_request: 21934
+author:
+type: fixed
diff --git a/changelogs/unreleased/toon-copy-meta-data-fix.yml b/changelogs/unreleased/toon-copy-meta-data-fix.yml
new file mode 100644
index 00000000000..f2f8a1a82a4
--- /dev/null
+++ b/changelogs/unreleased/toon-copy-meta-data-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Allow /copy_metadata for new issues and MRs
+merge_request: 21953
+author:
+type: changed
diff --git a/changelogs/unreleased/winh-page-title-margin.yml b/changelogs/unreleased/winh-page-title-margin.yml
new file mode 100644
index 00000000000..f21f07d396b
--- /dev/null
+++ b/changelogs/unreleased/winh-page-title-margin.yml
@@ -0,0 +1,5 @@
+---
+title: Change vertical margin of page titles to 16px
+merge_request: 21888
+author:
+type: changed
diff --git a/config/initializers/warden.rb b/config/initializers/warden.rb
index 33f55069c3e..1d2bb2bce0a 100644
--- a/config/initializers/warden.rb
+++ b/config/initializers/warden.rb
@@ -31,6 +31,11 @@ Rails.application.configure do |config|
Warden::Manager.before_logout(scope: :user) do |user, auth, opts|
user ||= auth.user
+
+ # Rails CSRF protection may attempt to log out a user before that
+ # user even logs in
+ next unless user
+
activity = Gitlab::Auth::Activity.new(opts)
tracker = Gitlab::Auth::BlockedUserTracker.new(user, auth)
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index 49c6902bc42..b5e2b5448f7 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -219,7 +219,7 @@ repository from your GitLab server over HTTP.
If you are running Gitaly [as a remote
service](#running-gitaly-on-its-own-server) you may want to disable
-the local Gitaly service that runs on your Gitlab server by default.
+the local Gitaly service that runs on your GitLab server by default.
> 'Disabling Gitaly' only makes sense when you run GitLab in a custom
cluster configuration, where different services run on different
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index 98134075b94..a8cdd20581d 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -13,7 +13,7 @@ This guide talks about how to read and use these system log files.
This file lives in `/var/log/gitlab/gitlab-rails/production_json.log` for
Omnibus GitLab packages or in `/home/git/gitlab/log/production_json.log` for
-installations from source. (When Gitlab is running in an environment
+installations from source. (When GitLab is running in an environment
other than production, the corresponding logfile is shown here.)
It contains a structured log for Rails controller requests received from
@@ -42,7 +42,7 @@ In addition, the log contains the IP address from which the request originated
This file lives in `/var/log/gitlab/gitlab-rails/production.log` for
Omnibus GitLab packages or in `/home/git/gitlab/log/production.log` for
-installations from source. (When Gitlab is running in an environment
+installations from source. (When GitLab is running in an environment
other than production, the corresponding logfile is shown here.)
It contains information about all performed requests. You can see the
@@ -187,7 +187,7 @@ This file lives in `/var/log/gitlab/gitlab-shell/gitlab-shell.log` for
Omnibus GitLab packages or in `/home/git/gitlab-shell/gitlab-shell.log` for
installations from source.
-GitLab shell is used by Gitlab for executing Git commands and provide
+GitLab shell is used by GitLab for executing Git commands and provide
SSH access to Git repositories. For example:
```
diff --git a/doc/administration/raketasks/maintenance.md b/doc/administration/raketasks/maintenance.md
index d3ce7b6f2df..29af07d12dc 100644
--- a/doc/administration/raketasks/maintenance.md
+++ b/doc/administration/raketasks/maintenance.md
@@ -58,9 +58,9 @@ Runs the following rake tasks:
It will check that each component was set up according to the installation guide and suggest fixes for issues found.
-You may also have a look at our Trouble Shooting Guides:
-- [Trouble Shooting Guide (GitLab)](http://docs.gitlab.com/ee/README.html#troubleshooting)
-- [Trouble Shooting Guide (Omnibus Gitlab)](http://docs.gitlab.com/omnibus/README.html#troubleshooting)
+You may also have a look at our Troubleshooting Guides:
+- [Troubleshooting Guide (GitLab)](http://docs.gitlab.com/ee/README.html#troubleshooting)
+- [Troubleshooting Guide (Omnibus Gitlab)](http://docs.gitlab.com/omnibus/README.html#troubleshooting)
**Omnibus Installation**
diff --git a/doc/api/commits.md b/doc/api/commits.md
index 624ed529009..5ff1e1f60e0 100644
--- a/doc/api/commits.md
+++ b/doc/api/commits.md
@@ -83,12 +83,13 @@ POST /projects/:id/repository/commits
| `actions[]` Attribute | Type | Required | Description |
| --------------------- | ---- | -------- | ----------- |
-| `action` | string | yes | The action to perform, `create`, `delete`, `move`, `update` |
+| `action` | string | yes | The action to perform, `create`, `delete`, `move`, `update`, `chmod`|
| `file_path` | string | yes | Full path to the file. Ex. `lib/class.rb` |
-| `previous_path` | string | no | Original full path to the file being moved. Ex. `lib/class1.rb` |
-| `content` | string | no | File content, required for all except `delete`. Optional for `move` |
+| `previous_path` | string | no | Original full path to the file being moved. Ex. `lib/class1.rb`. Only considered for `move` action. |
+| `content` | string | no | File content, required for all except `delete` and `chmod`. Optional for `move` |
| `encoding` | string | no | `text` or `base64`. `text` is default. |
| `last_commit_id` | string | no | Last known file commit id. Will be only considered in update, move and delete actions. |
+| `execute_filemode` | boolean | no | When `true/false` enables/disables the execute flag on the file. Only considered for `chmod` action. |
```bash
PAYLOAD=$(cat << 'JSON'
@@ -115,6 +116,11 @@ PAYLOAD=$(cat << 'JSON'
"action": "update",
"file_path": "foo/bar5",
"content": "new content"
+ },
+ {
+ "action": "chmod",
+ "file_path": "foo/bar5",
+ "execute_filemode": true
}
]
}
diff --git a/doc/api/deployments.md b/doc/api/deployments.md
index fd11894ea8f..1963b0a21de 100644
--- a/doc/api/deployments.md
+++ b/doc/api/deployments.md
@@ -46,19 +46,21 @@ Example of response
"status": "success",
"tag": false,
"user": {
+ "id": 1,
+ "name": "Administrator",
+ "username": "root",
+ "state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "web_url": "http://gitlab.dev/root",
+ "created_at": "2015-12-21T13:14:24.077Z",
"bio": null,
- "created_at": "2016-08-11T07:09:20.351Z",
- "id": 1,
- "linkedin": "",
"location": null,
- "name": "Administrator",
+ "public_email": "",
"skype": "",
- "state": "active",
+ "linkedin": "",
"twitter": "",
- "username": "root",
- "web_url": "http://localhost:3000/root",
- "website_url": ""
+ "website_url": "",
+ "organization": ""
}
},
"environment": {
@@ -103,19 +105,21 @@ Example of response
"status": "success",
"tag": false,
"user": {
+ "id": 1,
+ "name": "Administrator",
+ "username": "root",
+ "state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "web_url": "http://gitlab.dev/root",
+ "created_at": "2015-12-21T13:14:24.077Z",
"bio": null,
- "created_at": "2016-08-11T07:09:20.351Z",
- "id": 1,
- "linkedin": "",
"location": null,
- "name": "Administrator",
+ "public_email": "",
"skype": "",
- "state": "active",
+ "linkedin": "",
"twitter": "",
- "username": "root",
- "web_url": "http://localhost:3000/root",
- "website_url": ""
+ "website_url": "",
+ "organization": ""
}
},
"environment": {
@@ -188,19 +192,20 @@ Example of response
"started_at": null,
"finished_at": "2016-08-11T11:32:35.145Z",
"user": {
+ "id": 1,
"name": "Administrator",
"username": "root",
- "id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "http://localhost:3000/root",
- "created_at": "2016-08-11T07:09:20.351Z",
+ "web_url": "http://gitlab.dev/root",
+ "created_at": "2015-12-21T13:14:24.077Z",
"bio": null,
"location": null,
"skype": "",
"linkedin": "",
"twitter": "",
- "website_url": ""
+ "website_url": "",
+ "organization": ""
},
"commit": {
"id": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
index cf292adf150..aa290ff4cf8 100644
--- a/doc/api/jobs.md
+++ b/doc/api/jobs.md
@@ -53,18 +53,21 @@ Example of response
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/6",
"user": {
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "bio": null,
- "created_at": "2015-12-21T13:14:24.077Z",
"id": 1,
- "linkedin": "",
"name": "Administrator",
- "skype": "",
- "state": "active",
- "twitter": "",
"username": "root",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"web_url": "http://gitlab.dev/root",
- "website_url": ""
+ "created_at": "2015-12-21T13:14:24.077Z",
+ "bio": null,
+ "location": null,
+ "public_email": "",
+ "skype": "",
+ "linkedin": "",
+ "twitter": "",
+ "website_url": "",
+ "organization": ""
}
},
{
@@ -109,18 +112,21 @@ Example of response
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/7",
"user": {
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "bio": null,
- "created_at": "2015-12-21T13:14:24.077Z",
"id": 1,
- "linkedin": "",
"name": "Administrator",
- "skype": "",
- "state": "active",
- "twitter": "",
"username": "root",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"web_url": "http://gitlab.dev/root",
- "website_url": ""
+ "created_at": "2015-12-21T13:14:24.077Z",
+ "bio": null,
+ "location": null,
+ "public_email": "",
+ "skype": "",
+ "linkedin": "",
+ "twitter": "",
+ "website_url": "",
+ "organization": ""
}
}
]
@@ -180,18 +186,21 @@ Example of response
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/6",
"user": {
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "bio": null,
- "created_at": "2015-12-21T13:14:24.077Z",
"id": 1,
- "linkedin": "",
"name": "Administrator",
- "skype": "",
- "state": "active",
- "twitter": "",
"username": "root",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"web_url": "http://gitlab.dev/root",
- "website_url": ""
+ "created_at": "2015-12-21T13:14:24.077Z",
+ "bio": null,
+ "location": null,
+ "public_email": "",
+ "skype": "",
+ "linkedin": "",
+ "twitter": "",
+ "website_url": "",
+ "organization": ""
}
},
{
@@ -236,18 +245,21 @@ Example of response
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/7",
"user": {
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "bio": null,
- "created_at": "2015-12-21T13:14:24.077Z",
"id": 1,
- "linkedin": "",
"name": "Administrator",
- "skype": "",
- "state": "active",
- "twitter": "",
"username": "root",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"web_url": "http://gitlab.dev/root",
- "website_url": ""
+ "created_at": "2015-12-21T13:14:24.077Z",
+ "bio": null,
+ "location": null,
+ "public_email": "",
+ "skype": "",
+ "linkedin": "",
+ "twitter": "",
+ "website_url": "",
+ "organization": ""
}
}
]
@@ -305,18 +317,21 @@ Example of response
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/8",
"user": {
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "bio": null,
- "created_at": "2015-12-21T13:14:24.077Z",
"id": 1,
- "linkedin": "",
"name": "Administrator",
- "skype": "",
- "state": "active",
- "twitter": "",
"username": "root",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"web_url": "http://gitlab.dev/root",
- "website_url": ""
+ "created_at": "2015-12-21T13:14:24.077Z",
+ "bio": null,
+ "location": null,
+ "public_email": "",
+ "skype": "",
+ "linkedin": "",
+ "twitter": "",
+ "website_url": "",
+ "organization": ""
}
}
```
diff --git a/doc/api/keys.md b/doc/api/keys.md
index ddcf7830621..06b31a67d6a 100644
--- a/doc/api/keys.md
+++ b/doc/api/keys.md
@@ -27,10 +27,16 @@ Parameters:
"web_url": "http://localhost:3000/john_smith",
"created_at": "2015-09-03T07:24:01.670Z",
"bio": null,
+ "location": null,
+ "public_email": "john@example.com",
"skype": "",
"linkedin": "",
"twitter": "",
"website_url": "",
+ "organization": null,
+ "last_sign_in_at": "2015-09-03T07:24:01.670Z",
+ "confirmed_at": "2015-09-03T07:24:01.670Z",
+ "last_activity_on": "2015-09-03",
"email": "john@example.com",
"theme_id": 2,
"color_scheme_id": 1,
@@ -40,6 +46,8 @@ Parameters:
"can_create_group": true,
"can_create_project": true,
"two_factor_enabled": false
+ "external": false,
+ "private_profile": null
}
}
```
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index 9e6676d62fe..4c099581f07 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -437,6 +437,11 @@ Parameters:
"id" : 1,
"name" : "Administrator"
},
+ "diff_refs": {
+ "base_sha": "1111111111111111111111111111111111111111",
+ "head_sha": "2222222222222222222222222222222222222222",
+ "start_sha": "3333333333333333333333333333333333333333"
+ },
"diverged_commits_count": 2
}
```
diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md
index 77bb7a55d8c..8a1e6b52092 100644
--- a/doc/api/oauth2.md
+++ b/doc/api/oauth2.md
@@ -1,6 +1,6 @@
# GitLab as an OAuth2 provider
-This document covers using the [OAuth2](https://oauth.net/2/) protocol to allow other services access Gitlab resources on user's behalf.
+This document covers using the [OAuth2](https://oauth.net/2/) protocol to allow other services access GitLab resources on user's behalf.
If you want GitLab to be an OAuth authentication service provider to sign into other services please see the [OAuth2 provider](../integration/oauth_provider.md)
documentation.
@@ -9,7 +9,7 @@ This functionality is based on [doorkeeper gem](https://github.com/doorkeeper-ge
## Supported OAuth2 Flows
-Gitlab currently supports following authorization flows:
+GitLab currently supports following authorization flows:
* *Web Application Flow* - Most secure and common type of flow, designed for the applications with secure server-side.
* *Implicit Flow* - This flow is designed for user-agent only apps (e.g. single page web application running on GitLab Pages).
@@ -76,7 +76,7 @@ Check [RFC spec](http://tools.ietf.org/html/rfc6749#section-4.2) for a detailed
Unlike the web flow, the client receives an `access token` immediately as a result of the authorization request. The flow does not use client secret
or authorization code because all of the application code and storage is easily accessible, therefore __secrets__ can leak easily.
->**Important:** Avoid using this flow for applications that store data outside of the Gitlab instance. If you do, make sure to verify `application id`
+>**Important:** Avoid using this flow for applications that store data outside of the GitLab instance. If you do, make sure to verify `application id`
associated with access token before granting access to the data
(see [/oauth/token/info](https://github.com/doorkeeper-gem/doorkeeper/wiki/API-endpoint-descriptions-and-examples#get----oauthtokeninfo)).
@@ -146,7 +146,7 @@ access_token = client.password.get_token('user@example.com', 'secret')
puts access_token.token
```
-## Access Gitlab API with `access token`
+## Access GitLab API with `access token`
The `access token` allows you to make requests to the API on a behalf of a user. You can pass the token either as GET parameter
```
diff --git a/doc/api/runners.md b/doc/api/runners.md
index 71ecb6606c1..0bcbd0aebf0 100644
--- a/doc/api/runners.md
+++ b/doc/api/runners.md
@@ -294,6 +294,7 @@ Example response:
"created_at": "2017-11-16T18:38:46.000Z",
"bio": null,
"location": null,
+ "public_email": "",
"skype": "",
"linkedin": "",
"twitter": "",
diff --git a/doc/api/users.md b/doc/api/users.md
index b0ae455a025..762ea53edee 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -199,6 +199,7 @@ Parameters:
"created_at": "2012-05-23T08:00:58Z",
"bio": null,
"location": null,
+ "public_email": "john@example.com",
"skype": "",
"linkedin": "",
"twitter": "",
@@ -230,6 +231,7 @@ Parameters:
"is_admin": false,
"bio": null,
"location": null,
+ "public_email": "john@example.com",
"skype": "",
"linkedin": "",
"twitter": "",
@@ -367,6 +369,7 @@ GET /user
"created_at": "2012-05-23T08:00:58Z",
"bio": null,
"location": null,
+ "public_email": "john@example.com",
"skype": "",
"linkedin": "",
"twitter": "",
@@ -415,6 +418,7 @@ GET /user
"is_admin": false,
"bio": null,
"location": null,
+ "public_email": "john@example.com",
"skype": "",
"linkedin": "",
"twitter": "",
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index aa997d15b64..0b64c8caba7 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -314,8 +314,8 @@ build:
stage: build
script:
- docker pull $CONTAINER_IMAGE:latest || true
- - docker build --cache-from $CONTAINER_IMAGE:latest --tag $CONTAINER_IMAGE:$CI_BUILD_REF --tag $CONTAINER_IMAGE:latest .
- - docker push $CONTAINER_IMAGE:$CI_BUILD_REF
+ - docker build --cache-from $CONTAINER_IMAGE:latest --tag $CONTAINER_IMAGE:$CI_COMMIT_SHA --tag $CONTAINER_IMAGE:latest .
+ - docker push $CONTAINER_IMAGE:$CI_COMMIT_SHA
- docker push $CONTAINER_IMAGE:latest
```
diff --git a/doc/ci/examples/test-scala-application.md b/doc/ci/examples/test-scala-application.md
index 09d83c33f95..b3961ec91f3 100644
--- a/doc/ci/examples/test-scala-application.md
+++ b/doc/ci/examples/test-scala-application.md
@@ -1,6 +1,6 @@
# Test and deploy to Heroku a Scala application
-This example demonstrates the integration of Gitlab CI with Scala
+This example demonstrates the integration of GitLab CI with Scala
applications using SBT. Checkout the example
[project](https://gitlab.com/gitlab-examples/scala-sbt) and
[build status](https://gitlab.com/gitlab-examples/scala-sbt/builds).
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 873a5c4301e..e38628b288b 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -188,7 +188,7 @@ used for time of the job. The configuration of this feature is covered in
## `before_script` and `after_script`
-> Introduced in GitLab 8.7 and requires Gitlab Runner v1.2
+> Introduced in GitLab 8.7 and requires GitLab Runner v1.2
`before_script` is used to define the command that should be run before all
jobs, including deploy jobs, but after the restoration of [artifacts](#artifacts).
diff --git a/doc/development/contributing/community_roles.md b/doc/development/contributing/community_roles.md
new file mode 100644
index 00000000000..c508969f7f4
--- /dev/null
+++ b/doc/development/contributing/community_roles.md
@@ -0,0 +1,12 @@
+### Community members & roles
+
+GitLab community members and their privileges/responsibilities.
+
+| Roles | Responsibilities | Requirements |
+|-------|------------------|--------------|
+| Maintainer | Accepts merge requests on several GitLab projects | Added to the [team page](https://about.gitlab.com/team/). An expert on code reviews and knows the product/code base |
+| Reviewer | Performs code reviews on MRs | Added to the [team page](https://about.gitlab.com/team/) |
+| Developer |Has access to GitLab internal infrastructure & issues (e.g. HR-related) | GitLab employee or a Core Team member (with an NDA) |
+| Contributor | Can make contributions to all GitLab public projects | Have a GitLab.com account |
+
+[List of current reviewers/maintainers](https://about.gitlab.com/handbook/engineering/projects/#gitlab-ce) \ No newline at end of file
diff --git a/doc/development/contributing/design.md b/doc/development/contributing/design.md
index 45fe8c26591..be7891061f9 100644
--- a/doc/development/contributing/design.md
+++ b/doc/development/contributing/design.md
@@ -1,13 +1,4 @@
-<!-- START doctoc generated TOC please keep comment here to allow auto update -->
-<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
-**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
-
-- [Implement design & UI elements](#implement-design--ui-elements)
-- [Style guides](#style-guides)
-
-<!-- END doctoc generated TOC please keep comment here to allow auto update -->
-
-## Implement design & UI elements
+# Implement design & UI elements
For guidance on UX implementation at GitLab, please refer to our [Design System](https://design.gitlab.com/).
@@ -34,27 +25,27 @@ In order to complete a product discovery issue in a release, you must complete t
## Style guides
-1. [Ruby](https://github.com/bbatsov/ruby-style-guide).
- Important sections include [Source Code Layout][rss-source] and
- [Naming][rss-naming]. Use:
- - multi-line method chaining style **Option A**: dot `.` on the second line
- - string literal quoting style **Option A**: single quoted by default
-1. [Rails](https://github.com/bbatsov/rails-style-guide)
-1. [Newlines styleguide][newlines-styleguide]
-1. [Testing][testing]
-1. [JavaScript styleguide][js-styleguide]
-1. [SCSS styleguide][scss-styleguide]
-1. [Shell commands](../shell_commands.md) created by GitLab
- contributors to enhance security
-1. [Database Migrations](../migration_style_guide.md)
-1. [Markdown](http://www.cirosantilli.com/markdown-styleguide)
-1. [Documentation styleguide](https://docs.gitlab.com/ee/development/documentation/styleguide.html)
-1. Interface text should be written subjectively instead of objectively. It
- should be the GitLab core team addressing a person. It should be written in
- present time and never use past tense (has been/was). For example instead
- of _prohibited this user from being saved due to the following errors:_ the
- text should be _sorry, we could not create your account because:_
-1. Code should be written in [US English][us-english]
+1. [Ruby](https://github.com/bbatsov/ruby-style-guide).
+ Important sections include [Source Code Layout][rss-source] and
+ [Naming][rss-naming]. Use:
+ - multi-line method chaining style **Option A**: dot `.` on the second line
+ - string literal quoting style **Option A**: single quoted by default
+1. [Rails](https://github.com/bbatsov/rails-style-guide)
+1. [Newlines styleguide][newlines-styleguide]
+1. [Testing][testing]
+1. [JavaScript styleguide][js-styleguide]
+1. [SCSS styleguide][scss-styleguide]
+1. [Shell commands](../shell_commands.md) created by GitLab
+ contributors to enhance security
+1. [Database Migrations](../migration_style_guide.md)
+1. [Markdown](http://www.cirosantilli.com/markdown-styleguide)
+1. [Documentation styleguide](https://docs.gitlab.com/ee/development/documentation/styleguide.html)
+1. Interface text should be written subjectively instead of objectively. It
+ should be the GitLab core team addressing a person. It should be written in
+ present time and never use past tense (has been/was). For example instead
+ of _prohibited this user from being saved due to the following errors:_ the
+ text should be _sorry, we could not create your account because:_
+1. Code should be written in [US English][us-english]
This is also the style used by linting tools such as
[RuboCop](https://github.com/bbatsov/rubocop),
diff --git a/doc/development/contributing/index.md b/doc/development/contributing/index.md
index eac7cb44c40..f4486ae3549 100644
--- a/doc/development/contributing/index.md
+++ b/doc/development/contributing/index.md
@@ -1,41 +1,4 @@
-<!-- START doctoc generated TOC please keep comment here to allow auto update -->
-<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
-**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
-
-- [Contribute to GitLab](#contribute-to-gitlab)
-- [Security vulnerability disclosure](#security-vulnerability-disclosure)
-- [Code of conduct](#code-of-conduct)
-- [Closing policy for issues and merge requests](#closing-policy-for-issues-and-merge-requests)
-- [Helping others](#helping-others)
-- [I want to contribute!](#i-want-to-contribute)
-- [Contribution Flow](#contribution-flow)
-- [Workflow labels](#workflow-labels)
- - [Type labels](#type-labels)
- - [Subject labels](#subject-labels)
- - [Team labels](#team-labels)
- - [Milestone labels](#milestone-labels)
- - [Bug Priority labels](#bug-priority-labels)
- - [Bug Severity labels](#bug-severity-labels)
- - [Severity impact guidance](#severity-impact-guidance)
- - [Label for community contributors](#label-for-community-contributors)
-- [Implement design & UI elements](#implement-design--ui-elements)
-- [Issue tracker](#issue-tracker)
- - [Issue triaging](#issue-triaging)
- - [Feature proposals](#feature-proposals)
- - [Issue tracker guidelines](#issue-tracker-guidelines)
- - [Issue weight](#issue-weight)
- - [Regression issues](#regression-issues)
- - [Technical and UX debt](#technical-and-ux-debt)
- - [Stewardship](#stewardship)
-- [Merge requests](#merge-requests)
- - [Merge request guidelines](#merge-request-guidelines)
- - [Contribution acceptance criteria](#contribution-acceptance-criteria)
-- [Definition of done](#definition-of-done)
-- [Style guides](#style-guides)
-
-<!-- END doctoc generated TOC please keep comment here to allow auto update -->
-
-## Contribute to GitLab
+# Contribute to GitLab
For a first-time step-by-step guide to the contribution process, see
["Contributing to GitLab"](https://about.gitlab.com/contributing/).
diff --git a/doc/development/contributing/issue_workflow.md b/doc/development/contributing/issue_workflow.md
index edd2d063458..7ba8e3dce95 100644
--- a/doc/development/contributing/issue_workflow.md
+++ b/doc/development/contributing/issue_workflow.md
@@ -1,27 +1,4 @@
-<!-- START doctoc generated TOC please keep comment here to allow auto update -->
-<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
-**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
-
-- [Workflow labels](#workflow-labels)
- - [Type labels](#type-labels)
- - [Subject labels](#subject-labels)
- - [Team labels](#team-labels)
- - [Release Scoping labels](#release-scoping-labels)
- - [Priority labels](#priority-labels)
- - [Severity labels](#severity-labels)
- - [Severity impact guidance](#severity-impact-guidance)
- - [Label for community contributors](#label-for-community-contributors)
- - [Issue triaging](#issue-triaging)
- - [Feature proposals](#feature-proposals)
- - [Issue tracker guidelines](#issue-tracker-guidelines)
- - [Issue weight](#issue-weight)
- - [Regression issues](#regression-issues)
- - [Technical and UX debt](#technical-and-ux-debt)
- - [Stewardship](#stewardship)
-
-<!-- END doctoc generated TOC please keep comment here to allow auto update -->
-
-## Workflow labels
+# Workflow labels
To allow for asynchronous issue handling, we use [milestones][milestones-page]
and [labels][labels-page]. Leads and product managers handle most of the
@@ -45,7 +22,7 @@ labels, you can _always_ add the team and type, and often also the subject.
[milestones-page]: https://gitlab.com/gitlab-org/gitlab-ce/milestones
[labels-page]: https://gitlab.com/gitlab-org/gitlab-ce/labels
-### Type labels
+## Type labels
Type labels are very important. They define what kind of issue this is. Every
issue should have one or more.
@@ -61,7 +38,7 @@ already reserved for subject labels).
The descriptions on the [labels page][labels-page] explain what falls under each type label.
-### Subject labels
+## Subject labels
Subject labels are labels that define what area or feature of GitLab this issue
hits. They are not always necessary, but very convenient.
@@ -75,7 +52,7 @@ issue is labeled with a subject label corresponding to your expertise.
Subject labels are always all-lowercase.
-### Team labels
+## Team labels
Team labels specify what team is responsible for this issue.
Assigning a team label makes sure issues get the attention of the appropriate
@@ -107,7 +84,7 @@ indicate if an issue needs backend work, frontend work, or both.
Team labels are always capitalized so that they show up as the first label for
any issue.
-### Release Scoping labels
+## Release Scoping labels
Release Scoping labels help us clearly communicate expectations of the work for the
release. There are three levels of Release Scoping labels:
@@ -138,7 +115,7 @@ This label documents the planned timeline & urgency which is used to measure aga
| ~P3 | Medium Priority | Within the next 3 releases (approx one quarter) |
| ~P4 | Low Priority | Anything outside the next 3 releases (approx beyond one quarter) |
-### Severity labels
+## Severity labels
Severity labels help us clearly communicate the impact of a ~bug on users.
@@ -149,7 +126,7 @@ Severity labels help us clearly communicate the impact of a ~bug on users.
| ~S3 | Major Severity | Broken Feature, workaround acceptable | Can create merge requests only from the Merge Requests page, not through the Issue. |
| ~S4 | Low Severity | Functionality inconvenience or cosmetic issue | Label colors are incorrect / not being displayed. |
-#### Severity impact guidance
+### Severity impact guidance
Severity levels can be applied further depending on the facet of the impact; e.g. Affected customers, GitLab.com availability, performance and etc. The below is a guideline.
@@ -160,7 +137,7 @@ Severity levels can be applied further depending on the facet of the impact; e.g
| ~S3 | A few users or a single paid customer affected | Limited impact on important portions of GitLab.com | Degradation is likely to occur in the near future |
| ~S4 | No paid users/customer affected, or expected to in the near future | Minor impact on on GitLab.com | Degradation _may_ occur but it's not likely |
-### Label for community contributors
+## Label for community contributors
Issues that are beneficial to our users, 'nice to haves', that we currently do
not have the capacity for or want to give the priority to, are labeled as
@@ -210,8 +187,7 @@ any potential community contributor to @-mention per above.
[up-for-grabs]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=Accepting+Merge+Requests&scope=all&sort=weight_asc&state=opened
[firt-timers]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name%5B%5D=Accepting+Merge+Requests&scope=all&sort=upvotes_desc&state=opened&weight=1
-
-### Issue triaging
+## Issue triaging
Our issue triage policies are [described in our handbook]. You are very welcome
to help the GitLab team triage issues. We also organize [issue bash events] once
@@ -233,7 +209,7 @@ project.
[scheduled pipeline]: https://gitlab.com/gitlab-org/quality/triage-ops/pipeline_schedules/10512/edit
[quality/triage-ops]: https://gitlab.com/gitlab-org/quality/triage-ops
-### Feature proposals
+## Feature proposals
To create a feature proposal for CE, open an issue on the
[issue tracker of CE][ce-tracker].
@@ -259,7 +235,7 @@ need to ask one of the [core team] members to add the label, if you do not have
If you want to create something yourself, consider opening an issue first to
discuss whether it is interesting to include this in GitLab.
-### Issue tracker guidelines
+## Issue tracker guidelines
**[Search the issue tracker][ce-tracker]** for similar entries before
submitting your own, there's a good chance somebody else had the same issue or
@@ -271,7 +247,7 @@ The text in the parenthesis is there to help you with what to include. Omit it
when submitting the actual issue. You can copy-paste it and then edit as you
see fit.
-### Issue weight
+## Issue weight
Issue weight allows us to get an idea of the amount of work required to solve
one or multiple issues. This makes it possible to schedule work more accurately.
@@ -293,7 +269,7 @@ is probably 1, adding a new Git Hook maybe 4 or 5, big features 7-9.
issues or chunks. You can simply not set the weight of a parent issue and set
weights to children issues.
-### Regression issues
+## Regression issues
Every monthly release has a corresponding issue on the CE issue tracker to keep
track of functionality broken by that release and any fixes that need to be
@@ -313,7 +289,7 @@ addressed.
[8.3 Regressions]: https://gitlab.com/gitlab-org/gitlab-ce/issues/4127
[update the notes]: https://gitlab.com/gitlab-org/release-tools/blob/master/doc/pro-tips.md#update-the-regression-issue
-### Technical and UX debt
+## Technical and UX debt
In order to track things that can be improved in GitLab's codebase,
we use the ~"technical debt" label in [GitLab's issue tracker][ce-tracker].
@@ -337,7 +313,7 @@ for a release by the appropriate person.
Make sure to mention the merge request that the ~"technical debt" issue or
~"UX debt" issue is associated with in the description of the issue.
-### Stewardship
+## Stewardship
For issues related to the open source stewardship of GitLab,
there is the ~"stewardship" label.
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index 685287f7a0c..a286e74908c 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -1,15 +1,4 @@
-<!-- START doctoc generated TOC please keep comment here to allow auto update -->
-<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
-**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
-
-- [Merge requests](#merge-requests)
- - [Merge request guidelines](#merge-request-guidelines)
- - [Contribution acceptance criteria](#contribution-acceptance-criteria)
-- [Definition of done](#definition-of-done)
-
-<!-- END doctoc generated TOC please keep comment here to allow auto update -->
-
-## Merge requests
+# Merge requests
We welcome merge requests with fixes and improvements to GitLab code, tests,
and/or documentation. The issues that are specifically suitable for
@@ -36,7 +25,7 @@ some potentially easy issues.
To start with GitLab development download the [GitLab Development Kit][gdk] and
see the [Development section](../README.md) for some guidelines.
-### Merge request guidelines
+## Merge request guidelines
If you can, please submit a merge request with the fix or improvements
including tests. If you don't know how to fix the issue but can write a test
@@ -114,7 +103,7 @@ Please ensure that your merge request meets the contribution acceptance criteria
When having your code reviewed and when reviewing merge requests please take the
[code review guidelines](../code_review.md) into account.
-### Contribution acceptance criteria
+## Contribution acceptance criteria
1. The change is as small as possible
1. Include proper tests and make all tests pass (unless it contains a test
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index d6ae4cb39f0..2db78e4a365 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -43,13 +43,13 @@ how to structure GitLab docs.
Currently GitLab docs use Redcarpet as [markdown](../../user/markdown.md) engine, but there's an [open discussion](https://gitlab.com/gitlab-com/gitlab-docs/issues/50) for implementing Kramdown in the near future.
-All the docs follow the [documentation style guidelines](styleguide.md).
+All the docs follow the [documentation style guidelines](styleguide.md). See [Linting](#linting) for help to follow the guidelines.
## Documentation directory structure
The documentation is structured based on the GitLab UI structure itself,
separated by [`user`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/user),
-[`administrator`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/administration), and [`contributor`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/development).
+[`administrator`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/administration), and [`contributor`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/development).
In order to have a [solid site structure](https://searchengineland.com/seo-benefits-developing-solid-site-structure-277456) for our documentation,
all docs should be linked. Every new document should be cross-linked to its related documentation, and linked from its topic-related index, when existent.
@@ -223,6 +223,108 @@ 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`
+- `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` checks might reduce
+ noise. The following sample `proselint` configuration disables the `typography.symbols` checks:
+
+```json
+{
+ "checks": {
+ "typography.symbols": 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.
+
+```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,
+ "hr-style": { "style": "---" },
+ "fenced-code-language": false
+}
+```
+
+For [`markdownlint`](https://gitahub.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.
@@ -278,7 +380,6 @@ for GitLab Team members.
- Label the MR `Documentation`
- Assign the correct milestone (see note below)
-
NOTE: **Note:**
If the release version you want to add the documentation to has already been
frozen or released, use the label `Pick into X.Y` to get it merged into
diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md
index d4f7bb7ae74..c43f91278de 100644
--- a/doc/development/documentation/styleguide.md
+++ b/doc/development/documentation/styleguide.md
@@ -10,6 +10,8 @@ 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).
+
## Files
- [Directory structure](index.md#location-and-naming-documents): place the docs
diff --git a/doc/development/gitaly.md b/doc/development/gitaly.md
index 4f9ca1920a5..f4784c19359 100644
--- a/doc/development/gitaly.md
+++ b/doc/development/gitaly.md
@@ -9,7 +9,7 @@ status of the migration.
## Developing new Git features
-Starting with Gitlab 10.8, all new Git features should be developed in
+Starting with GitLab 10.8, all new Git features should be developed in
Gitaly.
> This is a new process that is not clearly defined yet. If you want
diff --git a/doc/development/ux_guide/users.md b/doc/development/ux_guide/users.md
index 08f393132e8..f9c395b2dff 100644
--- a/doc/development/ux_guide/users.md
+++ b/doc/development/ux_guide/users.md
@@ -242,7 +242,7 @@ Some of GitLab EE's features are too basic, in particular, issues boards which d
James and his team use CI quite heavily for several projects. Whilst they've welcomed improvements to the builds and pipelines interface, they still have some difficulty following build process on the different tabs under Pipelines. Some confusion has arisen from not knowing where to find different pieces of information or how to get to the next stages logs from the current stage's log output screen. They feel more intuitive linking and flow may alleviate the problem. Generally, they feel GitLab's navigation needs to reviewed and optimized.
#### Permissions
->"There is no granular control over user or group permissions. The permissions for a project are too tightly coupled to the permissions for Gitlab CI/build pipelines."
+>"There is no granular control over user or group permissions. The permissions for a project are too tightly coupled to the permissions for GitLab CI/build pipelines."
### Goals
@@ -290,7 +290,7 @@ JavaScript and SQL
Web development, mobile development, UX, open source, gaming, and travel.
### Motivations
-Karolina has been using GitLab.com for around a year. She roughly spends 8 hours every week programming, of that, 2 hours is spent contributing to open source projects. Karolina contributes to open source projects to gain programming experience and to give back to the community. She likes GitLab.com for its free private repositories and range of features which provide her with everything she needs for her personal projects. Karolina is also a massive fan of GitLab's values and the fact that it isn't a "behemoth of a company". She explains that "displaying every single thing (doc, culture, assumptions, development...) in the open gives me greater confidence to choose Gitlab personally and to recommend it at work." She's also an avid reader of GitLab's blog.
+Karolina has been using GitLab.com for around a year. She roughly spends 8 hours every week programming, of that, 2 hours is spent contributing to open source projects. Karolina contributes to open source projects to gain programming experience and to give back to the community. She likes GitLab.com for its free private repositories and range of features which provide her with everything she needs for her personal projects. Karolina is also a massive fan of GitLab's values and the fact that it isn't a "behemoth of a company". She explains that "displaying every single thing (doc, culture, assumptions, development...) in the open gives me greater confidence to choose GitLab personally and to recommend it at work." She's also an avid reader of GitLab's blog.
Karolina works for a software development company which currently hires around 500 people. Karolina would love to use GitLab at work but the company has used GitHub Enterprise for a number of years. She describes management at her company as "old fashioned" and explains that it's "less of a technical issue and more of a cultural issue" to convince upper management to move to GitLab. Karolina is also relatively new to the company so she's apprehensive about pushing too hard to change version control platforms.
diff --git a/doc/gitlab-basics/add-image.md b/doc/gitlab-basics/add-image.md
index 1a44123aa81..17c210c43e0 100644
--- a/doc/gitlab-basics/add-image.md
+++ b/doc/gitlab-basics/add-image.md
@@ -5,7 +5,7 @@ in Windows, or...), put the image file into the GitLab project. You can find the
project as a regular folder in your files.
Go to your [shell](command-line-commands.md), and move into the folder of your
-Gitlab project. This usually means running the following command until you get
+GitLab project. This usually means running the following command until you get
to the desired destination:
```
diff --git a/doc/install/kubernetes/gitlab_chart.md b/doc/install/kubernetes/gitlab_chart.md
index 09f5aaa04a7..6d1bc4aedc4 100644
--- a/doc/install/kubernetes/gitlab_chart.md
+++ b/doc/install/kubernetes/gitlab_chart.md
@@ -93,7 +93,7 @@ You can access the GitLab instance by visiting the domain name beginning with
above, the URL would be `https://gitlab.example.com`.
If you manually created the secret for initial root password, you
-can use that to sign in as `root` user. If not, Gitlab automatically
+can use that to sign in as `root` user. If not, GitLab automatically
created a random password for `root` user. This can be extracted by the
following command (replace `<name>` by name of the release - which is `gitlab`
if you used the command above):
diff --git a/doc/integration/github.md b/doc/integration/github.md
index 680712f9e01..7a83b8e4b35 100644
--- a/doc/integration/github.md
+++ b/doc/integration/github.md
@@ -19,7 +19,7 @@ GitHub will generate an application ID and secret key for you to use.
- Application name: This can be anything. Consider something like `<Organization>'s GitLab` or `<Your Name>'s GitLab` or something else descriptive.
- Homepage URL: The URL to your GitLab installation. 'https://gitlab.company.com'
- Application description: Fill this in if you wish.
- - Authorization callback URL is 'http(s)://${YOUR_DOMAIN}'. Please make sure the port is included if your Gitlab instance is not configured on default port.
+ - Authorization callback URL is 'http(s)://${YOUR_DOMAIN}'. Please make sure the port is included if your GitLab instance is not configured on default port.
1. Select "Register application".
1. You should now see a Client ID and Client Secret near the top right of the page (see screenshot).
@@ -154,7 +154,7 @@ You will also need to disable Git SSL verification on the server hosting GitLab.
$ git config --global http.sslVerify false
```
-For the changes to take effect, [reconfigure Gitlab] if you installed
+For the changes to take effect, [reconfigure GitLab] if you installed
via Omnibus, or [restart GitLab] if you installed from source.
[reconfigure GitLab]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md
index 98fce7efb0b..2b9cce6539f 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -591,10 +591,11 @@ This procedure assumes that:
First make sure your backup tar file is in the backup directory described in the
`gitlab.rb` configuration `gitlab_rails['backup_path']`. The default is
-`/var/opt/gitlab/backups`.
+`/var/opt/gitlab/backups`. It needs to be owned by the `git` user.
```shell
sudo cp 11493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar /var/opt/gitlab/backups/
+sudo chown git.git /var/opt/gitlab/backups/11493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar
```
Stop the processes that are connected to the database. Leave the rest of GitLab
diff --git a/doc/security/user_email_confirmation.md b/doc/security/user_email_confirmation.md
index 48c79cd4769..8c07e11dcb1 100644
--- a/doc/security/user_email_confirmation.md
+++ b/doc/security/user_email_confirmation.md
@@ -1,6 +1,6 @@
# User email confirmation at sign-up
-Gitlab admin can enable email confirmation on sign-up, if you want to confirm all
+GitLab admin can enable email confirmation on sign-up, if you want to confirm all
user emails before they are able to sign-in.
In the Admin area under **Settings** (`/admin/application_settings`), go to section
diff --git a/doc/university/README.md b/doc/university/README.md
index 203981b85ec..5edf92b3b09 100644
--- a/doc/university/README.md
+++ b/doc/university/README.md
@@ -11,7 +11,7 @@ and [Blog Articles](https://about.gitlab.com/blog/).
Would you like to contribute to GitLab University? Then please take a look at our contribution [process](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/PROCESS.md) for more information.
-## Gitlab University Curriculum
+## GitLab University Curriculum
The curriculum is composed of GitLab videos, screencasts, presentations, projects and external GitLab content hosted on other services and has been organized into the following sections.
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index 0b9395914f9..e14e716a5eb 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -221,7 +221,7 @@ and the following environment variables:
## Cron jobs
-Periodically executed jobs by Sidekiq, to self-heal Gitlab, do external
+Periodically executed jobs by Sidekiq, to self-heal GitLab, do external
synchronizations, run scheduled pipelines, etc.:
| Setting | GitLab.com | Default |
diff --git a/doc/user/index.md b/doc/user/index.md
index 649c0b664a5..08995032cb1 100644
--- a/doc/user/index.md
+++ b/doc/user/index.md
@@ -96,7 +96,7 @@ directly from GitLab. No third-party integrations needed.
- [GitLab Auto Deploy](../ci/autodeploy/index.md): Deploy your application out-of-the-box with GitLab Auto Deploy.
- [Review Apps](../ci/review_apps/index.md): Live-preview the changes introduced by a merge request with Review Apps.
- [GitLab Pages](project/pages/index.md): Publish your static site directly from
-GitLab with Gitlab Pages. You can build, test, and deploy any Static Site Generator with Pages.
+GitLab with GitLab Pages. You can build, test, and deploy any Static Site Generator with Pages.
- [GitLab Container Registry](project/container_registry.md): Build and deploy Docker
images with Container Registry.
diff --git a/doc/user/project/container_registry.md b/doc/user/project/container_registry.md
index 82cafcf432a..2709ebb6f05 100644
--- a/doc/user/project/container_registry.md
+++ b/doc/user/project/container_registry.md
@@ -27,7 +27,7 @@ to enable it.
1. First, ask your system administrator to enable GitLab Container Registry
following the [administration documentation](../../administration/container_registry.md).
If you are using GitLab.com, this is enabled by default so you can start using
- the Registry immediately. Currently there is a soft (10GB) size restriction for
+ the Registry immediately. Currently there is a soft (10GB) size restriction for
registry on GitLab.com, as part of the [repository size limit](repository/index.html#repository-size).
1. Go to your [project's General settings](settings/index.md#sharing-and-permissions)
and enable the **Container Registry** feature on your project. For new
@@ -216,7 +216,7 @@ needs to trust the mitmproxy SSL certificates for this to work.
The following installation instructions assume you are running Ubuntu:
-1. Install mitmproxy (see http://docs.mitmproxy.org/en/stable/install.html)
+1. [Install mitmproxy](https://docs.mitmproxy.org/stable/overview-installation/).
1. Run `mitmproxy --port 9000` to generate its certificates.
Enter <kbd>CTRL</kbd>-<kbd>C</kbd> to quit.
1. Install the certificate from `~/.mitmproxy` to your system:
@@ -293,4 +293,4 @@ Once the right permissions were set, the error will go away.
[docker-docs]: https://docs.docker.com/engine/userguide/intro/
[pat]: ../profile/personal_access_tokens.md
[pdt]: ../project/deploy_tokens/index.md
-[reconfigure]: ../../administration/restart_gitlab.md#omnibus-gitlab-reconfigure \ No newline at end of file
+[reconfigure]: ../../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md
index e22f8e976be..5a38f5d8aed 100644
--- a/doc/user/project/integrations/webhooks.md
+++ b/doc/user/project/integrations/webhooks.md
@@ -1170,7 +1170,7 @@ You can trigger the webhook manually. Sample data from the project will be used.
## Troubleshoot webhooks
-Gitlab stores each perform of the webhook.
+GitLab stores each perform of the webhook.
You can find records for last 2 days in "Recent Deliveries" section on the edit page of each webhook.
![Recent deliveries](img/webhook_logs.png)
diff --git a/lib/api/commits.rb b/lib/api/commits.rb
index fcaff35459e..5aeffc8fb99 100644
--- a/lib/api/commits.rb
+++ b/lib/api/commits.rb
@@ -73,7 +73,26 @@ module API
params do
requires :branch, type: String, desc: 'Name of the branch to commit into. To create a new branch, also provide `start_branch`.', allow_blank: false
requires :commit_message, type: String, desc: 'Commit message'
- requires :actions, type: Array[Hash], desc: 'Actions to perform in commit'
+ requires :actions, type: Array, desc: 'Actions to perform in commit' do
+ requires :action, type: String, desc: 'The action to perform, `create`, `delete`, `move`, `update`, `chmod`', values: %w[create update move delete chmod].freeze
+ requires :file_path, type: String, desc: 'Full path to the file. Ex. `lib/class.rb`'
+ given action: ->(action) { action == 'move' } do
+ requires :previous_path, type: String, desc: 'Original full path to the file being moved. Ex. `lib/class1.rb`'
+ end
+ given action: ->(action) { %w[create move].include? action } do
+ optional :content, type: String, desc: 'File content'
+ end
+ given action: ->(action) { action == 'update' } do
+ requires :content, type: String, desc: 'File content'
+ end
+ optional :encoding, type: String, desc: '`text` or `base64`', default: 'text', values: %w[text base64]
+ given action: ->(action) { %w[update move delete].include? action } do
+ optional :last_commit_id, type: String, desc: 'Last known file commit id'
+ end
+ given action: ->(action) { action == 'chmod' } do
+ requires :execute_filemode, type: Boolean, desc: 'When `true/false` enables/disables the execute flag on the file.'
+ end
+ end
optional :start_branch, type: String, desc: 'Name of the branch to start the new commit from'
optional :author_email, type: String, desc: 'Author email for commit'
optional :author_name, type: String, desc: 'Author name for commit'
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 0fec3dc3dc4..12c4340c1ba 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -53,7 +53,7 @@ module API
class User < UserBasic
expose :created_at, if: ->(user, opts) { Ability.allowed?(opts[:current_user], :read_user_profile, user) }
- expose :bio, :location, :skype, :linkedin, :twitter, :website_url, :organization
+ expose :bio, :location, :public_email, :skype, :linkedin, :twitter, :website_url, :organization
end
class UserActivity < Grape::Entity
diff --git a/lib/event_filter.rb b/lib/event_filter.rb
index f756a211a12..24fdcd6fbb1 100644
--- a/lib/event_filter.rb
+++ b/lib/event_filter.rb
@@ -1,76 +1,42 @@
-class EventFilter
- attr_accessor :params
-
- class << self
- def all
- 'all'
- end
-
- def push
- 'push'
- end
-
- def merged
- 'merged'
- end
+# frozen_string_literal: true
- def issue
- 'issue'
- end
-
- def comments
- 'comments'
- end
-
- def team
- 'team'
- end
+class EventFilter
+ attr_accessor :filter
+
+ ALL = 'all'
+ PUSH = 'push'
+ MERGED = 'merged'
+ ISSUE = 'issue'
+ COMMENTS = 'comments'
+ TEAM = 'team'
+ FILTERS = [ALL, PUSH, MERGED, ISSUE, COMMENTS, TEAM].freeze
+
+ def initialize(filter)
+ # Split using comma to maintain backward compatibility Ex/ "filter1,filter2"
+ filter = filter.to_s.split(',')[0].to_s
+ @filter = FILTERS.include?(filter) ? filter : ALL
end
- def initialize(params)
- @params = if params
- params.dup
- else
- [] # EventFilter.default_filter
- end
+ def active?(key)
+ filter == key.to_s
end
# rubocop: disable CodeReuse/ActiveRecord
def apply_filter(events)
- return events if params.blank? || params == EventFilter.all
-
- case params
- when EventFilter.push
+ case filter
+ when PUSH
events.where(action: Event::PUSHED)
- when EventFilter.merged
+ when MERGED
events.where(action: Event::MERGED)
- when EventFilter.comments
+ when COMMENTS
events.where(action: Event::COMMENTED)
- when EventFilter.team
+ when TEAM
events.where(action: [Event::JOINED, Event::LEFT, Event::EXPIRED])
- when EventFilter.issue
+ when ISSUE
events.where(action: [Event::CREATED, Event::UPDATED, Event::CLOSED, Event::REOPENED])
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def options(key)
- filter = params.dup
-
- if filter.include? key
- filter.delete key
else
- filter << key
- end
-
- filter
- end
-
- def active?(key)
- if params.present?
- params.include? key
- else
- key == EventFilter.all
+ events
end
end
+ # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
index 33ae9c6ad7e..d8fcdfac266 100644
--- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -49,7 +49,7 @@ variables:
POSTGRES_DB: $CI_ENVIRONMENT_SLUG
KUBERNETES_VERSION: 1.8.6
- HELM_VERSION: 2.6.1
+ HELM_VERSION: 2.10.0
DOCKER_DRIVER: overlay2
@@ -122,6 +122,9 @@ license_management:
paths: [gl-license-management-report.json]
only:
- branches
+ only:
+ variables:
+ - $GITLAB_FEATURES =~ /\blicense_management\b/
except:
variables:
- $LICENSE_MANAGEMENT_DISABLED
@@ -484,15 +487,11 @@ rollout 100%:
}
function license_management() {
- if echo $GITLAB_FEATURES |grep license_management > /dev/null ; then
- # Extract "MAJOR.MINOR" from CI_SERVER_VERSION and generate "MAJOR-MINOR-stable"
- LICENSE_MANAGEMENT_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
+ # Extract "MAJOR.MINOR" from CI_SERVER_VERSION and generate "MAJOR-MINOR-stable"
+ LICENSE_MANAGEMENT_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
- docker run --volume "$PWD:/code" \
- "registry.gitlab.com/gitlab-org/security-products/license-management:$LICENSE_MANAGEMENT_VERSION" analyze /code
- else
- echo "License management is not available in your subscription"
- fi
+ docker run --volume "$PWD:/code" \
+ "registry.gitlab.com/gitlab-org/security-products/license-management:$LICENSE_MANAGEMENT_VERSION" analyze /code
}
function sast() {
@@ -605,7 +604,6 @@ rollout 100%:
--set postgresql.postgresPassword="$POSTGRES_PASSWORD" \
--set postgresql.postgresDatabase="$POSTGRES_DB" \
--namespace="$KUBE_NAMESPACE" \
- --version="$CI_PIPELINE_ID-$CI_JOB_ID" \
"$name" \
chart/
diff --git a/lib/gitlab/ci/templates/Julia.gitlab-ci.yml b/lib/gitlab/ci/templates/Julia.gitlab-ci.yml
index 140cb4635f3..04c21b4725d 100644
--- a/lib/gitlab/ci/templates/Julia.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Julia.gitlab-ci.yml
@@ -1,4 +1,4 @@
-# An example .gitlab-ci.yml file to test (and optionally report the coverage
+# This is an example .gitlab-ci.yml file to test (and optionally report the coverage
# results of) your [Julia][1] packages. Please refer to the [documentation][2]
# for more information about package development in Julia.
#
@@ -6,7 +6,7 @@
# whatever name you have given to your package.
#
# [1]: http://julialang.org/
-# [2]: http://julia.readthedocs.org/
+# [2]: https://docs.julialang.org/en/v1/manual/documentation/index.html
# Below is the template to run your tests in Julia
.test_template: &test_definition
@@ -18,25 +18,30 @@
script:
# Let's run the tests. Substitute `coverage = false` below, if you do not
# want coverage results.
- - /opt/julia/bin/julia -e 'Pkg.clone(pwd()); Pkg.test("MyPackage",
- coverage = true)'
+ - julia -e 'using Pkg; Pkg.clone(pwd()); Pkg.build("MyPackage"); Pkg.test("MyPackage"; coverage = true)'
# Comment out below if you do not want coverage results.
- - /opt/julia/bin/julia -e 'Pkg.add("Coverage"); cd(Pkg.dir("MyPackage"));
+ - julia -e 'using Pkg; Pkg.add("Coverage");
+ import MyPackage; cd(joinpath(dirname(pathof(MyPackage)), ".."));
using Coverage; cl, tl = get_summary(process_folder());
println("(", cl/tl*100, "%) covered")'
# Name a test and select an appropriate image.
-test:0.4.6:
- image: julialang/julia:v0.4.6
+# images comes from Docker hub
+test:0.7:
+ image: julia:0.7
+ <<: *test_definition
+
+test:1.0:
+ image: julia:1.0
<<: *test_definition
# Maybe you would like to test your package against the development branch:
-test:0.5.0-dev:
- image: julialang/julia:v0.5.0-dev
- # ... allowing for failures, since we are testing against the development
- # branch:
- allow_failure: true
- <<: *test_definition
+# test:1.1-dev (not sure there is such an image in docker, so not tested yet):
+# image: julia:v1.1-dev
+# # ... allowing for failures, since we are testing against the development
+# # branch:
+# allow_failure: true
+# <<: *test_definition
# REMARK: Do not forget to enable the coverage feature for your project, if you
# are using code coverage reporting above. This can be done by
@@ -44,11 +49,28 @@ test:0.5.0-dev:
# - Navigating to the `CI/CD Pipelines` settings of your project,
# - Copying and pasting the default `Simplecov` regex example provided, i.e.,
# `\(\d+.\d+\%\) covered` in the `test coverage parsing` textfield.
-#
-# WARNING: This template is using the `julialang/julia` images from [Docker
+
+# Example documentation deployment
+pages:
+ image: julia:0.7
+ stage: deploy
+ script:
+ - apt-get update -qq && apt-get install -y git # needed by Documenter
+ - julia -e 'using Pkg; Pkg.clone(pwd()); Pkg.build("MyPackage");' # rebuild Julia (can be put somewhere else I'm sure
+ - julia -e 'using Pkg; import MyPackage; Pkg.add("Documenter")' # install Documenter
+ - julia --color=yes docs/make.jl # make documentation
+ - mv docs/build public # move to the directory picked up by Gitlab pages
+ artifacts:
+ paths:
+ - public
+ only:
+ - master
+
+
+# WARNING: This template is using the `julia` images from [Docker
# Hub][3]. One can use custom Julia images and/or the official ones found
# in the same place. However, care must be taken to correctly locate the binary
# file (`/opt/julia/bin/julia` above), which is usually given on the image's
# description page.
#
-# [3]: http://hub.docker.com/
+# [3]: https://hub.docker.com/_/julia/
diff --git a/lib/gitlab/ci/templates/Pages/Jigsaw.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Jigsaw.gitlab-ci.yml
new file mode 100644
index 00000000000..0e5fb410a4e
--- /dev/null
+++ b/lib/gitlab/ci/templates/Pages/Jigsaw.gitlab-ci.yml
@@ -0,0 +1,42 @@
+# Jigsaw is a simple static sites generator with Laravel's Blade.
+#
+# Full project: https://github.com/tightenco/jigsaw
+
+image: php:7.2
+
+# These folders are cached between builds
+cache:
+ paths:
+ - vendor/
+ - node_modules/
+
+before_script:
+ # Update packages
+ - apt-get update -yqq
+
+ # Install dependencies
+ - apt-get install -yqq gnupg zlib1g-dev libpng-dev
+
+ # Install Node 8
+ - curl -sL https://deb.nodesource.com/setup_8.x | bash -
+ - apt-get install -yqq nodejs
+
+ # Install php extensions
+ - docker-php-ext-install zip
+
+ # Install Composer and project dependencies.
+ - curl -sS https://getcomposer.org/installer | php
+ - php composer.phar install
+
+ # Install Node dependencies.
+ - npm install
+
+pages:
+ script:
+ - npm run production
+ - mv build_production public
+ artifacts:
+ paths:
+ - public
+ only:
+ - master
diff --git a/lib/gitlab/ci/templates/Swift.gitlab-ci.yml b/lib/gitlab/ci/templates/Swift.gitlab-ci.yml
index b97bfd460f2..ba8a802ba4f 100644
--- a/lib/gitlab/ci/templates/Swift.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Swift.gitlab-ci.yml
@@ -1,5 +1,5 @@
# Lifted from: https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/
-# This file assumes an own GitLab CI runner, set up on a macOS system.
+# This file assumes an own GitLab CI runner, setup on a macOS system.
stages:
- build
- archive
diff --git a/lib/gitlab/gitaly_client/operation_service.rb b/lib/gitlab/gitaly_client/operation_service.rb
index 54c78fdb680..0f148614b20 100644
--- a/lib/gitlab/gitaly_client/operation_service.rb
+++ b/lib/gitlab/gitaly_client/operation_service.rb
@@ -333,7 +333,8 @@ module Gitlab
action: action[:action].upcase.to_sym,
file_path: encode_binary(action[:file_path]),
previous_path: encode_binary(action[:previous_path]),
- base64_content: action[:encoding] == 'base64'
+ base64_content: action[:encoding] == 'base64',
+ execute_filemode: !!action[:execute_filemode]
)
rescue RangeError
raise ArgumentError, "Unknown action '#{action[:action]}'"
diff --git a/lib/tasks/gitlab/artifacts/migrate.rake b/lib/tasks/gitlab/artifacts/migrate.rake
index bfca4bfb3f7..e7634d2ed4f 100644
--- a/lib/tasks/gitlab/artifacts/migrate.rake
+++ b/lib/tasks/gitlab/artifacts/migrate.rake
@@ -15,7 +15,7 @@ namespace :gitlab do
build.artifacts_file.migrate!(ObjectStorage::Store::REMOTE)
build.artifacts_metadata.migrate!(ObjectStorage::Store::REMOTE)
- logger.info("Transferred artifacts of #{build.id} of #{build.artifacts_size} to object storage")
+ logger.info("Transferred artifact ID #{build.id} with size #{build.artifacts_size} to object storage")
rescue => e
logger.error("Failed to transfer artifacts of #{build.id} with error: #{e.message}")
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 4d8f05a81cc..a9c5e45f9fa 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -3338,9 +3338,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
diff --git a/package.json b/package.json
index 94707fe3587..714bdb285fe 100644
--- a/package.json
+++ b/package.json
@@ -19,7 +19,7 @@
},
"dependencies": {
"@gitlab-org/gitlab-svgs": "^1.29.0",
- "@gitlab-org/gitlab-ui": "^1.7.0",
+ "@gitlab-org/gitlab-ui": "^1.7.1",
"autosize": "^4.0.0",
"axios": "^0.17.1",
"babel-core": "^6.26.3",
@@ -94,11 +94,11 @@
"underscore": "^1.9.0",
"url-loader": "^1.1.1",
"visibilityjs": "^1.2.4",
- "vue": "^2.5.16",
- "vue-loader": "^15.2.4",
+ "vue": "^2.5.17",
+ "vue-loader": "^15.4.2",
"vue-resource": "^1.5.0",
"vue-router": "^3.0.1",
- "vue-template-compiler": "^2.5.16",
+ "vue-template-compiler": "^2.5.17",
"vue-virtual-scroll-list": "^1.2.5",
"vuex": "^3.0.1",
"webpack": "^4.19.1",
diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb
index 89542b49d0e..9b3183ba328 100644
--- a/qa/qa/page/main/login.rb
+++ b/qa/qa/page/main/login.rb
@@ -108,6 +108,7 @@ module QA
end
def switch_to_register_tab
+ set_initial_password_if_present
click_element :register_tab
end
diff --git a/qa/qa/page/project/activity.rb b/qa/qa/page/project/activity.rb
index 0196922c889..a0500b4d31a 100644
--- a/qa/qa/page/project/activity.rb
+++ b/qa/qa/page/project/activity.rb
@@ -3,7 +3,7 @@ module QA
module Project
class Activity < Page::Base
view 'app/views/shared/_event_filter.html.haml' do
- element :push_events, "event_filter_link EventFilter.push, _('Push events')"
+ element :push_events, "event_filter_link EventFilter::PUSH, _('Push events')"
end
def go_to_push_events
diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb
index c82c85970dc..fd11cb31a2a 100644
--- a/spec/controllers/projects/jobs_controller_spec.rb
+++ b/spec/controllers/projects/jobs_controller_spec.rb
@@ -337,6 +337,22 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
end
end
+
+ context 'when no trace is available' do
+ it 'has_trace is false' do
+ expect(response).to match_response_schema('job/job_details')
+ expect(json_response['has_trace']).to be false
+ end
+ end
+
+ context 'when job has trace' do
+ let(:job) { create(:ci_build, :running, :trace_live, pipeline: pipeline) }
+
+ it "has_trace is true" do
+ expect(response).to match_response_schema('job/job_details')
+ expect(json_response['has_trace']).to be true
+ end
+ end
end
context 'when requesting JSON job is triggered' do
diff --git a/spec/factories/events.rb b/spec/factories/events.rb
index 5798b81ecad..bf8411b1894 100644
--- a/spec/factories/events.rb
+++ b/spec/factories/events.rb
@@ -24,7 +24,7 @@ FactoryBot.define do
factory :push_event, class: PushEvent do
project factory: :project_empty_repo
- author factory: :user
+ author(factory: :user) { project.creator }
action Event::PUSHED
end
diff --git a/spec/features/projects/activity/user_sees_activity_spec.rb b/spec/features/projects/activity/user_sees_activity_spec.rb
index e0248911b5f..ebaa137772d 100644
--- a/spec/features/projects/activity/user_sees_activity_spec.rb
+++ b/spec/features/projects/activity/user_sees_activity_spec.rb
@@ -3,8 +3,10 @@ require 'spec_helper'
describe 'Projects > Activity > User sees activity' do
let(:project) { create(:project, :repository, :public) }
let(:user) { project.creator }
+ let(:issue) { create(:issue, project: project) }
before do
+ create(:event, :created, project: project, target: issue, author: user)
event = create(:push_event, project: project, author: user)
create(:push_event_payload,
event: event,
@@ -12,10 +14,18 @@ describe 'Projects > Activity > User sees activity' do
commit_to: '6d394385cf567f80a8fd85055db1ab4c5295806f',
ref: 'fix',
commit_count: 1)
- visit activity_project_path(project)
end
it 'shows the last push in the activity page', :js do
+ visit activity_project_path(project)
+
expect(page).to have_content "#{user.name} pushed new branch fix"
end
+
+ it 'allows to filter event with the "event_filter=issue" URL param', :js do
+ visit activity_project_path(project, event_filter: 'issue')
+
+ expect(page).not_to have_content "#{user.name} pushed new branch fix"
+ expect(page).to have_content "#{user.name} opened issue #{issue.to_reference}"
+ end
end
diff --git a/spec/fixtures/api/schemas/job/job_details.json b/spec/fixtures/api/schemas/job/job_details.json
index cd67d3e4160..70d59c6e621 100644
--- a/spec/fixtures/api/schemas/job/job_details.json
+++ b/spec/fixtures/api/schemas/job/job_details.json
@@ -3,12 +3,16 @@
{ "$ref": "job.json" }
],
"description": "An extension of job.json with more detailed information",
+ "required": [
+ "has_trace"
+ ],
"properties": {
"artifact": { "$ref": "artifact.json" },
"terminal_path": { "type": "string" },
"trigger": { "$ref": "trigger.json" },
"deployment_status": { "$ref": "deployment_status.json" },
"runner": { "$ref": "runner.json" },
- "runners": { "type": "runners.json" }
+ "runners": { "type": "runners.json" },
+ "has_trace": { "type": "boolean" }
}
}
diff --git a/spec/javascripts/jobs/components/empty_state_spec.js b/spec/javascripts/jobs/components/empty_state_spec.js
index dcc2b3d8a20..872cc1e3864 100644
--- a/spec/javascripts/jobs/components/empty_state_spec.js
+++ b/spec/javascripts/jobs/components/empty_state_spec.js
@@ -66,7 +66,7 @@ describe('Empty State', () => {
...props,
content,
action: {
- link: 'runner',
+ path: 'runner',
title: 'Check runner',
method: 'post',
},
diff --git a/spec/javascripts/jobs/components/erased_block_spec.js b/spec/javascripts/jobs/components/erased_block_spec.js
index a4ae0c7c81e..8e0433d3fb7 100644
--- a/spec/javascripts/jobs/components/erased_block_spec.js
+++ b/spec/javascripts/jobs/components/erased_block_spec.js
@@ -18,9 +18,10 @@ describe('Erased block', () => {
describe('with job erased by user', () => {
beforeEach(() => {
vm = mountComponent(Component, {
- erasedByUser: true,
- username: 'root',
- linkToUser: 'gitlab.com/root',
+ user: {
+ username: 'root',
+ web_url: 'gitlab.com/root',
+ },
erasedAt,
});
});
@@ -40,7 +41,6 @@ describe('Erased block', () => {
describe('with erased job', () => {
beforeEach(() => {
vm = mountComponent(Component, {
- erasedByUser: false,
erasedAt,
});
});
diff --git a/spec/javascripts/jobs/components/job_details_mediator_spec.js b/spec/javascripts/jobs/components/job_details_mediator_spec.js
deleted file mode 100644
index 3e2fb7bfbbb..00000000000
--- a/spec/javascripts/jobs/components/job_details_mediator_spec.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import JobMediator from '~/jobs/job_details_mediator';
-import job from '../mock_data';
-
-describe('JobMediator', () => {
- let mediator;
- let mock;
-
- beforeEach(() => {
- mediator = new JobMediator({ endpoint: 'jobs/40291672.json' });
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('should set defaults', () => {
- expect(mediator.store).toBeDefined();
- expect(mediator.service).toBeDefined();
- expect(mediator.options).toEqual({ endpoint: 'jobs/40291672.json' });
- expect(mediator.state.isLoading).toEqual(false);
- });
-
- describe('request and store data', () => {
- beforeEach(() => {
- mock.onGet().reply(200, job, {});
- });
-
- it('should store received data', (done) => {
- mediator.fetchJob();
- setTimeout(() => {
- expect(mediator.store.state.job).toEqual(job);
- done();
- }, 0);
- });
- });
-});
diff --git a/spec/javascripts/jobs/components/job_log_controllers_spec.js b/spec/javascripts/jobs/components/job_log_controllers_spec.js
index 416dfab8a48..099aca602c4 100644
--- a/spec/javascripts/jobs/components/job_log_controllers_spec.js
+++ b/spec/javascripts/jobs/components/job_log_controllers_spec.js
@@ -10,50 +10,51 @@ describe('Job log controllers', () => {
vm.$destroy();
});
- describe('Truncate information', () => {
+ const props = {
+ rawPath: '/raw',
+ erasePath: '/erase',
+ size: 511952,
+ isScrollTopDisabled: false,
+ isScrollBottomDisabled: false,
+ isScrollingDown: true,
+ isTraceSizeVisible: true,
+ };
- beforeEach(() => {
- vm = mountComponent(Component, {
- rawTracePath: '/raw',
- canEraseJob: true,
- size: 511952,
- canScrollToTop: true,
- canScrollToBottom: true,
+ describe('Truncate information', () => {
+ describe('with isTraceSizeVisible', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, props);
+ });
+ it('renders size information', () => {
+ expect(vm.$el.querySelector('.js-truncated-info').textContent).toContain('499.95 KiB');
});
- });
-
- it('renders size information', () => {
- expect(vm.$el.querySelector('.js-truncated-info').textContent).toContain('499.95 KiB');
- });
- it('renders link to raw trace', () => {
- expect(vm.$el.querySelector('.js-raw-link').getAttribute('href')).toEqual('/raw');
+ it('renders link to raw trace', () => {
+ expect(vm.$el.querySelector('.js-raw-link').getAttribute('href')).toEqual('/raw');
+ });
});
-
});
describe('links section', () => {
describe('with raw trace path', () => {
it('renders raw trace link', () => {
- vm = mountComponent(Component, {
- rawTracePath: '/raw',
- canEraseJob: true,
- size: 511952,
- canScrollToTop: true,
- canScrollToBottom: true,
- });
+ vm = mountComponent(Component, props);
- expect(vm.$el.querySelector('.js-raw-link-controller').getAttribute('href')).toEqual('/raw');
+ expect(vm.$el.querySelector('.js-raw-link-controller').getAttribute('href')).toEqual(
+ '/raw',
+ );
});
});
describe('without raw trace path', () => {
it('does not render raw trace link', () => {
vm = mountComponent(Component, {
- canEraseJob: true,
+ erasePath: '/erase',
size: 511952,
- canScrollToTop: true,
- canScrollToBottom: true,
+ isScrollTopDisabled: true,
+ isScrollBottomDisabled: true,
+ isScrollingDown: false,
+ isTraceSizeVisible: true,
});
expect(vm.$el.querySelector('.js-raw-link-controller')).toBeNull();
@@ -62,52 +63,23 @@ describe('Job log controllers', () => {
describe('when is erasable', () => {
beforeEach(() => {
- vm = mountComponent(Component, {
- rawTracePath: '/raw',
- canEraseJob: true,
- size: 511952,
- canScrollToTop: true,
- canScrollToBottom: true,
- });
+ vm = mountComponent(Component, props);
});
- it('renders erase job button', () => {
+ it('renders erase job link', () => {
expect(vm.$el.querySelector('.js-erase-link')).not.toBeNull();
});
-
- describe('on click', () => {
- describe('when user confirms action', () => {
- it('emits eraseJob event', () => {
- spyOn(window, 'confirm').and.returnValue(true);
- spyOn(vm, '$emit');
-
- vm.$el.querySelector('.js-erase-link').click();
-
- expect(vm.$emit).toHaveBeenCalledWith('eraseJob');
- });
- });
-
- describe('when user does not confirm action', () => {
- it('does not emit eraseJob event', () => {
- spyOn(window, 'confirm').and.returnValue(false);
- spyOn(vm, '$emit');
-
- vm.$el.querySelector('.js-erase-link').click();
-
- expect(vm.$emit).not.toHaveBeenCalledWith('eraseJob');
- });
- });
- });
});
describe('when it is not erasable', () => {
it('does not render erase button', () => {
vm = mountComponent(Component, {
- rawTracePath: '/raw',
- canEraseJob: false,
+ rawPath: '/raw',
size: 511952,
- canScrollToTop: true,
- canScrollToBottom: true,
+ isScrollTopDisabled: true,
+ isScrollBottomDisabled: true,
+ isScrollingDown: false,
+ isTraceSizeVisible: true,
});
expect(vm.$el.querySelector('.js-erase-link')).toBeNull();
@@ -119,13 +91,7 @@ describe('Job log controllers', () => {
describe('scroll top button', () => {
describe('when user can scroll top', () => {
beforeEach(() => {
- vm = mountComponent(Component, {
- rawTracePath: '/raw',
- canEraseJob: true,
- size: 511952,
- canScrollToTop: true,
- canScrollToBottom: true,
- });
+ vm = mountComponent(Component, props);
});
it('renders enabled scroll top button', () => {
@@ -143,16 +109,20 @@ describe('Job log controllers', () => {
describe('when user can not scroll top', () => {
beforeEach(() => {
vm = mountComponent(Component, {
- rawTracePath: '/raw',
- canEraseJob: true,
+ rawPath: '/raw',
+ erasePath: '/erase',
size: 511952,
- canScrollToTop: false,
- canScrollToBottom: true,
+ isScrollTopDisabled: true,
+ isScrollBottomDisabled: false,
+ isScrollingDown: false,
+ isTraceSizeVisible: true,
});
});
it('renders disabled scroll top button', () => {
- expect(vm.$el.querySelector('.js-scroll-top').getAttribute('disabled')).toEqual('disabled');
+ expect(vm.$el.querySelector('.js-scroll-top').getAttribute('disabled')).toEqual(
+ 'disabled',
+ );
});
it('does not emit scrollJobLogTop event on click', () => {
@@ -167,13 +137,7 @@ describe('Job log controllers', () => {
describe('scroll bottom button', () => {
describe('when user can scroll bottom', () => {
beforeEach(() => {
- vm = mountComponent(Component, {
- rawTracePath: '/raw',
- canEraseJob: true,
- size: 511952,
- canScrollToTop: true,
- canScrollToBottom: true,
- });
+ vm = mountComponent(Component, props);
});
it('renders enabled scroll bottom button', () => {
@@ -191,17 +155,20 @@ describe('Job log controllers', () => {
describe('when user can not scroll bottom', () => {
beforeEach(() => {
vm = mountComponent(Component, {
- rawTracePath: '/raw',
- canEraseJob: true,
+ rawPath: '/raw',
+ erasePath: '/erase',
size: 511952,
- canScrollToTop: true,
- canScrollToBottom: false,
+ isScrollTopDisabled: false,
+ isScrollBottomDisabled: true,
+ isScrollingDown: false,
+ isTraceSizeVisible: true,
});
});
it('renders disabled scroll bottom button', () => {
- expect(vm.$el.querySelector('.js-scroll-bottom').getAttribute('disabled')).toEqual('disabled');
-
+ expect(vm.$el.querySelector('.js-scroll-bottom').getAttribute('disabled')).toEqual(
+ 'disabled',
+ );
});
it('does not emit scrollJobLogBottom event on click', () => {
@@ -211,7 +178,29 @@ describe('Job log controllers', () => {
expect(vm.$emit).not.toHaveBeenCalledWith('scrollJobLogBottom');
});
});
+
+ describe('while isScrollingDown is true', () => {
+ it('renders animate class for the scroll down button', () => {
+ vm = mountComponent(Component, props);
+
+ expect(vm.$el.querySelector('.js-scroll-bottom').className).toContain('animate');
+ });
+ });
+
+ describe('while isScrollingDown is false', () => {
+ it('does not render animate class for the scroll down button', () => {
+ vm = mountComponent(Component, {
+ rawPath: '/raw',
+ erasePath: '/erase',
+ size: 511952,
+ isScrollTopDisabled: true,
+ isScrollBottomDisabled: false,
+ isScrollingDown: false,
+ isTraceSizeVisible: true,
+ });
+ expect(vm.$el.querySelector('.js-scroll-bottom').className).not.toContain('animate');
+ });
+ });
});
});
});
-
diff --git a/spec/javascripts/jobs/components/job_log_spec.js b/spec/javascripts/jobs/components/job_log_spec.js
index 6a5b375a26c..1011512360d 100644
--- a/spec/javascripts/jobs/components/job_log_spec.js
+++ b/spec/javascripts/jobs/components/job_log_spec.js
@@ -15,7 +15,7 @@ describe('Job Log', () => {
it('renders provided trace', () => {
vm = mountComponent(Component, {
trace,
- isReceivingBuildTrace: true,
+ isComplete: true,
});
expect(vm.$el.querySelector('code').textContent).toContain('Running with gitlab-runner 11.1.0 (081978aa)');
@@ -25,7 +25,7 @@ describe('Job Log', () => {
it('renders animation', () => {
vm = mountComponent(Component, {
trace,
- isReceivingBuildTrace: true,
+ isComplete: true,
});
expect(vm.$el.querySelector('.js-log-animation')).not.toBeNull();
@@ -36,7 +36,7 @@ describe('Job Log', () => {
it('does not render animation', () => {
vm = mountComponent(Component, {
trace,
- isReceivingBuildTrace: false,
+ isComplete: false,
});
expect(vm.$el.querySelector('.js-log-animation')).toBeNull();
diff --git a/spec/javascripts/jobs/components/job_store_spec.js b/spec/javascripts/jobs/components/job_store_spec.js
deleted file mode 100644
index 0dad5111b32..00000000000
--- a/spec/javascripts/jobs/components/job_store_spec.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import JobStore from '~/jobs/stores/job_store';
-import job from '../mock_data';
-
-describe('Job Store', () => {
- let store;
-
- beforeEach(() => {
- store = new JobStore();
- });
-
- it('should set defaults', () => {
- expect(store.state.job).toEqual({});
- });
-
- describe('storeJob', () => {
- it('should store empty object if none is provided', () => {
- store.storeJob();
- expect(store.state.job).toEqual({});
- });
-
- it('should store provided argument', () => {
- store.storeJob(job);
- expect(store.state.job).toEqual(job);
- });
- });
-});
diff --git a/spec/javascripts/jobs/store/mutations_spec.js b/spec/javascripts/jobs/store/mutations_spec.js
index 6900b2e5602..9ba543d32a8 100644
--- a/spec/javascripts/jobs/store/mutations_spec.js
+++ b/spec/javascripts/jobs/store/mutations_spec.js
@@ -12,6 +12,13 @@ describe('Jobs Store Mutations', () => {
stateCopy = state();
});
+ describe('SET_JOB_ENDPOINT', () => {
+ it('should set jobEndpoint', () => {
+ mutations[types.SET_JOB_ENDPOINT](stateCopy, 'job/21312321.json');
+ expect(stateCopy.jobEndpoint).toEqual('job/21312321.json');
+ });
+ });
+
describe('REQUEST_STATUS_FAVICON', () => {
it('should set fetchingStatusFavicon to true', () => {
mutations[types.REQUEST_STATUS_FAVICON](stateCopy);
diff --git a/spec/javascripts/monitoring/dashboard_spec.js b/spec/javascripts/monitoring/dashboard_spec.js
index 997163c7602..f0d53b2d8d7 100644
--- a/spec/javascripts/monitoring/dashboard_spec.js
+++ b/spec/javascripts/monitoring/dashboard_spec.js
@@ -25,7 +25,10 @@ describe('Dashboard', () => {
};
beforeEach(() => {
- setFixtures('<div class="prometheus-graphs"></div>');
+ setFixtures(`
+ <div class="prometheus-graphs"></div>
+ <div class="nav-sidebar"></div>
+ `);
DashboardComponent = Vue.extend(Dashboard);
});
@@ -127,4 +130,41 @@ describe('Dashboard', () => {
});
});
});
+
+ describe('when the window resizes', () => {
+ let mock;
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
+ jasmine.clock().install();
+ });
+
+ afterEach(() => {
+ mock.restore();
+ jasmine.clock().uninstall();
+ });
+
+ it('rerenders the dashboard when the sidebar is resized', done => {
+ const component = new DashboardComponent({
+ el: document.querySelector('.prometheus-graphs'),
+ propsData: { ...propsData, hasMetrics: true, showPanels: false },
+ });
+
+ expect(component.forceRedraw).toEqual(0);
+
+ const navSidebarEl = document.querySelector('.nav-sidebar');
+ navSidebarEl.classList.add('nav-sidebar-collapsed');
+
+ Vue.nextTick()
+ .then(() => {
+ jasmine.clock().tick(1000);
+ return Vue.nextTick();
+ })
+ .then(() => {
+ expect(component.forceRedraw).toEqual(component.elWidth);
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
});
diff --git a/spec/javascripts/monitoring/graph_spec.js b/spec/javascripts/monitoring/graph_spec.js
index 990619b4109..99180e4d303 100644
--- a/spec/javascripts/monitoring/graph_spec.js
+++ b/spec/javascripts/monitoring/graph_spec.js
@@ -1,7 +1,6 @@
import Vue from 'vue';
import Graph from '~/monitoring/components/graph.vue';
import MonitoringMixins from '~/monitoring/mixins/monitoring_mixins';
-import eventHub from '~/monitoring/event_hub';
import {
deploymentData,
convertDatesMultipleSeries,
@@ -69,23 +68,6 @@ describe('Graph', () => {
});
});
- it('sends an event to the eventhub when it has finished resizing', done => {
- const component = createComponent({
- graphData: convertedMetrics[1],
- updateAspectRatio: false,
- deploymentData,
- tagsPath,
- projectPath,
- });
- spyOn(eventHub, '$emit');
-
- component.updateAspectRatio = true;
- Vue.nextTick(() => {
- expect(eventHub.$emit).toHaveBeenCalled();
- done();
- });
- });
-
it('has a title for the y-axis and the chart legend that comes from the backend', () => {
const component = createComponent({
graphData: convertedMetrics[1],
diff --git a/spec/lib/event_filter_spec.rb b/spec/lib/event_filter_spec.rb
index 87ae6b6cf01..30016da6828 100644
--- a/spec/lib/event_filter_spec.rb
+++ b/spec/lib/event_filter_spec.rb
@@ -1,58 +1,119 @@
require 'spec_helper'
describe EventFilter do
+ describe 'FILTERS' do
+ it 'returns a definite list of filters' do
+ expect(described_class::FILTERS).to eq(%w[all push merged issue comments team])
+ end
+ end
+
+ describe '#filter' do
+ it 'returns "all" if given filter is nil' do
+ expect(described_class.new(nil).filter).to eq(described_class::ALL)
+ end
+
+ it 'returns "all" if given filter is ""' do
+ expect(described_class.new('').filter).to eq(described_class::ALL)
+ end
+
+ it 'returns "all" if given filter is "foo"' do
+ expect(described_class.new('foo').filter).to eq('all')
+ end
+ end
+
describe '#apply_filter' do
- let(:source_user) { create(:user) }
- let!(:public_project) { create(:project, :public) }
+ set(:public_project) { create(:project, :public) }
+
+ set(:push_event) { create(:push_event, project: public_project) }
+ set(:merged_event) { create(:event, :merged, project: public_project, target: public_project) }
+ set(:created_event) { create(:event, :created, project: public_project, target: public_project) }
+ set(:updated_event) { create(:event, :updated, project: public_project, target: public_project) }
+ set(:closed_event) { create(:event, :closed, project: public_project, target: public_project) }
+ set(:reopened_event) { create(:event, :reopened, project: public_project, target: public_project) }
+ set(:comments_event) { create(:event, :commented, project: public_project, target: public_project) }
+ set(:joined_event) { create(:event, :joined, project: public_project, target: public_project) }
+ set(:left_event) { create(:event, :left, project: public_project, target: public_project) }
- let!(:push_event) { create(:push_event, project: public_project, author: source_user) }
- let!(:merged_event) { create(:event, :merged, project: public_project, target: public_project, author: source_user) }
- let!(:created_event) { create(:event, :created, project: public_project, target: public_project, author: source_user) }
- let!(:updated_event) { create(:event, :updated, project: public_project, target: public_project, author: source_user) }
- let!(:closed_event) { create(:event, :closed, project: public_project, target: public_project, author: source_user) }
- let!(:reopened_event) { create(:event, :reopened, project: public_project, target: public_project, author: source_user) }
- let!(:comments_event) { create(:event, :commented, project: public_project, target: public_project, author: source_user) }
- let!(:joined_event) { create(:event, :joined, project: public_project, target: public_project, author: source_user) }
- let!(:left_event) { create(:event, :left, project: public_project, target: public_project, author: source_user) }
+ let(:filtered_events) { described_class.new(filter).apply_filter(Event.all) }
- it 'applies push filter' do
- events = described_class.new(described_class.push).apply_filter(Event.all)
- expect(events).to contain_exactly(push_event)
+ context 'with the "push" filter' do
+ let(:filter) { described_class::PUSH }
+
+ it 'filters push events only' do
+ expect(filtered_events).to contain_exactly(push_event)
+ end
end
- it 'applies merged filter' do
- events = described_class.new(described_class.merged).apply_filter(Event.all)
- expect(events).to contain_exactly(merged_event)
+ context 'with the "merged" filter' do
+ let(:filter) { described_class::MERGED }
+
+ it 'filters merged events only' do
+ expect(filtered_events).to contain_exactly(merged_event)
+ end
end
- it 'applies issue filter' do
- events = described_class.new(described_class.issue).apply_filter(Event.all)
- expect(events).to contain_exactly(created_event, updated_event, closed_event, reopened_event)
+ context 'with the "issue" filter' do
+ let(:filter) { described_class::ISSUE }
+
+ it 'filters issue events only' do
+ expect(filtered_events).to contain_exactly(created_event, updated_event, closed_event, reopened_event)
+ end
end
- it 'applies comments filter' do
- events = described_class.new(described_class.comments).apply_filter(Event.all)
- expect(events).to contain_exactly(comments_event)
+ context 'with the "comments" filter' do
+ let(:filter) { described_class::COMMENTS }
+
+ it 'filters comment events only' do
+ expect(filtered_events).to contain_exactly(comments_event)
+ end
end
- it 'applies team filter' do
- events = described_class.new(described_class.team).apply_filter(Event.all)
- expect(events).to contain_exactly(joined_event, left_event)
+ context 'with the "team" filter' do
+ let(:filter) { described_class::TEAM }
+
+ it 'filters team events only' do
+ expect(filtered_events).to contain_exactly(joined_event, left_event)
+ end
end
- it 'applies all filter' do
- events = described_class.new(described_class.all).apply_filter(Event.all)
- expect(events).to contain_exactly(push_event, merged_event, created_event, updated_event, closed_event, reopened_event, comments_event, joined_event, left_event)
+ context 'with the "all" filter' do
+ let(:filter) { described_class::ALL }
+
+ it 'returns all events' do
+ expect(filtered_events).to eq(Event.all)
+ end
+ end
+
+ context 'with an unknown filter' do
+ let(:filter) { 'foo' }
+
+ it 'returns all events' do
+ expect(filtered_events).to eq(Event.all)
+ end
+ end
+
+ context 'with a nil filter' do
+ let(:filter) { nil }
+
+ it 'returns all events' do
+ expect(filtered_events).to eq(Event.all)
+ end
+ end
+ end
+
+ describe '#active?' do
+ let(:event_filter) { described_class.new(described_class::TEAM) }
+
+ it 'returns false if filter does not include the given key' do
+ expect(event_filter.active?('foo')).to eq(false)
end
- it 'applies no filter' do
- events = described_class.new(nil).apply_filter(Event.all)
- expect(events).to contain_exactly(push_event, merged_event, created_event, updated_event, closed_event, reopened_event, comments_event, joined_event, left_event)
+ it 'returns false if the given key is nil' do
+ expect(event_filter.active?(nil)).to eq(false)
end
- it 'applies unknown filter' do
- events = described_class.new('').apply_filter(Event.all)
- expect(events).to contain_exactly(push_event, merged_event, created_event, updated_event, closed_event, reopened_event, comments_event, joined_event, left_event)
+ it 'returns true if filter does not include the given key' do
+ expect(event_filter.active?(described_class::TEAM)).to eq(true)
end
end
end
diff --git a/spec/models/clusters/applications/jupyter_spec.rb b/spec/models/clusters/applications/jupyter_spec.rb
index 591a01d78a9..9c4396731eb 100644
--- a/spec/models/clusters/applications/jupyter_spec.rb
+++ b/spec/models/clusters/applications/jupyter_spec.rb
@@ -108,8 +108,15 @@ describe Clusters::Applications::Jupyter do
expect(values).to include('rbac')
expect(values).to include('proxy')
expect(values).to include('auth')
+ expect(values).to include('singleuser')
expect(values).to match(/clientId: '?#{application.oauth_application.uid}/)
expect(values).to match(/callbackUrl: '?#{application.callback_url}/)
end
+
+ context 'when cluster belongs to a project' do
+ it 'sets GitLab project id' do
+ expect(values).to match(/GITLAB_CLUSTER_ID: '?#{application.cluster.id}/)
+ end
+ end
end
end
diff --git a/spec/models/event_collection_spec.rb b/spec/models/event_collection_spec.rb
index e0a87c18cc7..6078f429bdc 100644
--- a/spec/models/event_collection_spec.rb
+++ b/spec/models/event_collection_spec.rb
@@ -41,7 +41,7 @@ describe EventCollection do
end
it 'allows filtering of events using an EventFilter' do
- filter = EventFilter.new(EventFilter.issue)
+ filter = EventFilter.new(EventFilter::ISSUE)
events = described_class.new(projects, filter: filter).to_a
expect(events.length).to eq(1)
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index d5b31610dad..f3fb88474a4 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -238,7 +238,7 @@ describe API::Commits do
describe 'create' do
let(:message) { 'Created file' }
- let!(:invalid_c_params) do
+ let(:invalid_c_params) do
{
branch: 'master',
commit_message: message,
@@ -251,7 +251,7 @@ describe API::Commits do
]
}
end
- let!(:valid_c_params) do
+ let(:valid_c_params) do
{
branch: 'master',
commit_message: message,
@@ -264,7 +264,7 @@ describe API::Commits do
]
}
end
- let!(:valid_utf8_c_params) do
+ let(:valid_utf8_c_params) do
{
branch: 'master',
commit_message: message,
@@ -315,7 +315,7 @@ describe API::Commits do
describe 'delete' do
let(:message) { 'Deleted file' }
- let!(:invalid_d_params) do
+ let(:invalid_d_params) do
{
branch: 'markdown',
commit_message: message,
@@ -327,7 +327,7 @@ describe API::Commits do
]
}
end
- let!(:valid_d_params) do
+ let(:valid_d_params) do
{
branch: 'markdown',
commit_message: message,
@@ -356,7 +356,7 @@ describe API::Commits do
describe 'move' do
let(:message) { 'Moved file' }
- let!(:invalid_m_params) do
+ let(:invalid_m_params) do
{
branch: 'feature',
commit_message: message,
@@ -370,7 +370,7 @@ describe API::Commits do
]
}
end
- let!(:valid_m_params) do
+ let(:valid_m_params) do
{
branch: 'feature',
commit_message: message,
@@ -401,7 +401,7 @@ describe API::Commits do
describe 'update' do
let(:message) { 'Updated file' }
- let!(:invalid_u_params) do
+ let(:invalid_u_params) do
{
branch: 'master',
commit_message: message,
@@ -414,7 +414,7 @@ describe API::Commits do
]
}
end
- let!(:valid_u_params) do
+ let(:valid_u_params) do
{
branch: 'master',
commit_message: message,
@@ -442,9 +442,57 @@ describe API::Commits do
end
end
+ describe 'chmod' do
+ let(:message) { 'Chmod +x file' }
+ let(:file_path) { 'files/ruby/popen.rb' }
+ let(:execute_filemode) { true }
+ let(:params) do
+ {
+ branch: 'master',
+ commit_message: message,
+ actions: [
+ {
+ action: 'chmod',
+ file_path: file_path,
+ execute_filemode: execute_filemode
+ }
+ ]
+ }
+ end
+
+ it 'responds with success' do
+ post api(url, user), params
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['title']).to eq(message)
+ end
+
+ context 'when execute_filemode is false' do
+ let(:execute_filemode) { false }
+
+ it 'responds with success' do
+ post api(url, user), params
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['title']).to eq(message)
+ end
+ end
+
+ context "when the file doesn't exists" do
+ let(:file_path) { 'foo/bar.baz' }
+
+ it "responds with 400" do
+ post api(url, user), params
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['message']).to eq("A file with this name doesn't exist")
+ end
+ end
+ end
+
describe 'multiple operations' do
let(:message) { 'Multiple actions' }
- let!(:invalid_mo_params) do
+ let(:invalid_mo_params) do
{
branch: 'master',
commit_message: message,
@@ -468,11 +516,16 @@ describe API::Commits do
action: 'update',
file_path: 'foo/bar.baz',
content: 'puts 8'
+ },
+ {
+ action: 'chmod',
+ file_path: 'files/ruby/popen.rb',
+ execute_filemode: true
}
]
}
end
- let!(:valid_mo_params) do
+ let(:valid_mo_params) do
{
branch: 'master',
commit_message: message,
@@ -496,6 +549,11 @@ describe API::Commits do
action: 'update',
file_path: 'files/ruby/popen.rb',
content: 'puts 8'
+ },
+ {
+ action: 'chmod',
+ file_path: 'files/ruby/popen.rb',
+ execute_filemode: true
}
]
}
diff --git a/spec/services/files/multi_service_spec.rb b/spec/services/files/multi_service_spec.rb
index 3bdedaf3770..5f3c8e82715 100644
--- a/spec/services/files/multi_service_spec.rb
+++ b/spec/services/files/multi_service_spec.rb
@@ -11,6 +11,7 @@ describe Files::MultiService do
let(:new_file_path) { 'files/ruby/popen.rb' }
let(:file_content) { 'New content' }
let(:action) { 'update' }
+ let(:commit_message) { 'Update File' }
let!(:original_commit_id) do
Gitlab::Git::Commit.last_for_path(project.repository, branch_name, original_file_path).sha
@@ -30,7 +31,7 @@ describe Files::MultiService do
let(:commit_params) do
{
- commit_message: "Update File",
+ commit_message: commit_message,
branch_name: branch_name,
start_branch: branch_name,
actions: actions
@@ -84,6 +85,39 @@ describe Files::MultiService do
end
end
+ describe 'changing execute_filemode of a file' do
+ let(:commit_message) { 'Chmod +x file' }
+ let(:file_path) { original_file_path }
+ let(:default_action) do
+ {
+ action: 'chmod',
+ file_path: file_path,
+ execute_filemode: true
+ }
+ end
+
+ it 'accepts the commit' do
+ results = subject.execute
+
+ expect(results[:status]).to eq(:success)
+ end
+
+ it 'updates the execute_filemode of the file' do
+ expect { subject.execute }.to change { repository.blob_at_branch(branch_name, file_path).mode }.from('100644').to('100755')
+ end
+
+ context "when the file doesn't exists" do
+ let(:file_path) { 'files/wrong_path.rb' }
+
+ it 'rejects the commit' do
+ results = subject.execute
+
+ expect(results[:status]).to eq(:error)
+ expect(results[:message]).to eq("A file with this name doesn't exist")
+ end
+ end
+ end
+
context 'when moving a file' do
let(:action) { 'move' }
let(:new_file_path) { 'files/ruby/new_popen.rb' }
diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb
index 06cad9c00d2..ac0ca1f33a5 100644
--- a/spec/services/quick_actions/interpret_service_spec.rb
+++ b/spec/services/quick_actions/interpret_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe QuickActions::InterpretService do
@@ -863,6 +865,13 @@ describe QuickActions::InterpretService do
let(:source_issuable) { create(:labeled_issue, project: project, labels: [inreview_label, todo_label]) }
let(:content) { "/copy_metadata #{source_issuable.to_reference}" }
+ let(:issuable) { build(:issue, project: project) }
+ end
+
+ it_behaves_like 'copy_metadata command' do
+ let(:source_issuable) { create(:labeled_issue, project: project, labels: [inreview_label, todo_label]) }
+
+ let(:content) { "/copy_metadata #{source_issuable.to_reference}" }
let(:issuable) { issue }
end
diff --git a/yarn.lock b/yarn.lock
index 397fd4a2c13..33849642705 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -164,9 +164,9 @@
version "1.29.0"
resolved "https://registry.yarnpkg.com/@gitlab-org/gitlab-svgs/-/gitlab-svgs-1.29.0.tgz#03b65b513f9099bbda6ecf94d673a2952f8c6c70"
-"@gitlab-org/gitlab-ui@^1.7.0":
- version "1.7.0"
- resolved "https://registry.yarnpkg.com/@gitlab-org/gitlab-ui/-/gitlab-ui-1.7.0.tgz#cf37b7262f90af42664d4d1600917271a8f8fb28"
+"@gitlab-org/gitlab-ui@^1.7.1":
+ version "1.7.1"
+ resolved "https://registry.yarnpkg.com/@gitlab-org/gitlab-ui/-/gitlab-ui-1.7.1.tgz#e9cce86cb7e34311405e705c1de674276b453f17"
dependencies:
"@gitlab-org/gitlab-svgs" "^1.23.0"
bootstrap-vue "^2.0.0-rc.11"
@@ -204,9 +204,9 @@
version "5.0.0"
resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.0.tgz#9ae2106efc443d7c1e26570aa8247828c9c80f11"
-"@vue/component-compiler-utils@^1.2.1":
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-1.2.1.tgz#3d543baa75cfe5dab96e29415b78366450156ef6"
+"@vue/component-compiler-utils@^2.0.0":
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-2.2.0.tgz#bbbb7ed38a9a8a7c93abe7ef2e54a90a04b631b4"
dependencies:
consolidate "^0.15.1"
hash-sum "^1.0.2"
@@ -214,7 +214,7 @@
merge-source-map "^1.1.0"
postcss "^6.0.20"
postcss-selector-parser "^3.1.1"
- prettier "^1.11.1"
+ prettier "1.13.7"
source-map "^0.5.6"
vue-template-es2015-compiler "^1.6.0"
@@ -5552,10 +5552,14 @@ prepend-http@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
-prettier@1.12.1, prettier@^1.11.1:
+prettier@1.12.1:
version "1.12.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.12.1.tgz#c1ad20e803e7749faf905a409d2367e06bbe7325"
+prettier@1.13.7:
+ version "1.13.7"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.7.tgz#850f3b8af784a49a6ea2d2eaa7ed1428a34b7281"
+
prismjs@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.6.0.tgz#118d95fb7a66dba2272e343b345f5236659db365"
@@ -7005,11 +7009,11 @@ vue-hot-reload-api@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.0.tgz#97976142405d13d8efae154749e88c4e358cf926"
-vue-loader@^15.2.4:
- version "15.2.4"
- resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.2.4.tgz#a7b923123d3cf87230a8ff54a1c16d31a6c5dbb4"
+vue-loader@^15.4.2:
+ version "15.4.2"
+ resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.4.2.tgz#812bb26e447dd3b84c485eb634190d914ce125e2"
dependencies:
- "@vue/component-compiler-utils" "^1.2.1"
+ "@vue/component-compiler-utils" "^2.0.0"
hash-sum "^1.0.2"
loader-utils "^1.1.0"
vue-hot-reload-api "^2.3.0"
@@ -7032,9 +7036,9 @@ vue-style-loader@^4.1.0:
hash-sum "^1.0.2"
loader-utils "^1.0.2"
-vue-template-compiler@^2.5.0, vue-template-compiler@^2.5.16:
- version "2.5.16"
- resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.16.tgz#93b48570e56c720cdf3f051cc15287c26fbd04cb"
+vue-template-compiler@^2.5.0, vue-template-compiler@^2.5.17:
+ version "2.5.17"
+ resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.17.tgz#52a4a078c327deb937482a509ae85c06f346c3cb"
dependencies:
de-indent "^1.0.2"
he "^1.1.0"
@@ -7047,9 +7051,9 @@ vue-virtual-scroll-list@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/vue-virtual-scroll-list/-/vue-virtual-scroll-list-1.2.5.tgz#bcbd010f7cdb035eba8958ebf807c6214d9a167a"
-vue@^2.5.16:
- version "2.5.16"
- resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.16.tgz#07edb75e8412aaeed871ebafa99f4672584a0085"
+vue@^2.5.16, vue@^2.5.17:
+ version "2.5.17"
+ resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.17.tgz#0f8789ad718be68ca1872629832ed533589c6ada"
vuex@^3.0.1:
version "3.0.1"