diff options
488 files changed, 3122 insertions, 2699 deletions
diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml index ac2a70dda0b..8628e1e0a14 100644 --- a/.gitlab/ci/qa.gitlab-ci.yml +++ b/.gitlab/ci/qa.gitlab-ci.yml @@ -1,7 +1,6 @@ .package-and-qa-base: image: ruby:2.6-alpine stage: qa - needs: ["build-qa-image", "gitlab:assets:compile pull-cache"] dependencies: [] variables: GIT_DEPTH: "1" @@ -11,24 +10,31 @@ - install_gitlab_gem - ./scripts/trigger-build omnibus only: - - branches@gitlab-org/gitlab-ce - - branches@gitlab-org/gitlab-ee - except: - - master + refs: + - branches@gitlab-org/gitlab-ce + - branches@gitlab-org/gitlab-ee package-and-qa-manual: - extends: - - .package-and-qa-base - - .except-docs-qa - when: manual + extends: .package-and-qa-base except: - - master - - /(^docs[\/-].+|.+-docs$)/ - - /(^qa[\/-].*|.*-qa$) + refs: + - master + when: manual + needs: ["build-qa-image", "gitlab:assets:compile pull-cache"] + +package-and-qa-manual:master: + extends: .package-and-qa-base + only: + refs: + - master + when: manual + needs: ["build-qa-image", "gitlab:assets:compile"] package-and-qa: extends: .package-and-qa-base - allow_failure: true only: - - /(^qa[\/-].*|.*-qa$)/@gitlab-org/gitlab-ce - - /(^qa[\/-].*|.*-qa$)/@gitlab-org/gitlab-ee + refs: + - /(^qa[\/-].*|.*-qa$)/@gitlab-org/gitlab-ce + - /(^qa[\/-].*|.*-qa$)/@gitlab-org/gitlab-ee + needs: ["build-qa-image", "gitlab:assets:compile pull-cache"] + allow_failure: true diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml index 3415f1b6ab4..c4a81a021a9 100644 --- a/.gitlab/ci/review.gitlab-ci.yml +++ b/.gitlab/ci/review.gitlab-ci.yml @@ -22,7 +22,9 @@ - source scripts/utils.sh .review-docker: - extends: .review-base + extends: + - .default-tags + - .default-retry image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine services: - docker:19.03.0-dind @@ -36,7 +38,13 @@ QA_IMAGE: "${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab/${CI_PROJECT_NAME}-qa:${CI_COMMIT_REF_SLUG}" build-qa-image: - extends: .review-docker + extends: + - .review-docker + - .except-docs + only: + refs: + - branches@gitlab-org/gitlab-ce + - branches@gitlab-org/gitlab-ee stage: test script: - time docker build --cache-from ${LATEST_QA_IMAGE} --tag ${QA_IMAGE} --file ./qa/Dockerfile ./ @@ -124,7 +132,9 @@ review-stop: artifacts: {} .review-qa-base: - extends: .review-docker + extends: + - .review-docker + - .review-only retry: 2 stage: qa variables: diff --git a/.rubocop.yml b/.rubocop.yml index a20924c21b7..f24cbb6ce92 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -264,8 +264,6 @@ RSpec/EnvAssignment: Exclude: - 'spec/**/fast_spec_helper.rb' - 'ee/spec/**/fast_spec_helper.rb' - - 'spec/**/rails_helper.rb' - - 'ee/spec/**/rails_helper.rb' - 'spec/**/spec_helper.rb' - 'ee/spec/**/spec_helper.rb' RSpec/BeSuccessMatcher: diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 3898206e3b5..be147d72f71 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -570,11 +570,6 @@ Style/EmptyMethod: Style/Encoding: Enabled: false -# Offense count: 2 -Style/EvalWithLocation: - Exclude: - - 'app/models/service.rb' - # Offense count: 203 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. diff --git a/CHANGELOG.md b/CHANGELOG.md index c4d238b2999..a432b091c7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 12.2.4 + +### Fixed (7 changes) + +- Add syntax highlighting for line expansion. !31821 +- Fix issuable sidebar icon on notification disabled. !32134 +- Upgrade Mermaid to v8.2.4. !32186 +- Fix Piwik not working. !32234 +- Fix snippets API not working with visibility level. !32286 +- Fix upload URLs in Markdown for users without access to project repository. !32448 +- Update Mermaid to v8.2.6. !32502 + +### Performance (1 change) + +- Fix N+1 Gitaly calls in /api/v4/projects/:id/issues. !32171 + + ## 12.2.3 ### Security (22 changes) @@ -171,7 +171,7 @@ gem 'acts-as-taggable-on', '~> 6.0' gem 'sidekiq', '~> 5.2.7' gem 'sidekiq-cron', '~> 1.0' gem 'redis-namespace', '~> 1.6.0' -gem 'gitlab-sidekiq-fetcher', '0.5.1', require: 'sidekiq-reliable-fetch' +gem 'gitlab-sidekiq-fetcher', '0.5.2', require: 'sidekiq-reliable-fetch' # Cron Parser gem 'fugit', '~> 1.2.1' @@ -216,6 +216,7 @@ gem 'hipchat', '~> 1.5.0' # Jira integration gem 'jira-ruby', '~> 1.7' +gem 'atlassian-jwt', '~> 0.2.0' # Flowdock integration gem 'flowdock', '~> 0.7' diff --git a/Gemfile.lock b/Gemfile.lock index 0803cf7f752..f0b3d722326 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -321,7 +321,7 @@ GEM gitlab-markup (1.7.0) gitlab-peek (0.0.1) railties (>= 4.0.0) - gitlab-sidekiq-fetcher (0.5.1) + gitlab-sidekiq-fetcher (0.5.2) sidekiq (~> 5) gitlab-styles (2.8.0) rubocop (~> 0.69.0) @@ -1028,6 +1028,7 @@ DEPENDENCIES asciidoctor (~> 2.0.10) asciidoctor-include-ext (~> 0.3.1) asciidoctor-plantuml (= 0.0.9) + atlassian-jwt (~> 0.2.0) attr_encrypted (~> 3.1.0) awesome_print babosa (~> 1.0.2) @@ -1097,7 +1098,7 @@ DEPENDENCIES gitlab-labkit (~> 0.5) gitlab-markup (~> 1.7.0) gitlab-peek (~> 0.0.1) - gitlab-sidekiq-fetcher (= 0.5.1) + gitlab-sidekiq-fetcher (= 0.5.2) gitlab-styles (~> 2.7) gitlab_omniauth-ldap (~> 2.1.1) gon (~> 6.2) diff --git a/app/assets/javascripts/boards/models/issue.js b/app/assets/javascripts/boards/models/issue.js index 9069b35db9a..086340105b7 100644 --- a/app/assets/javascripts/boards/models/issue.js +++ b/app/assets/javascripts/boards/models/issue.js @@ -3,7 +3,7 @@ /* global ListMilestone */ /* global ListAssignee */ -import Vue from 'vue'; +import axios from '~/lib/utils/axios_utils'; import './label'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import IssueProject from './project'; @@ -133,7 +133,7 @@ class ListIssue { } const projectPath = this.project ? this.project.path : ''; - return Vue.http.patch(`${this.path}.json`, data).then(({ body = {} } = {}) => { + return axios.patch(`${this.path}.json`, data).then(({ data: body = {} } = {}) => { /** * Since post implementation of Scoped labels, server can reject * same key-ed labels. To keep the UI and server Model consistent, diff --git a/app/assets/javascripts/branches/divergence_graph.js b/app/assets/javascripts/branches/divergence_graph.js index 7dbaf984acf..303735a1807 100644 --- a/app/assets/javascripts/branches/divergence_graph.js +++ b/app/assets/javascripts/branches/divergence_graph.js @@ -25,6 +25,11 @@ export default endpoint => { const names = [...document.querySelectorAll('.js-branch-item')].map( ({ dataset }) => dataset.name, ); + + if (names.length === 0) { + return true; + } + return axios .get(endpoint, { params: { names }, diff --git a/app/assets/javascripts/flash.js b/app/assets/javascripts/flash.js index c2397842125..660f0f0ba3e 100644 --- a/app/assets/javascripts/flash.js +++ b/app/assets/javascripts/flash.js @@ -1,4 +1,5 @@ import _ from 'underscore'; +import { spriteIcon } from './lib/utils/common_utils'; const hideFlash = (flashEl, fadeTransition = true) => { if (fadeTransition) { @@ -35,16 +36,11 @@ const createAction = config => ` </a> `; -const createFlashEl = (message, type, isFixedLayout = false) => ` - <div - class="flash-${type}" - > - <div - class="flash-text ${ - isFixedLayout ? 'container-fluid container-limited limit-container-width' : '' - }" - > +const createFlashEl = (message, type) => ` + <div class="flash-content flash-${type} rounded"> + <div class="flash-text"> ${_.escape(message)} + ${spriteIcon('close', 'close-icon')} </div> </div> `; @@ -76,15 +72,10 @@ const createFlash = function createFlash( addBodyClass = false, ) { const flashContainer = parent.querySelector('.flash-container'); - const navigation = parent.querySelector('.content'); if (!flashContainer) return null; - const isFixedLayout = navigation - ? navigation.parentNode.classList.contains('container-limited') - : true; - - flashContainer.innerHTML = createFlashEl(message, type, isFixedLayout); + flashContainer.innerHTML = createFlashEl(message, type); const flashEl = flashContainer.querySelector(`.flash-${type}`); removeFlashClickListener(flashEl, fadeTransition); diff --git a/app/assets/javascripts/jobs/store/utils.js b/app/assets/javascripts/jobs/store/utils.js new file mode 100644 index 00000000000..de7de92ed2e --- /dev/null +++ b/app/assets/javascripts/jobs/store/utils.js @@ -0,0 +1,40 @@ +/** + * Parses the job log content into a structure usable by the template + * + * For collaspible lines (section_header = true): + * - creates a new array to hold the lines that are collpasible, + * - adds a isClosed property to handle toggle + * - adds a isHeader property to handle template logic + * For each line: + * - adds the index as lineNumber + * + * @param {Array} lines + * @returns {Array} + */ +export default (lines = []) => + lines.reduce((acc, line, index) => { + if (line.section_header) { + acc.push({ + isClosed: true, + isHeader: true, + line: { + ...line, + lineNumber: index, + }, + + lines: [], + }); + } else if (acc.length && acc[acc.length - 1].isHeader) { + acc[acc.length - 1].lines.push({ + ...line, + lineNumber: index, + }); + } else { + acc.push({ + ...line, + lineNumber: index, + }); + } + + return acc; + }, []); diff --git a/app/assets/javascripts/monitoring/components/charts/area.vue b/app/assets/javascripts/monitoring/components/charts/area.vue deleted file mode 100644 index cac10474d06..00000000000 --- a/app/assets/javascripts/monitoring/components/charts/area.vue +++ /dev/null @@ -1,304 +0,0 @@ -<script> -import { __ } from '~/locale'; -import { GlLink } from '@gitlab/ui'; -import { GlAreaChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts'; -import dateFormat from 'dateformat'; -import { debounceByAnimationFrame, roundOffFloat } from '~/lib/utils/common_utils'; -import { getSvgIconPathContent } from '~/lib/utils/icon_utils'; -import Icon from '~/vue_shared/components/icon.vue'; -import { chartHeight, graphTypes, lineTypes } from '../../constants'; -import { makeDataSeries } from '~/helpers/monitor_helper'; -import { graphDataValidatorForValues } from '../../utils'; - -let debouncedResize; - -// TODO: Remove this component in favor of the more general time_series.vue -// Please port all changes here to time_series.vue as well. - -export default { - components: { - GlAreaChart, - GlChartSeriesLabel, - GlLink, - Icon, - }, - inheritAttrs: false, - props: { - graphData: { - type: Object, - required: true, - validator: graphDataValidatorForValues.bind(null, false), - }, - containerWidth: { - type: Number, - required: true, - }, - deploymentData: { - type: Array, - required: false, - default: () => [], - }, - projectPath: { - type: String, - required: false, - default: () => '', - }, - showBorder: { - type: Boolean, - required: false, - default: () => false, - }, - singleEmbed: { - type: Boolean, - required: false, - default: false, - }, - thresholds: { - type: Array, - required: false, - default: () => [], - }, - }, - data() { - return { - tooltip: { - title: '', - content: [], - commitUrl: '', - isDeployment: false, - sha: '', - }, - width: 0, - height: chartHeight, - svgs: {}, - primaryColor: null, - }; - }, - computed: { - chartData() { - // Transforms & supplements query data to render appropriate labels & styles - // Input: [{ queryAttributes1 }, { queryAttributes2 }] - // Output: [{ seriesAttributes1 }, { seriesAttributes2 }] - return this.graphData.queries.reduce((acc, query) => { - const { appearance } = query; - const lineType = - appearance && appearance.line && appearance.line.type - ? appearance.line.type - : lineTypes.default; - const lineWidth = - appearance && appearance.line && appearance.line.width - ? appearance.line.width - : undefined; - - const series = makeDataSeries(query.result, { - name: this.formatLegendLabel(query), - lineStyle: { - type: lineType, - width: lineWidth, - }, - areaStyle: { - opacity: - appearance && appearance.area && typeof appearance.area.opacity === 'number' - ? appearance.area.opacity - : undefined, - }, - }); - - return acc.concat(series); - }, []); - }, - chartOptions() { - return { - xAxis: { - name: __('Time'), - type: 'time', - axisLabel: { - formatter: date => dateFormat(date, 'h:MM TT'), - }, - axisPointer: { - snap: true, - }, - }, - yAxis: { - name: this.yAxisLabel, - axisLabel: { - formatter: num => roundOffFloat(num, 3).toString(), - }, - }, - series: this.scatterSeries, - dataZoom: [this.dataZoomConfig], - }; - }, - dataZoomConfig() { - const handleIcon = this.svgs['scroll-handle']; - - return handleIcon ? { handleIcon } : {}; - }, - earliestDatapoint() { - return this.chartData.reduce((acc, series) => { - const { data } = series; - const { length } = data; - if (!length) { - return acc; - } - - const [first] = data[0]; - const [last] = data[length - 1]; - const seriesEarliest = first < last ? first : last; - - return seriesEarliest < acc || acc === null ? seriesEarliest : acc; - }, null); - }, - isMultiSeries() { - return this.tooltip.content.length > 1; - }, - recentDeployments() { - return this.deploymentData.reduce((acc, deployment) => { - if (deployment.created_at >= this.earliestDatapoint) { - acc.push({ - id: deployment.id, - createdAt: deployment.created_at, - sha: deployment.sha, - commitUrl: `${this.projectPath}/commit/${deployment.sha}`, - tag: deployment.tag, - tagUrl: deployment.tag ? `${this.tagsPath}/${deployment.ref.name}` : null, - ref: deployment.ref.name, - showDeploymentFlag: false, - }); - } - - return acc; - }, []); - }, - scatterSeries() { - return { - type: graphTypes.deploymentData, - data: this.recentDeployments.map(deployment => [deployment.createdAt, 0]), - symbol: this.svgs.rocket, - symbolSize: 14, - itemStyle: { - color: this.primaryColor, - }, - }; - }, - yAxisLabel() { - return `${this.graphData.y_label}`; - }, - }, - watch: { - containerWidth: 'onResize', - }, - beforeDestroy() { - window.removeEventListener('resize', debouncedResize); - }, - created() { - debouncedResize = debounceByAnimationFrame(this.onResize); - window.addEventListener('resize', debouncedResize); - this.setSvg('rocket'); - this.setSvg('scroll-handle'); - }, - methods: { - formatLegendLabel(query) { - return `${query.label}`; - }, - formatTooltipText(params) { - this.tooltip.title = dateFormat(params.value, 'dd mmm yyyy, h:MMTT'); - this.tooltip.content = []; - params.seriesData.forEach(seriesData => { - this.tooltip.isDeployment = seriesData.componentSubType === graphTypes.deploymentData; - if (this.tooltip.isDeployment) { - const [deploy] = this.recentDeployments.filter( - deployment => deployment.createdAt === seriesData.value[0], - ); - this.tooltip.sha = deploy.sha.substring(0, 8); - this.tooltip.commitUrl = deploy.commitUrl; - } else { - const { seriesName, color } = seriesData; - // seriesData.value contains the chart's [x, y] value pair - // seriesData.value[1] is threfore the chart y value - const value = seriesData.value[1].toFixed(3); - - this.tooltip.content.push({ - name: seriesName, - value, - color, - }); - } - }); - }, - setSvg(name) { - getSvgIconPathContent(name) - .then(path => { - if (path) { - this.$set(this.svgs, name, `path://${path}`); - } - }) - .catch(() => {}); - }, - onChartUpdated(chart) { - [this.primaryColor] = chart.getOption().color; - }, - onResize() { - if (!this.$refs.areaChart) return; - const { width } = this.$refs.areaChart.$el.getBoundingClientRect(); - this.width = width; - }, - }, -}; -</script> - -<template> - <div - class="prometheus-graph col-12" - :class="[showBorder ? 'p-2' : 'p-0', { 'col-lg-6': !singleEmbed }]" - > - <div :class="{ 'prometheus-graph-embed w-100 p-3': showBorder }"> - <div class="prometheus-graph-header"> - <h5 ref="graphTitle" class="prometheus-graph-title">{{ graphData.title }}</h5> - <div ref="graphWidgets" class="prometheus-graph-widgets"><slot></slot></div> - </div> - <gl-area-chart - ref="areaChart" - v-bind="$attrs" - :data="chartData" - :option="chartOptions" - :format-tooltip-text="formatTooltipText" - :thresholds="thresholds" - :width="width" - :height="height" - @updated="onChartUpdated" - > - <template v-if="tooltip.isDeployment"> - <template slot="tooltipTitle"> - {{ __('Deployed') }} - </template> - <div slot="tooltipContent" class="d-flex align-items-center"> - <icon name="commit" class="mr-2" /> - <gl-link :href="tooltip.commitUrl">{{ tooltip.sha }}</gl-link> - </div> - </template> - <template v-else> - <template slot="tooltipTitle"> - <div class="text-nowrap"> - {{ tooltip.title }} - </div> - </template> - <template slot="tooltipContent"> - <div - v-for="(content, key) in tooltip.content" - :key="key" - class="d-flex justify-content-between" - > - <gl-chart-series-label :color="isMultiSeries ? content.color : ''"> - {{ content.name }} - </gl-chart-series-label> - <div class="prepend-left-32"> - {{ content.value }} - </div> - </div> - </template> - </template> - </gl-area-chart> - </div> - </div> -</template> diff --git a/app/assets/javascripts/pages/profiles/two_factor_auths/index.js b/app/assets/javascripts/pages/profiles/two_factor_auths/index.js index 820f0f7f12d..0d377eb9c68 100644 --- a/app/assets/javascripts/pages/profiles/two_factor_auths/index.js +++ b/app/assets/javascripts/pages/profiles/two_factor_auths/index.js @@ -5,9 +5,10 @@ import { parseBoolean } from '~/lib/utils/common_utils'; document.addEventListener('DOMContentLoaded', () => { const twoFactorNode = document.querySelector('.js-two-factor-auth'); const skippable = parseBoolean(twoFactorNode.dataset.twoFactorSkippable); + if (skippable) { const button = `<a class="btn btn-sm btn-warning float-right" data-method="patch" href="${twoFactorNode.dataset.two_factor_skip_url}">Configure it later</a>`; - const flashAlert = document.querySelector('.flash-alert .container-fluid'); + const flashAlert = document.querySelector('.flash-alert'); if (flashAlert) flashAlert.insertAdjacentHTML('beforeend', button); } diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue index c6cc04a139f..ce592720531 100644 --- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue +++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue @@ -67,18 +67,14 @@ export default { saveAssignees() { this.loading = true; - function setLoadingFalse() { - this.loading = false; - } - this.mediator .saveAssignees(this.field) - .then(setLoadingFalse.bind(this)) .then(() => { + this.loading = false; refreshUserMergeRequestCounts(); }) .catch(() => { - setLoadingFalse(); + this.loading = false; return new Flash(__('Error occurred when saving assignees')); }); }, diff --git a/app/assets/javascripts/sidebar/services/sidebar_service.js b/app/assets/javascripts/sidebar/services/sidebar_service.js index cbe20f761ff..feb08e3acaf 100644 --- a/app/assets/javascripts/sidebar/services/sidebar_service.js +++ b/app/assets/javascripts/sidebar/services/sidebar_service.js @@ -1,7 +1,4 @@ -import Vue from 'vue'; -import VueResource from 'vue-resource'; - -Vue.use(VueResource); +import axios from '~/lib/utils/axios_utils'; export default class SidebarService { constructor(endpointMap) { @@ -18,23 +15,15 @@ export default class SidebarService { } get() { - return Vue.http.get(this.endpoint); + return axios.get(this.endpoint); } update(key, data) { - return Vue.http.put( - this.endpoint, - { - [key]: data, - }, - { - emulateJSON: true, - }, - ); + return axios.put(this.endpoint, { [key]: data }); } getProjectsAutocomplete(searchTerm) { - return Vue.http.get(this.projectsAutocompleteEndpoint, { + return axios.get(this.projectsAutocompleteEndpoint, { params: { search: searchTerm, }, @@ -42,11 +31,11 @@ export default class SidebarService { } toggleSubscription() { - return Vue.http.post(this.toggleSubscriptionEndpoint); + return axios.post(this.toggleSubscriptionEndpoint); } moveIssue(moveToProjectId) { - return Vue.http.post(this.moveIssueEndpoint, { + return axios.post(this.moveIssueEndpoint, { move_to_project_id: moveToProjectId, }); } diff --git a/app/assets/javascripts/sidebar/sidebar_mediator.js b/app/assets/javascripts/sidebar/sidebar_mediator.js index 643fe6c00b6..4a7000cbbda 100644 --- a/app/assets/javascripts/sidebar/sidebar_mediator.js +++ b/app/assets/javascripts/sidebar/sidebar_mediator.js @@ -32,7 +32,10 @@ export default class SidebarMediator { // If there are no ids, that means we have to unassign (which is id = 0) // And it only accepts an array, hence [0] - return this.service.update(field, selected.length === 0 ? [0] : selected); + const assignees = selected.length === 0 ? [0] : selected; + const data = { assignee_ids: assignees }; + + return this.service.update(field, data); } setMoveToProjectId(projectId) { @@ -42,8 +45,7 @@ export default class SidebarMediator { fetch() { return this.service .get() - .then(response => response.json()) - .then(data => { + .then(({ data }) => { this.processFetchedData(data); }) .catch(() => new Flash(__('Error occurred when fetching sidebar data'))); @@ -71,23 +73,17 @@ export default class SidebarMediator { } fetchAutocompleteProjects(searchTerm) { - return this.service - .getProjectsAutocomplete(searchTerm) - .then(response => response.json()) - .then(data => { - this.store.setAutocompleteProjects(data); - return this.store.autocompleteProjects; - }); + return this.service.getProjectsAutocomplete(searchTerm).then(({ data }) => { + this.store.setAutocompleteProjects(data); + return this.store.autocompleteProjects; + }); } moveIssue() { - return this.service - .moveIssue(this.store.moveToProjectId) - .then(response => response.json()) - .then(data => { - if (window.location.pathname !== data.web_url) { - visitUrl(data.web_url); - } - }); + return this.service.moveIssue(this.store.moveToProjectId).then(({ data }) => { + if (window.location.pathname !== data.web_url) { + visitUrl(data.web_url); + } + }); } } diff --git a/app/assets/stylesheets/framework/flash.scss b/app/assets/stylesheets/framework/flash.scss index 96f6d02a68f..af05d069f97 100644 --- a/app/assets/stylesheets/framework/flash.scss +++ b/app/assets/stylesheets/framework/flash.scss @@ -1,3 +1,5 @@ +$notification-box-shadow-color: rgba(0, 0, 0, 0.25); + .flash-container { cursor: pointer; margin: 0; @@ -6,12 +8,32 @@ position: relative; z-index: 1; + &.sticky { + position: sticky; + position: -webkit-sticky; + top: $flash-container-top; + z-index: 200; + + .flash-content { + box-shadow: 0 2px 4px 0 $notification-box-shadow-color; + } + } + + .close-icon { + width: 16px; + height: 16px; + position: absolute; + right: $gl-padding; + top: $gl-padding; + } + .flash-notice, .flash-alert, .flash-success, .flash-warning { border-radius: $border-radius-default; color: $white-light; + padding-right: $gl-padding * 2; .container-fluid, .container-fluid.container-limited { @@ -97,3 +119,28 @@ } } } + +.gl-browser-ie .flash-container { + position: fixed; + max-width: $limited-layout-width; + left: 50%; + + .flash-alert { + position: relative; + left: -50%; + } +} + +.with-system-header .flash-container { + top: $flash-container-top + $system-header-height; +} + +.with-performance-bar { + .flash-container { + top: $flash-container-top + $performance-bar-height; + } + + &.with-system-header .flash-container { + top: $flash-container-top + $performance-bar-height + $system-header-height; + } +} diff --git a/app/assets/stylesheets/framework/layout.scss b/app/assets/stylesheets/framework/layout.scss index 97cb9d90ff0..7205324e86f 100644 --- a/app/assets/stylesheets/framework/layout.scss +++ b/app/assets/stylesheets/framework/layout.scss @@ -29,6 +29,15 @@ body { } } +.container-fluid { + &.limit-container-width { + .flash-container.sticky { + max-width: $limited-layout-width; + margin: 0 auto; + } + } +} + .content-wrapper { margin-top: $header-height; padding-bottom: 100px; diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 7a3fd2adfbb..15a779dde1d 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -377,6 +377,7 @@ $performance-bar-height: 35px; $system-header-height: 16px; $system-footer-height: $system-header-height; $flash-height: 52px; +$flash-container-top: 48px; $context-header-height: 60px; $breadcrumb-min-height: 48px; $home-panel-title-row-height: 64px; diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb index 6317fa7c8d1..32a36da56fe 100644 --- a/app/controllers/admin/groups_controller.rb +++ b/app/controllers/admin/groups_controller.rb @@ -14,7 +14,11 @@ class Admin::GroupsController < Admin::ApplicationController # rubocop: disable CodeReuse/ActiveRecord def show - @group = Group.with_statistics.joins(:route).group('routes.path').find_by_full_path(params[:id]) + # Group.with_statistics doesn't behave nicely when including other relations. + # Group.find_by_full_path includes the routes relation to avoid a common N+1 + # (at the expense of this action: there are two queries here to find and retrieve + # the Group with statistics). + @group = Group.with_statistics.find(group&.id) @members = present_members( @group.members.order("access_level DESC").page(params[:members_page])) @requesters = present_members( diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb index 04db1980b99..8b93ead0ee6 100644 --- a/app/mailers/emails/notes.rb +++ b/app/mailers/emails/notes.rb @@ -2,44 +2,44 @@ module Emails module Notes - def note_commit_email(recipient_id, note_id) + def note_commit_email(recipient_id, note_id, reason = nil) setup_note_mail(note_id, recipient_id) @commit = @note.noteable @target_url = project_commit_url(*note_target_url_options) - mail_answer_note_thread(@commit, @note, note_thread_options(recipient_id)) + mail_answer_note_thread(@commit, @note, note_thread_options(recipient_id, reason)) end - def note_issue_email(recipient_id, note_id) + def note_issue_email(recipient_id, note_id, reason = nil) setup_note_mail(note_id, recipient_id) @issue = @note.noteable @target_url = project_issue_url(*note_target_url_options) - mail_answer_note_thread(@issue, @note, note_thread_options(recipient_id)) + mail_answer_note_thread(@issue, @note, note_thread_options(recipient_id, reason)) end - def note_merge_request_email(recipient_id, note_id) + def note_merge_request_email(recipient_id, note_id, reason = nil) setup_note_mail(note_id, recipient_id) @merge_request = @note.noteable @target_url = project_merge_request_url(*note_target_url_options) - mail_answer_note_thread(@merge_request, @note, note_thread_options(recipient_id)) + mail_answer_note_thread(@merge_request, @note, note_thread_options(recipient_id, reason)) end - def note_project_snippet_email(recipient_id, note_id) + def note_project_snippet_email(recipient_id, note_id, reason = nil) setup_note_mail(note_id, recipient_id) @snippet = @note.noteable @target_url = project_snippet_url(*note_target_url_options) - mail_answer_note_thread(@snippet, @note, note_thread_options(recipient_id)) + mail_answer_note_thread(@snippet, @note, note_thread_options(recipient_id, reason)) end - def note_personal_snippet_email(recipient_id, note_id) + def note_personal_snippet_email(recipient_id, note_id, reason = nil) setup_note_mail(note_id, recipient_id) @snippet = @note.noteable @target_url = snippet_url(@note.noteable) - mail_answer_note_thread(@snippet, @note, note_thread_options(recipient_id)) + mail_answer_note_thread(@snippet, @note, note_thread_options(recipient_id, reason)) end private @@ -48,11 +48,12 @@ module Emails [@project || @group, @note.noteable, anchor: "note_#{@note.id}"] end - def note_thread_options(recipient_id) + def note_thread_options(recipient_id, reason) { from: sender(@note.author_id), to: recipient(recipient_id, @project&.group || @group), - subject: subject("#{@note.noteable.title} (#{@note.noteable.reference_link_text})") + subject: subject("#{@note.noteable.title} (#{@note.noteable.reference_link_text})"), + 'X-GitLab-NotificationReason' => reason } end diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 64e372878e6..2b6f10ef79f 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -460,8 +460,8 @@ module Ci canceled? && auto_canceled_by_id? end - def cancel_running - retry_optimistic_lock(cancelable_statuses) do |cancelable| + def cancel_running(retries: nil) + retry_optimistic_lock(cancelable_statuses, retries) do |cancelable| cancelable.find_each do |job| yield(job) if block_given? job.cancel @@ -469,10 +469,10 @@ module Ci end end - def auto_cancel_running(pipeline) + def auto_cancel_running(pipeline, retries: nil) update(auto_canceled_by: pipeline) - cancel_running do |job| + cancel_running(retries: retries) do |job| job.auto_canceled_by = pipeline end end @@ -670,6 +670,7 @@ module Ci variables.append(key: 'CI_COMMIT_REF_PROTECTED', value: (!!protected_ref?).to_s) if merge_request_event? && merge_request + variables.append(key: 'CI_MERGE_REQUEST_EVENT_TYPE', value: merge_request_event_type.to_s) variables.append(key: 'CI_MERGE_REQUEST_SOURCE_BRANCH_SHA', value: source_sha.to_s) variables.append(key: 'CI_MERGE_REQUEST_TARGET_BRANCH_SHA', value: target_sha.to_s) variables.concat(merge_request.predefined_variables) @@ -772,10 +773,18 @@ module Ci triggered_by_merge_request? && target_sha.present? end + def merge_train_pipeline? + merge_request_pipeline? && merge_train_ref? + end + def merge_request_ref? MergeRequest.merge_request_ref?(ref) end + def merge_train_ref? + MergeRequest.merge_train_ref?(ref) + end + def matches_sha_or_source_sha?(sha) self.sha == sha || self.source_sha == sha end @@ -804,6 +813,20 @@ module Ci errors ? errors.full_messages.to_sentence : "" end + def merge_request_event_type + return unless merge_request_event? + + strong_memoize(:merge_request_event_type) do + if detached_merge_request_pipeline? + :detached + elsif merge_request_pipeline? + :merged_result + elsif merge_train_pipeline? + :merge_train + end + end + end + private def ci_yaml_from_repo diff --git a/app/models/concerns/routable.rb b/app/models/concerns/routable.rb index 3a486632800..07d22641a0a 100644 --- a/app/models/concerns/routable.rb +++ b/app/models/concerns/routable.rb @@ -38,7 +38,7 @@ module Routable if Feature.enabled?(:routable_two_step_lookup) # Case sensitive match first (it's cheaper and the usual case) # If we didn't have an exact match, we perform a case insensitive search - found = joins(:route).find_by(routes: { path: path }) || where_full_path_in([path]).take + found = includes(:route).find_by(routes: { path: path }) || where_full_path_in([path]).take else order_sql = Arel.sql("(CASE WHEN routes.path = #{connection.quote(path)} THEN 0 ELSE 1 END)") found = where_full_path_in([path]).reorder(order_sql).take @@ -67,7 +67,7 @@ module Routable "(LOWER(routes.path) = LOWER(#{connection.quote(path)}))" end - joins(:route).where(wheres.join(' OR ')) + includes(:route).where(wheres.join(' OR ')).references(:routes) end # Temporary instrumentation of method calls diff --git a/app/models/member.rb b/app/models/member.rb index dbae1076670..6457fe9ef0c 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -399,7 +399,7 @@ class Member < ApplicationRecord end def post_update_hook - # override in sub class + system_hook_service.execute_hooks_for(self, :update) end def post_destroy_hook diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index bfd636fa62a..28e450f9b30 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -1142,6 +1142,10 @@ class MergeRequest < ApplicationRecord ref.start_with?("refs/#{Repository::REF_MERGE_REQUEST}/") end + def self.merge_train_ref?(ref) + %r{\Arefs/#{Repository::REF_MERGE_REQUEST}/\d+/train\z}.match?(ref) + end + def in_locked_state begin lock_mr diff --git a/app/models/milestone.rb b/app/models/milestone.rb index 2ad2838111e..101e963ea29 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -24,6 +24,12 @@ class Milestone < ApplicationRecord belongs_to :project belongs_to :group + # A one-to-one relationship is set up here as part of a MVC: https://gitlab.com/gitlab-org/gitlab-ce/issues/62402 + # However, on the long term, we will want a many-to-many relationship between Release and Milestone. + # The "has_one through" allows us today to set up this one-to-one relationship while setting up the architecture for the long-term (ie intermediate table). + has_one :milestone_release + has_one :release, through: :milestone_release + has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.milestones&.maximum(:iid) } has_internal_id :iid, scope: :group, init: ->(s) { s&.group&.milestones&.maximum(:iid) } @@ -59,6 +65,7 @@ class Milestone < ApplicationRecord validate :milestone_type_check validate :start_date_should_be_less_than_due_date, if: proc { |m| m.start_date.present? && m.due_date.present? } validate :dates_within_4_digits + validates_associated :milestone_release, message: -> (_, obj) { obj[:value].errors.full_messages.join(",") } strip_attributes :title diff --git a/app/models/milestone_release.rb b/app/models/milestone_release.rb new file mode 100644 index 00000000000..c8743a8cad8 --- /dev/null +++ b/app/models/milestone_release.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class MilestoneRelease < ApplicationRecord + belongs_to :milestone + belongs_to :release + + validates :milestone_id, uniqueness: { scope: [:release_id] } + validate :same_project_between_milestone_and_release + + private + + def same_project_between_milestone_and_release + return if milestone&.project_id == release&.project_id + + errors.add(:base, 'does not have the same project as the milestone') + end +end diff --git a/app/models/project_services/chat_notification_service.rb b/app/models/project_services/chat_notification_service.rb index 7c9ecc6b821..cb75c89136e 100644 --- a/app/models/project_services/chat_notification_service.rb +++ b/app/models/project_services/chat_notification_service.rb @@ -5,17 +5,25 @@ class ChatNotificationService < Service include ChatMessage + SUPPORTED_EVENTS = %w[ + push issue confidential_issue merge_request note confidential_note + tag_push pipeline wiki_page deployment + ].freeze + + EVENT_CHANNEL = proc { |event| "#{event}_channel" } + default_value_for :category, 'chat' prop_accessor :webhook, :username, :channel + + # Custom serialized properties initialization + prop_accessor(*SUPPORTED_EVENTS.map { |event| EVENT_CHANNEL[event] }) + boolean_accessor :notify_only_broken_pipelines, :notify_only_default_branch validates :webhook, presence: true, public_url: true, if: :activated? def initialize_properties - # Custom serialized properties initialization - self.supported_events.each { |event| self.class.prop_accessor(event_channel_name(event)) } - if properties.nil? self.properties = {} self.notify_only_broken_pipelines = true @@ -32,8 +40,7 @@ class ChatNotificationService < Service end def self.supported_events - %w[push issue confidential_issue merge_request note confidential_note tag_push - pipeline wiki_page deployment] + SUPPORTED_EVENTS end def fields @@ -139,7 +146,7 @@ class ChatNotificationService < Service end def event_channel_name(event) - "#{event}_channel" + EVENT_CHANNEL[event] end def project_name diff --git a/app/models/release.rb b/app/models/release.rb index 459a7c29ad0..b2e65974aa0 100644 --- a/app/models/release.rb +++ b/app/models/release.rb @@ -12,6 +12,12 @@ class Release < ApplicationRecord has_many :links, class_name: 'Releases::Link' + # A one-to-one relationship is set up here as part of a MVC: https://gitlab.com/gitlab-org/gitlab-ce/issues/62402 + # However, on the long term, we will want a many-to-many relationship between Release and Milestone. + # The "has_one through" allows us today to set up this one-to-one relationship while setting up the architecture for the long-term (ie intermediate table). + has_one :milestone_release + has_one :milestone, through: :milestone_release + default_value_for :released_at, allows_nil: false do Time.zone.now end @@ -20,6 +26,7 @@ class Release < ApplicationRecord validates :description, :project, :tag, presence: true validates :name, presence: true, on: :create + validates_associated :milestone_release, message: -> (_, obj) { obj[:value].errors.full_messages.join(",") } scope :sorted, -> { order(released_at: :desc) } diff --git a/app/models/repository.rb b/app/models/repository.rb index 7882b2b3036..5cb4b56a114 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -456,6 +456,10 @@ class Repository def after_import expire_content_cache + # This call is stubbed in tests due to being an expensive operation + # It can be reenabled for specific tests via: + # + # allow(DetectRepositoryLanguagesWorker).to receive(:perform_async).and_call_original DetectRepositoryLanguagesWorker.perform_async(project.id) end diff --git a/app/models/service.rb b/app/models/service.rb index f6d8fb1fb46..431c5881460 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -174,7 +174,7 @@ class Service < ApplicationRecord # Also keep track of updated properties in a similar way as ActiveModel::Dirty def self.prop_accessor(*args) args.each do |arg| - class_eval %{ + class_eval <<~RUBY, __FILE__, __LINE__ + 1 unless method_defined?(arg) def #{arg} properties['#{arg}'] @@ -198,7 +198,7 @@ class Service < ApplicationRecord def #{arg}_was updated_properties['#{arg}'] end - } + RUBY end end @@ -209,12 +209,12 @@ class Service < ApplicationRecord self.prop_accessor(*args) args.each do |arg| - class_eval %{ + class_eval <<~RUBY, __FILE__, __LINE__ + 1 def #{arg}? # '!!' is used because nil or empty string is converted to nil !!ActiveRecord::Type::Boolean.new.cast(#{arg}) end - } + RUBY end end diff --git a/app/presenters/blob_presenter.rb b/app/presenters/blob_presenter.rb index 2cf3278d240..3a71d2b87f3 100644 --- a/app/presenters/blob_presenter.rb +++ b/app/presenters/blob_presenter.rb @@ -3,12 +3,12 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated presents :blob - def highlight(plain: nil) + def highlight(to: nil, plain: nil) load_all_blob_data Gitlab::Highlight.highlight( blob.path, - blob.data, + limited_blob_data(to: to), language: blob.language_from_gitattributes, plain: plain ) @@ -23,4 +23,18 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated def load_all_blob_data blob.load_all_data! if blob.respond_to?(:load_all_data!) end + + def limited_blob_data(to: nil) + return blob.data if to.blank? + + # Even though we don't need all the lines at the start of the file (e.g + # viewing the middle part of a file), they still need to be highlighted + # to ensure that the succeeding lines can be formatted correctly (e.g. + # multi-line comments). + all_lines[0..to - 1].join + end + + def all_lines + @all_lines ||= blob.data.lines + end end diff --git a/app/presenters/blobs/unfold_presenter.rb b/app/presenters/blobs/unfold_presenter.rb index a256dd05a4d..487c6fe0757 100644 --- a/app/presenters/blobs/unfold_presenter.rb +++ b/app/presenters/blobs/unfold_presenter.rb @@ -26,8 +26,6 @@ module Blobs # so we can accurately show the rest of the diff when unfolding. load_all_blob_data - @all_lines = blob.data.lines - handle_full_or_end! end @@ -46,7 +44,7 @@ module Blobs def lines strong_memoize(:lines) do - limit(highlight.lines).map(&:html_safe) + limit(highlight(to: to).lines).map(&:html_safe) end end @@ -76,7 +74,7 @@ module Blobs def all_lines_size strong_memoize(:all_lines_size) do - @all_lines.size + all_lines.size end end @@ -101,7 +99,7 @@ module Blobs def limited_blob_lines strong_memoize(:limited_blob_lines) do - limit(@all_lines) + limit(all_lines) end end diff --git a/app/presenters/ci/pipeline_presenter.rb b/app/presenters/ci/pipeline_presenter.rb index 358473d0a74..a96f97988b2 100644 --- a/app/presenters/ci/pipeline_presenter.rb +++ b/app/presenters/ci/pipeline_presenter.rb @@ -34,6 +34,18 @@ module Ci end end + NAMES = { + merge_train: s_('Pipeline|Merge train pipeline'), + merged_result: s_('Pipeline|Merged result pipeline'), + detached: s_('Pipeline|Detached merge request pipeline') + }.freeze + + def name + # Currently, `merge_request_event_type` is the only source to name pipelines + # but this could be extended with the other types in the future. + NAMES.fetch(pipeline.merge_request_event_type, s_('Pipeline|Pipeline')) + end + def ref_text if pipeline.detached_merge_request_pipeline? _("for %{link_to_merge_request} with %{link_to_merge_request_source_branch}").html_safe % { link_to_merge_request: link_to_merge_request, link_to_merge_request_source_branch: link_to_merge_request_source_branch } diff --git a/app/presenters/clusterable_presenter.rb b/app/presenters/clusterable_presenter.rb index fff6d23efdf..d1bf0344b66 100644 --- a/app/presenters/clusterable_presenter.rb +++ b/app/presenters/clusterable_presenter.rb @@ -53,6 +53,11 @@ class ClusterablePresenter < Gitlab::View::Presenter::Delegated raise NotImplementedError end + # Will be overidden in EE + def environments_cluster_path(cluster) + nil + end + def empty_state_help_text nil end diff --git a/app/serializers/entity_date_helper.rb b/app/serializers/entity_date_helper.rb index f515abe5917..d8f267d7183 100644 --- a/app/serializers/entity_date_helper.rb +++ b/app/serializers/entity_date_helper.rb @@ -46,12 +46,14 @@ module EntityDateHelper # If start date is provided and elapsed, with no due date, it returns "# days elapsed" def remaining_days_in_words(due_date, start_date = nil) if due_date&.past? - content_tag(:strong, 'Past due') + content_tag(:strong, _('Past due')) + elsif due_date&.today? + content_tag(:strong, _('Today')) elsif start_date&.future? - content_tag(:strong, 'Upcoming') + content_tag(:strong, _('Upcoming')) elsif due_date is_upcoming = (due_date - Date.today).to_i > 0 - time_ago = time_ago_in_words(due_date) + time_ago = distance_of_time_in_words(due_date, Date.today) # https://gitlab.com/gitlab-org/gitlab-ce/issues/49440 # @@ -59,8 +61,8 @@ module EntityDateHelper # of the string instead of piecewise translations. content = time_ago .gsub(/\d+/) { |match| "<strong>#{match}</strong>" } - .remove("about ") - remaining_or_ago = is_upcoming ? _("remaining") : _("ago") + .remove('about ') + remaining_or_ago = is_upcoming ? _('remaining') : _('ago') "#{content} #{remaining_or_ago}".html_safe elsif start_date&.past? diff --git a/app/serializers/pipeline_entity.rb b/app/serializers/pipeline_entity.rb index 9ef93b2387f..94e8b174f0f 100644 --- a/app/serializers/pipeline_entity.rb +++ b/app/serializers/pipeline_entity.rb @@ -2,6 +2,9 @@ class PipelineEntity < Grape::Entity include RequestAwareEntity + include Gitlab::Utils::StrongMemoize + + delegate :name, :failure_reason, to: :presented_pipeline expose :id expose :user, using: UserEntity @@ -36,6 +39,7 @@ class PipelineEntity < Grape::Entity expose :ordered_stages, as: :stages, using: StageEntity expose :duration expose :finished_at + expose :name end expose :merge_request, if: -> (*) { has_presentable_merge_request? }, with: MergeRequestForPipelineEntity do |pipeline| @@ -59,13 +63,11 @@ class PipelineEntity < Grape::Entity end expose :commit, using: CommitEntity + expose :merge_request_event_type, if: -> (pipeline, _) { pipeline.merge_request_event? } expose :source_sha, if: -> (pipeline, _) { pipeline.merge_request_pipeline? } expose :target_sha, if: -> (pipeline, _) { pipeline.merge_request_pipeline? } expose :yaml_errors, if: -> (pipeline, _) { pipeline.has_yaml_errors? } - - expose :failure_reason, if: -> (pipeline, _) { pipeline.failure_reason? } do |pipeline| - pipeline.present.failure_reason - end + expose :failure_reason, if: -> (pipeline, _) { pipeline.failure_reason? } expose :retry_path, if: -> (*) { can_retry? } do |pipeline| retry_project_pipeline_path(pipeline.project, pipeline) @@ -97,4 +99,10 @@ class PipelineEntity < Grape::Entity def detailed_status pipeline.detailed_status(request.current_user) end + + def presented_pipeline + strong_memoize(:presented_pipeline) do + pipeline.present + end + end end diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb index 0a069320936..9e7319c1d9b 100644 --- a/app/services/auth/container_registry_authentication_service.rb +++ b/app/services/auth/container_registry_authentication_service.rb @@ -124,13 +124,21 @@ module Auth build_can_pull?(requested_project) || user_can_pull?(requested_project) || deploy_token_can_pull?(requested_project) when 'push' build_can_push?(requested_project) || user_can_push?(requested_project) - when '*', 'delete' + when 'delete' + build_can_delete?(requested_project) || user_can_admin?(requested_project) + when '*' user_can_admin?(requested_project) else false end end + def build_can_delete?(requested_project) + # Build can delete only from the project from which it originates + has_authentication_ability?(:build_destroy_container_image) && + requested_project == project + end + def registry Gitlab.config.registry end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index 5b8c1288854..a4243b7bc5e 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -285,7 +285,7 @@ class NotificationService recipients = NotificationRecipientService.build_new_note_recipients(note) recipients.each do |recipient| - mailer.send(notify_method, recipient.user.id, note.id).deliver_later + mailer.send(notify_method, recipient.user.id, note.id, recipient.reason).deliver_later end end diff --git a/app/services/releases/concerns.rb b/app/services/releases/concerns.rb index 618d96717b8..b5412e97284 100644 --- a/app/services/releases/concerns.rb +++ b/app/services/releases/concerns.rb @@ -47,6 +47,27 @@ module Releases project.repository end end + + def milestone + return unless params[:milestone] + + strong_memoize(:milestone) do + MilestonesFinder.new( + project: project, + current_user: current_user, + project_ids: Array(project.id), + title: params[:milestone] + ).execute.first + end + end + + def inexistent_milestone? + params[:milestone] && !params[:milestone].empty? && !milestone + end + + def param_for_milestone_title_provided? + params[:milestone].present? || params[:milestone]&.empty? + end end end end diff --git a/app/services/releases/create_service.rb b/app/services/releases/create_service.rb index 5b13ac631ba..c91d43084d3 100644 --- a/app/services/releases/create_service.rb +++ b/app/services/releases/create_service.rb @@ -7,6 +7,7 @@ module Releases def execute return error('Access Denied', 403) unless allowed? return error('Release already exists', 409) if release + return error('Milestone does not exist', 400) if inexistent_milestone? tag = ensure_tag @@ -59,7 +60,8 @@ module Releases tag: tag.name, sha: tag.dereferenced_target.sha, released_at: released_at, - links_attributes: params.dig(:assets, 'links') || [] + links_attributes: params.dig(:assets, 'links') || [], + milestone: milestone ) end end diff --git a/app/services/releases/update_service.rb b/app/services/releases/update_service.rb index fabfa398c59..70acc68f747 100644 --- a/app/services/releases/update_service.rb +++ b/app/services/releases/update_service.rb @@ -9,6 +9,9 @@ module Releases return error('Release does not exist', 404) unless release return error('Access Denied', 403) unless allowed? return error('params is empty', 400) if empty_params? + return error('Milestone does not exist', 400) if inexistent_milestone? + + params[:milestone] = milestone if param_for_milestone_title_provided? if release.update(params) success(tag: existing_tag, release: release) diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb index 858e04f43b2..34260d12a62 100644 --- a/app/services/system_hooks_service.rb +++ b/app/services/system_hooks_service.rb @@ -74,9 +74,11 @@ class SystemHooksService when ProjectMember return "user_add_to_team" if event == :create return "user_remove_from_team" if event == :destroy + return "user_update_for_team" if event == :update when GroupMember return 'user_add_to_group' if event == :create return 'user_remove_from_group' if event == :destroy + return 'user_update_for_group' if event == :update else "#{model.class.name.downcase}_#{event}" end diff --git a/app/views/admin/application_settings/_email.html.haml b/app/views/admin/application_settings/_email.html.haml index bd60ff0b99c..3dd72909805 100644 --- a/app/views/admin/application_settings/_email.html.haml +++ b/app/views/admin/application_settings/_email.html.haml @@ -25,4 +25,4 @@ = render_if_exists 'admin/application_settings/email_additional_text_setting', form: f - = f.submit _('Save changes'), class: "btn btn-success" + = f.submit _('Save changes'), class: "btn btn-success", data: { qa_selector: 'save_changes_button' } diff --git a/app/views/admin/application_settings/preferences.html.haml b/app/views/admin/application_settings/preferences.html.haml index c468d69d7b8..0ad76e56d0b 100644 --- a/app/views/admin/application_settings/preferences.html.haml +++ b/app/views/admin/application_settings/preferences.html.haml @@ -2,7 +2,7 @@ - page_title _("Preferences") - @content_class = "limit-container-width" unless fluid_layout -%section.settings.as-email.no-animate#js-email-settings{ class: ('expanded' if expanded_by_default?) } +%section.settings.as-email.no-animate#js-email-settings{ class: ('expanded' if expanded_by_default?), data: { qa_selector: 'email_section' } } .settings-header %h4 = _('Email') diff --git a/app/views/admin/background_jobs/show.html.haml b/app/views/admin/background_jobs/show.html.haml index a0a00ac5d96..1001a69b787 100644 --- a/app/views/admin/background_jobs/show.html.haml +++ b/app/views/admin/background_jobs/show.html.haml @@ -1,10 +1,8 @@ -- @no_container = true - page_title "Background Jobs" -%div{ class: container_class } - %h3.page-title Background Jobs - %p.light GitLab uses #{link_to "sidekiq", "http://sidekiq.org/"} library for async job processing +%h3.page-title Background Jobs +%p.light GitLab uses #{link_to "sidekiq", "http://sidekiq.org/"} library for async job processing - %hr - .card - %iframe{ src: sidekiq_path, width: '100%', height: 970, style: "border: 0" } +%hr +.card + %iframe{ src: sidekiq_path, width: '100%', height: 970, style: "border: 0" } diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index c29ecb43fe6..8aca61efe7b 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -1,167 +1,165 @@ -- @no_container = true - breadcrumb_title "Dashboard" -%div{ class: container_class } - = render_if_exists 'admin/licenses/breakdown', license: @license += render_if_exists 'admin/licenses/breakdown', license: @license - .admin-dashboard.prepend-top-default - .row - .col-sm-4 - .info-well.dark-well - .well-segment.well-centered - = link_to admin_projects_path do - %h3.text-center - Projects: - = approximate_count_with_delimiters(@counts, Project) - %hr - = link_to('New project', new_project_path, class: "btn btn-success") - .col-sm-4 - .info-well.dark-well - .well-segment.well-centered - = link_to admin_users_path do - %h3.text-center - Users: - = approximate_count_with_delimiters(@counts, User) - %hr - .btn-group.d-flex{ role: 'group' } - = link_to 'New user', new_admin_user_path, class: "btn btn-success" - = render_if_exists 'admin/dashboard/users_statistics' - .col-sm-4 - .info-well.dark-well - .well-segment.well-centered - = link_to admin_groups_path do - %h3.text-center - Groups: - = approximate_count_with_delimiters(@counts, Group) - %hr - = link_to 'New group', new_admin_group_path, class: "btn btn-success" - .row - .col-md-4 - .info-well - .well-segment.admin-well.admin-well-statistics - %h4 Statistics - %p - Forks - %span.light.float-right - = approximate_fork_count_with_delimiters(@counts) - %p - Issues - %span.light.float-right - = approximate_count_with_delimiters(@counts, Issue) - %p - Merge Requests - %span.light.float-right - = approximate_count_with_delimiters(@counts, MergeRequest) - %p - Notes - %span.light.float-right - = approximate_count_with_delimiters(@counts, Note) - %p - Snippets - %span.light.float-right - = approximate_count_with_delimiters(@counts, Snippet) - %p - SSH Keys - %span.light.float-right - = approximate_count_with_delimiters(@counts, Key) - %p - Milestones - %span.light.float-right - = approximate_count_with_delimiters(@counts, Milestone) - %p - Active Users - %span.light.float-right - = number_with_delimiter(User.active.count) - .col-md-4 - .info-well - .well-segment.admin-well.admin-well-features - %h4 Features - = feature_entry(_('Sign up'), href: admin_application_settings_path(anchor: 'js-signup-settings')) - = feature_entry(_('LDAP'), enabled: Gitlab.config.ldap.enabled) - = feature_entry(_('Gravatar'), href: admin_application_settings_path(anchor: 'js-account-settings'), enabled: gravatar_enabled?) - = feature_entry(_('OmniAuth'), href: admin_application_settings_path(anchor: 'js-signin-settings'), enabled: Gitlab::Auth.omniauth_enabled?) - = feature_entry(_('Reply by email'), enabled: Gitlab::IncomingEmail.enabled?) +.admin-dashboard.prepend-top-default + .row + .col-sm-4 + .info-well.dark-well + .well-segment.well-centered + = link_to admin_projects_path do + %h3.text-center + Projects: + = approximate_count_with_delimiters(@counts, Project) + %hr + = link_to('New project', new_project_path, class: "btn btn-success") + .col-sm-4 + .info-well.dark-well + .well-segment.well-centered + = link_to admin_users_path do + %h3.text-center + Users: + = approximate_count_with_delimiters(@counts, User) + %hr + .btn-group.d-flex{ role: 'group' } + = link_to 'New user', new_admin_user_path, class: "btn btn-success" + = render_if_exists 'admin/dashboard/users_statistics' + .col-sm-4 + .info-well.dark-well + .well-segment.well-centered + = link_to admin_groups_path do + %h3.text-center + Groups: + = approximate_count_with_delimiters(@counts, Group) + %hr + = link_to 'New group', new_admin_group_path, class: "btn btn-success" + .row + .col-md-4 + .info-well + .well-segment.admin-well.admin-well-statistics + %h4 Statistics + %p + Forks + %span.light.float-right + = approximate_fork_count_with_delimiters(@counts) + %p + Issues + %span.light.float-right + = approximate_count_with_delimiters(@counts, Issue) + %p + Merge Requests + %span.light.float-right + = approximate_count_with_delimiters(@counts, MergeRequest) + %p + Notes + %span.light.float-right + = approximate_count_with_delimiters(@counts, Note) + %p + Snippets + %span.light.float-right + = approximate_count_with_delimiters(@counts, Snippet) + %p + SSH Keys + %span.light.float-right + = approximate_count_with_delimiters(@counts, Key) + %p + Milestones + %span.light.float-right + = approximate_count_with_delimiters(@counts, Milestone) + %p + Active Users + %span.light.float-right + = number_with_delimiter(User.active.count) + .col-md-4 + .info-well + .well-segment.admin-well.admin-well-features + %h4 Features + = feature_entry(_('Sign up'), href: admin_application_settings_path(anchor: 'js-signup-settings')) + = feature_entry(_('LDAP'), enabled: Gitlab.config.ldap.enabled) + = feature_entry(_('Gravatar'), href: admin_application_settings_path(anchor: 'js-account-settings'), enabled: gravatar_enabled?) + = feature_entry(_('OmniAuth'), href: admin_application_settings_path(anchor: 'js-signin-settings'), enabled: Gitlab::Auth.omniauth_enabled?) + = feature_entry(_('Reply by email'), enabled: Gitlab::IncomingEmail.enabled?) - = render_if_exists 'admin/dashboard/elastic_and_geo' + = render_if_exists 'admin/dashboard/elastic_and_geo' - = feature_entry(_('Container Registry'), href: ci_cd_admin_application_settings_path(anchor: 'js-registry-settings'), enabled: Gitlab.config.registry.enabled) - = feature_entry(_('Gitlab Pages'), href: help_instance_configuration_url, enabled: Gitlab.config.pages.enabled) - = feature_entry(_('Shared Runners'), href: admin_runners_path, enabled: Gitlab.config.gitlab_ci.shared_runners_enabled) - .col-md-4 - .info-well - .well-segment.admin-well - %h4 - Components - - if Gitlab::CurrentSettings.version_check_enabled - .float-right - = version_status_badge - %p - %a{ href: admin_application_settings_path } - GitLab + = feature_entry(_('Container Registry'), href: ci_cd_admin_application_settings_path(anchor: 'js-registry-settings'), enabled: Gitlab.config.registry.enabled) + = feature_entry(_('Gitlab Pages'), href: help_instance_configuration_url, enabled: Gitlab.config.pages.enabled) + = feature_entry(_('Shared Runners'), href: admin_runners_path, enabled: Gitlab.config.gitlab_ci.shared_runners_enabled) + .col-md-4 + .info-well + .well-segment.admin-well + %h4 + Components + - if Gitlab::CurrentSettings.version_check_enabled + .float-right + = version_status_badge + %p + %a{ href: admin_application_settings_path } + GitLab + %span.float-right + = Gitlab::VERSION + = "(#{Gitlab.revision})" + %p + GitLab Shell + %span.float-right + = Gitlab::Shell.new.version + %p + GitLab Workhorse + %span.float-right + = gitlab_workhorse_version + %p + GitLab API + %span.float-right + = API::API::version + - if Gitlab.config.pages.enabled + %p + GitLab Pages %span.float-right - = Gitlab::VERSION - = "(#{Gitlab.revision})" - %p - GitLab Shell - %span.float-right - = Gitlab::Shell.new.version - %p - GitLab Workhorse - %span.float-right - = gitlab_workhorse_version - %p - GitLab API - %span.float-right - = API::API::version - - if Gitlab.config.pages.enabled - %p - GitLab Pages - %span.float-right - = Gitlab::Pages::VERSION + = Gitlab::Pages::VERSION - = render_if_exists 'admin/dashboard/geo' + = render_if_exists 'admin/dashboard/geo' - %p - Ruby - %span.float-right - #{RUBY_VERSION}p#{RUBY_PATCHLEVEL} - %p - Rails - %span.float-right - #{Rails::VERSION::STRING} - %p - = Gitlab::Database.human_adapter_name - %span.float-right - = Gitlab::Database.version - %p - = link_to "Gitaly Servers", admin_gitaly_servers_path - .row - .col-md-4 - .info-well - .well-segment.admin-well - %h4 Latest projects - - @projects.each do |project| - %p - = link_to project.full_name, admin_project_path(project), class: 'str-truncated-60' - %span.light.float-right - #{time_ago_with_tooltip(project.created_at)} - .col-md-4 - .info-well - .well-segment.admin-well - %h4 Latest users - - @users.each do |user| - %p - = link_to [:admin, user], class: 'str-truncated-60' do - = user.name - %span.light.float-right - #{time_ago_with_tooltip(user.created_at)} - .col-md-4 - .info-well - .well-segment.admin-well - %h4 Latest groups - - @groups.each do |group| - %p - = link_to [:admin, group], class: 'str-truncated-60' do - = group.full_name - %span.light.float-right - #{time_ago_with_tooltip(group.created_at)} + %p + Ruby + %span.float-right + #{RUBY_VERSION}p#{RUBY_PATCHLEVEL} + %p + Rails + %span.float-right + #{Rails::VERSION::STRING} + %p + = Gitlab::Database.human_adapter_name + %span.float-right + = Gitlab::Database.version + %p + = link_to "Gitaly Servers", admin_gitaly_servers_path + .row + .col-md-4 + .info-well + .well-segment.admin-well + %h4 Latest projects + - @projects.each do |project| + %p + = link_to project.full_name, admin_project_path(project), class: 'str-truncated-60' + %span.light.float-right + #{time_ago_with_tooltip(project.created_at)} + .col-md-4 + .info-well + .well-segment.admin-well + %h4 Latest users + - @users.each do |user| + %p + = link_to [:admin, user], class: 'str-truncated-60' do + = user.name + %span.light.float-right + #{time_ago_with_tooltip(user.created_at)} + .col-md-4 + .info-well + .well-segment.admin-well + %h4 Latest groups + - @groups.each do |group| + %p + = link_to [:admin, group], class: 'str-truncated-60' do + = group.full_name + %span.light.float-right + #{time_ago_with_tooltip(group.created_at)} diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml index cb833ffd9ac..434b6e3a37e 100644 --- a/app/views/admin/groups/index.html.haml +++ b/app/views/admin/groups/index.html.haml @@ -1,20 +1,18 @@ -- @no_container = true - page_title _("Groups") -%div{ class: container_class } - .top-area - .prepend-top-default.append-bottom-default - = form_tag admin_groups_path, method: :get, class: 'js-search-form' do |f| - = hidden_field_tag :sort, @sort - .search-holder - - project_name = params[:name].present? ? params[:name] : nil - .search-field-holder - = search_field_tag :name, project_name, class: "form-control search-text-input js-search-input", autofocus: true, spellcheck: false, placeholder: 'Search by name' - = icon("search", class: "search-icon") - = render "shared/groups/dropdown", options_hash: admin_groups_sort_options_hash - = link_to new_admin_group_path, class: "btn btn-success" do - = _('New group') - %ul.content-list - = render @groups +.top-area + .prepend-top-default.append-bottom-default + = form_tag admin_groups_path, method: :get, class: 'js-search-form' do |f| + = hidden_field_tag :sort, @sort + .search-holder + - project_name = params[:name].present? ? params[:name] : nil + .search-field-holder + = search_field_tag :name, project_name, class: "form-control search-text-input js-search-input", autofocus: true, spellcheck: false, placeholder: 'Search by name' + = icon("search", class: "search-icon") + = render "shared/groups/dropdown", options_hash: admin_groups_sort_options_hash + = link_to new_admin_group_path, class: "btn btn-success" do + = _('New group') +%ul.content-list + = render @groups - = paginate @groups, theme: "gitlab" += paginate @groups, theme: "gitlab" diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml index ac56e354a4d..587bfba8d47 100644 --- a/app/views/admin/health_check/show.html.haml +++ b/app/views/admin/health_check/show.html.haml @@ -1,41 +1,39 @@ -- @no_container = true - page_title _('Health Check') - no_errors = @errors.blank? -%div{ class: container_class } - %h3.page-title= page_title - .bs-callout.clearfix - .float-left - %p - #{ s_('HealthCheck|Access token is') } - %code#health-check-token= Gitlab::CurrentSettings.health_check_access_token - .prepend-top-10 - = button_to _("Reset health check access token"), reset_health_check_token_admin_application_settings_path, - method: :put, class: 'btn btn-default', - data: { confirm: _('Are you sure you want to reset the health check token?') } - %p.light - #{ _('Health information can be retrieved from the following endpoints. More information is available') } - = link_to s_('More information is available|here'), help_page_path('user/admin_area/monitoring/health_check') - %ul - %li - %code= readiness_url(token: Gitlab::CurrentSettings.health_check_access_token) - %li - %code= liveness_url(token: Gitlab::CurrentSettings.health_check_access_token) - %li - %code= metrics_url(token: Gitlab::CurrentSettings.health_check_access_token) - = render_if_exists 'admin/health_check/health_check_url' - %hr - .card - .card-header - Current Status: - - if no_errors - = icon('circle', class: 'cgreen') - #{ s_('HealthCheck|Healthy') } - - else - = icon('warning', class: 'cred') - #{ s_('HealthCheck|Unhealthy') } - .card-body - - if no_errors - #{ s_('HealthCheck|No Health Problems Detected') } - - else - = @errors +%h3.page-title= page_title +.bs-callout.clearfix + .float-left + %p + #{ s_('HealthCheck|Access token is') } + %code#health-check-token= Gitlab::CurrentSettings.health_check_access_token + .prepend-top-10 + = button_to _("Reset health check access token"), reset_health_check_token_admin_application_settings_path, + method: :put, class: 'btn btn-default', + data: { confirm: _('Are you sure you want to reset the health check token?') } +%p.light + #{ _('Health information can be retrieved from the following endpoints. More information is available') } + = link_to s_('More information is available|here'), help_page_path('user/admin_area/monitoring/health_check') + %ul + %li + %code= readiness_url(token: Gitlab::CurrentSettings.health_check_access_token) + %li + %code= liveness_url(token: Gitlab::CurrentSettings.health_check_access_token) + %li + %code= metrics_url(token: Gitlab::CurrentSettings.health_check_access_token) + = render_if_exists 'admin/health_check/health_check_url' +%hr +.card + .card-header + Current Status: + - if no_errors + = icon('circle', class: 'cgreen') + #{ s_('HealthCheck|Healthy') } + - else + = icon('warning', class: 'cred') + #{ s_('HealthCheck|Unhealthy') } + .card-body + - if no_errors + #{ s_('HealthCheck|No Health Problems Detected') } + - else + = @errors diff --git a/app/views/admin/jobs/index.html.haml b/app/views/admin/jobs/index.html.haml index 4e3e2f7a475..f1bdd52b399 100644 --- a/app/views/admin/jobs/index.html.haml +++ b/app/views/admin/jobs/index.html.haml @@ -1,22 +1,19 @@ - breadcrumb_title "Jobs" -- @no_container = true -%div{ class: container_class } +.top-area.scrolling-tabs-container.inner-page-scroll-tabs + - build_path_proc = ->(scope) { admin_jobs_path(scope: scope) } + = render "shared/builds/tabs", build_path_proc: build_path_proc, all_builds: @all_builds, scope: @scope - .top-area.scrolling-tabs-container.inner-page-scroll-tabs - - build_path_proc = ->(scope) { admin_jobs_path(scope: scope) } - = render "shared/builds/tabs", build_path_proc: build_path_proc, all_builds: @all_builds, scope: @scope + - if @all_builds.running_or_pending.any? + #stop-jobs-modal + .nav-controls + %button#stop-jobs-button.btn.btn-danger{ data: { toggle: 'modal', + target: '#stop-jobs-modal', + url: cancel_all_admin_jobs_path } } + = s_('AdminArea|Stop all jobs') - - if @all_builds.running_or_pending.any? - #stop-jobs-modal - .nav-controls - %button#stop-jobs-button.btn.btn-danger{ data: { toggle: 'modal', - target: '#stop-jobs-modal', - url: cancel_all_admin_jobs_path } } - = s_('AdminArea|Stop all jobs') +.row-content-block.second-block + #{(@scope || 'all').capitalize} jobs - .row-content-block.second-block - #{(@scope || 'all').capitalize} jobs - - %ul.content-list.builds-content-list.admin-builds-table - = render "projects/jobs/table", builds: @builds, admin: true +%ul.content-list.builds-content-list.admin-builds-table + = render "projects/jobs/table", builds: @builds, admin: true diff --git a/app/views/admin/logs/show.html.haml b/app/views/admin/logs/show.html.haml index e4c0382a437..eb93f645ea6 100644 --- a/app/views/admin/logs/show.html.haml +++ b/app/views/admin/logs/show.html.haml @@ -1,26 +1,24 @@ -- @no_container = true - page_title "Logs" -%div{ class: container_class } - %ul.nav-links.log-tabs.nav.nav-tabs - - @loggers.each do |klass| - %li.nav-item - = link_to klass.file_name, "##{klass.file_name_noext}", data: { toggle: 'tab' }, class: "#{active_when(klass == @loggers.first)} nav-link" - .row-content-block - To prevent performance issues admin logs output the last 2000 lines - .tab-content - - @loggers.each do |klass| - .tab-pane{ class: active_when(klass == @loggers.first), id: klass.file_name_noext } - .file-holder#README - .js-file-title.file-title - %i.fa.fa-file - = klass.file_name - .float-right - = link_to '#', class: 'log-bottom' do - %i.fa.fa-arrow-down - Scroll down - .file-content.logs - %ol - - klass.read_latest.each do |line| - %li - %p= line +%ul.nav-links.log-tabs.nav.nav-tabs + - @loggers.each do |klass| + %li.nav-item + = link_to klass.file_name, "##{klass.file_name_noext}", data: { toggle: 'tab' }, class: "#{active_when(klass == @loggers.first)} nav-link" +.row-content-block + To prevent performance issues admin logs output the last 2000 lines +.tab-content + - @loggers.each do |klass| + .tab-pane{ class: active_when(klass == @loggers.first), id: klass.file_name_noext } + .file-holder#README + .js-file-title.file-title + %i.fa.fa-file + = klass.file_name + .float-right + = link_to '#', class: 'log-bottom' do + %i.fa.fa-arrow-down + Scroll down + .file-content.logs + %ol + - klass.read_latest.each do |line| + %li + %p= line diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index b88b760536d..7e03eb4f075 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -1,44 +1,41 @@ -- @no_container = true - page_title "Projects" - params[:visibility_level] ||= [] +.top-area.scrolling-tabs-container.inner-page-scroll-tabs + .prepend-top-default + .search-holder + = render 'shared/projects/search_form', autofocus: true, icon: true, admin_view: true + .dropdown + - toggle_text = 'Namespace' + - if params[:namespace_id].present? + = hidden_field_tag :namespace_id, params[:namespace_id] + - namespace = Namespace.find(params[:namespace_id]) + - toggle_text = "#{namespace.kind}: #{namespace.full_path}" + = dropdown_toggle(toggle_text, { toggle: 'dropdown', is_filter: 'true' }, { toggle_class: 'js-namespace-select large' }) + .dropdown-menu.dropdown-select.dropdown-menu-right + = dropdown_title('Namespaces') + = dropdown_filter("Search for Namespace") + = dropdown_content + = dropdown_loading + = render 'shared/projects/dropdown' + = link_to new_project_path, class: 'btn btn-success' do + New Project + = button_tag "Search", class: "btn btn-primary btn-search hide" -%div{ class: container_class } - .top-area.scrolling-tabs-container.inner-page-scroll-tabs - .prepend-top-default - .search-holder - = render 'shared/projects/search_form', autofocus: true, icon: true, admin_view: true - .dropdown - - toggle_text = 'Namespace' - - if params[:namespace_id].present? - = hidden_field_tag :namespace_id, params[:namespace_id] - - namespace = Namespace.find(params[:namespace_id]) - - toggle_text = "#{namespace.kind}: #{namespace.full_path}" - = dropdown_toggle(toggle_text, { toggle: 'dropdown', is_filter: 'true' }, { toggle_class: 'js-namespace-select large' }) - .dropdown-menu.dropdown-select.dropdown-menu-right - = dropdown_title('Namespaces') - = dropdown_filter("Search for Namespace") - = dropdown_content - = dropdown_loading - = render 'shared/projects/dropdown' - = link_to new_project_path, class: 'btn btn-success' do - New Project - = button_tag "Search", class: "btn btn-primary btn-search hide" + %ul.nav-links.nav.nav-tabs + - opts = params[:visibility_level].present? ? {} : { page: admin_projects_path } + = nav_link(opts) do + = link_to admin_projects_path do + All - %ul.nav-links.nav.nav-tabs - - opts = params[:visibility_level].present? ? {} : { page: admin_projects_path } - = nav_link(opts) do - = link_to admin_projects_path do - All + = nav_link(html_options: { class: active_when(params[:visibility_level] == Gitlab::VisibilityLevel::PRIVATE.to_s) }) do + = link_to admin_projects_path(visibility_level: Gitlab::VisibilityLevel::PRIVATE) do + Private + = nav_link(html_options: { class: active_when(params[:visibility_level] == Gitlab::VisibilityLevel::INTERNAL.to_s) }) do + = link_to admin_projects_path(visibility_level: Gitlab::VisibilityLevel::INTERNAL) do + Internal + = nav_link(html_options: { class: active_when(params[:visibility_level] == Gitlab::VisibilityLevel::PUBLIC.to_s) }) do + = link_to admin_projects_path(visibility_level: Gitlab::VisibilityLevel::PUBLIC) do + Public - = nav_link(html_options: { class: active_when(params[:visibility_level] == Gitlab::VisibilityLevel::PRIVATE.to_s) }) do - = link_to admin_projects_path(visibility_level: Gitlab::VisibilityLevel::PRIVATE) do - Private - = nav_link(html_options: { class: active_when(params[:visibility_level] == Gitlab::VisibilityLevel::INTERNAL.to_s) }) do - = link_to admin_projects_path(visibility_level: Gitlab::VisibilityLevel::INTERNAL) do - Internal - = nav_link(html_options: { class: active_when(params[:visibility_level] == Gitlab::VisibilityLevel::PUBLIC.to_s) }) do - = link_to admin_projects_path(visibility_level: Gitlab::VisibilityLevel::PUBLIC) do - Public - - = render 'projects' += render 'projects' diff --git a/app/views/admin/requests_profiles/index.html.haml b/app/views/admin/requests_profiles/index.html.haml index 86bfeef580c..efc16bb4d3b 100644 --- a/app/views/admin/requests_profiles/index.html.haml +++ b/app/views/admin/requests_profiles/index.html.haml @@ -1,26 +1,24 @@ -- @no_container = true - page_title 'Requests Profiles' -%div{ class: container_class } - %h3.page-title - = page_title +%h3.page-title + = page_title - .bs-callout.clearfix - Pass the header - %code X-Profile-Token: #{@profile_token} - to profile the request +.bs-callout.clearfix + Pass the header + %code X-Profile-Token: #{@profile_token} + to profile the request - - if @profiles.present? - .prepend-top-default - - @profiles.each do |path, profiles| - .card.card-small - .card-header - %code= path - %ul.content-list - - profiles.each do |profile| - %li - = link_to profile.time.to_s(:long) + ' ' + profile.profile_mode.capitalize, - admin_requests_profile_path(profile) - - else - %p - No profiles found +- if @profiles.present? + .prepend-top-default + - @profiles.each do |path, profiles| + .card.card-small + .card-header + %code= path + %ul.content-list + - profiles.each do |profile| + %li + = link_to profile.time.to_s(:long) + ' ' + profile.profile_mode.capitalize, + admin_requests_profile_path(profile) +- else + %p + No profiles found diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml index 5129f5d193b..76af4189b5b 100644 --- a/app/views/admin/runners/index.html.haml +++ b/app/views/admin/runners/index.html.haml @@ -1,96 +1,87 @@ - breadcrumb_title _('Runners') -- @no_container = true -%div{ class: container_class } - .row - .col-sm-6 - .bs-callout - %p - = (_"A 'Runner' is a process which runs a job. You can set up as many Runners as you need.") - %br - = _('Runners can be placed on separate users, servers, even on your local machine.') - %br +.row + .col-sm-6 + .bs-callout + %p + = (_"A 'Runner' is a process which runs a job. You can set up as many Runners as you need.") + %br + = _('Runners can be placed on separate users, servers, even on your local machine.') + %br - %div - %span= _('Each Runner can be in one of the following states:') - %ul - %li - %span.badge.badge-success shared - \- - = _('Runner runs jobs from all unassigned projects') - %li - %span.badge.badge-success group - \- - = _('Runner runs jobs from all unassigned projects in its group') - %li - %span.badge.badge-info specific - \- - = _('Runner runs jobs from assigned projects') - %li - %span.badge.badge-warning locked - \- - = _('Runner cannot be assigned to other projects') - %li - %span.badge.badge-danger paused - \- - = _('Runner will not receive any new jobs') + %div + %span= _('Each Runner can be in one of the following states:') + %ul + %li + %span.badge.badge-success shared + \- + = _('Runner runs jobs from all unassigned projects') + %li + %span.badge.badge-success group + \- + = _('Runner runs jobs from all unassigned projects in its group') + %li + %span.badge.badge-info specific + \- + = _('Runner runs jobs from assigned projects') + %li + %span.badge.badge-warning locked + \- + = _('Runner cannot be assigned to other projects') + %li + %span.badge.badge-danger paused + \- + = _('Runner will not receive any new jobs') - .col-sm-6 - .bs-callout - = render partial: 'ci/runner/how_to_setup_runner', - locals: { registration_token: Gitlab::CurrentSettings.runners_registration_token, - type: 'shared', - reset_token_url: reset_registration_token_admin_application_settings_path } + .col-sm-6 + .bs-callout + = render partial: 'ci/runner/how_to_setup_runner', + locals: { registration_token: Gitlab::CurrentSettings.runners_registration_token, + type: 'shared', + reset_token_url: reset_registration_token_admin_application_settings_path } - .row - .col-sm-9 - = form_tag admin_runners_path, id: 'runners-search', method: :get, class: 'filter-form js-filter-form' do - .filtered-search-wrapper - .filtered-search-box - = dropdown_tag(custom_icon('icon_history'), - options: { wrapper_class: 'filtered-search-history-dropdown-wrapper', - toggle_class: 'filtered-search-history-dropdown-toggle-button', - dropdown_class: 'filtered-search-history-dropdown', - content_class: 'filtered-search-history-dropdown-content', - title: _('Recent searches') }) do - .js-filtered-search-history-dropdown{ data: { full_path: admin_runners_path } } - .filtered-search-box-input-container.droplab-dropdown - .scroll-container - %ul.tokens-container.list-unstyled - %li.input-token - %input.form-control.filtered-search{ search_filter_input_options('runners') } - #js-dropdown-hint.filtered-search-input-dropdown-menu.dropdown-menu.hint-dropdown - %ul{ data: { dropdown: true } } - %li.filter-dropdown-item{ data: { action: 'submit' } } - = button_tag class: %w[btn btn-link] do - = sprite_icon('search') - %span - = _('Press Enter or click to search') - %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } } - %li.filter-dropdown-item - = button_tag class: %w[btn btn-link] do - -# Encapsulate static class name `{{icon}}` inside #{} to bypass - -# haml lint's ClassAttributeWithStaticValue - %svg - %use{ 'xlink:href': "#{'{{icon}}'}" } - %span.js-filter-hint - {{hint}} - %span.js-filter-tag.dropdown-light-content - {{tag}} - - #js-dropdown-admin-runner-status.filtered-search-input-dropdown-menu.dropdown-menu - %ul{ data: { dropdown: true } } - - Ci::Runner::AVAILABLE_STATUSES.each do |status| - %li.filter-dropdown-item{ data: { value: status } } - = button_tag class: %w[btn btn-link] do - = status.titleize +.row + .col-sm-9 + = form_tag admin_runners_path, id: 'runners-search', method: :get, class: 'filter-form js-filter-form' do + .filtered-search-wrapper + .filtered-search-box + = dropdown_tag(custom_icon('icon_history'), + options: { wrapper_class: 'filtered-search-history-dropdown-wrapper', + toggle_class: 'filtered-search-history-dropdown-toggle-button', + dropdown_class: 'filtered-search-history-dropdown', + content_class: 'filtered-search-history-dropdown-content', + title: _('Recent searches') }) do + .js-filtered-search-history-dropdown{ data: { full_path: admin_runners_path } } + .filtered-search-box-input-container.droplab-dropdown + .scroll-container + %ul.tokens-container.list-unstyled + %li.input-token + %input.form-control.filtered-search{ search_filter_input_options('runners') } + #js-dropdown-hint.filtered-search-input-dropdown-menu.dropdown-menu.hint-dropdown + %ul{ data: { dropdown: true } } + %li.filter-dropdown-item{ data: { action: 'submit' } } + = button_tag class: %w[btn btn-link] do + = sprite_icon('search') + %span + = _('Press Enter or click to search') + %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } } + %li.filter-dropdown-item + = button_tag class: %w[btn btn-link] do + -# Encapsulate static class name `{{icon}}` inside #{} to bypass + -# haml lint's ClassAttributeWithStaticValue + %svg + %use{ 'xlink:href': "#{'{{icon}}'}" } + %span.js-filter-hint + {{hint}} + %span.js-filter-tag.dropdown-light-content + {{tag}} - #js-dropdown-admin-runner-type.filtered-search-input-dropdown-menu.dropdown-menu - %ul{ data: { dropdown: true } } - - Ci::Runner::AVAILABLE_TYPES.each do |runner_type| - %li.filter-dropdown-item{ data: { value: runner_type } } - = button_tag class: %w[btn btn-link] do - = runner_type.titleize + #js-dropdown-admin-runner-status.filtered-search-input-dropdown-menu.dropdown-menu + %ul{ data: { dropdown: true } } + - Ci::Runner::AVAILABLE_STATUSES.each do |status| + %li.filter-dropdown-item{ data: { value: status } } + = button_tag class: %w[btn btn-link] do + = status.titleize #js-dropdown-admin-runner-type.filtered-search-input-dropdown-menu.dropdown-menu %ul{ data: { dropdown: true } } @@ -99,43 +90,50 @@ = button_tag class: %w[btn btn-link] do = runner_type.titleize - #js-dropdown-runner-tag.filtered-search-input-dropdown-menu.dropdown-menu - %ul{ data: { dropdown: true } } - %li.filter-dropdown-item{ data: { value: 'none' } } - %button.btn.btn-link - = _('No Tag') - %li.divider.droplab-item-ignore - %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } } - %li.filter-dropdown-item - %button.btn.btn-link.js-data-value - %span.dropdown-light-content - {{name}} + #js-dropdown-admin-runner-type.filtered-search-input-dropdown-menu.dropdown-menu + %ul{ data: { dropdown: true } } + - Ci::Runner::AVAILABLE_TYPES.each do |runner_type| + %li.filter-dropdown-item{ data: { value: runner_type } } + = button_tag class: %w[btn btn-link] do + = runner_type.titleize + + #js-dropdown-runner-tag.filtered-search-input-dropdown-menu.dropdown-menu + %ul{ data: { dropdown: true } } + %li.filter-dropdown-item{ data: { value: 'none' } } + %button.btn.btn-link + = _('No Tag') + %li.divider.droplab-item-ignore + %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } } + %li.filter-dropdown-item + %button.btn.btn-link.js-data-value + %span.dropdown-light-content + {{name}} - = button_tag class: %w[clear-search hidden] do - = icon('times') - .filter-dropdown-container - = render 'sort_dropdown' + = button_tag class: %w[clear-search hidden] do + = icon('times') + .filter-dropdown-container + = render 'sort_dropdown' - .col-sm-3.text-right-lg - = _('Runners currently online: %{active_runners_count}') % { active_runners_count: @active_runners_count } + .col-sm-3.text-right-lg + = _('Runners currently online: %{active_runners_count}') % { active_runners_count: @active_runners_count } - - if @runners.any? - .runners-content.content-list - .table-holder - .gl-responsive-table-row.table-row-header{ role: 'row' } - .table-section.section-10{ role: 'rowheader' }= _('Type') - .table-section.section-10{ role: 'rowheader' }= _('Runner token') - .table-section.section-20{ role: 'rowheader' }= _('Description') - .table-section.section-10{ role: 'rowheader' }= _('Version') - .table-section.section-10{ role: 'rowheader' }= _('IP Address') - .table-section.section-5{ role: 'rowheader' }= _('Projects') - .table-section.section-5{ role: 'rowheader' }= _('Jobs') - .table-section.section-10{ role: 'rowheader' }= _('Tags') - .table-section.section-10{ role: 'rowheader' }= _('Last contact') - .table-section.section-10{ role: 'rowheader' } +- if @runners.any? + .runners-content.content-list + .table-holder + .gl-responsive-table-row.table-row-header{ role: 'row' } + .table-section.section-10{ role: 'rowheader' }= _('Type') + .table-section.section-10{ role: 'rowheader' }= _('Runner token') + .table-section.section-20{ role: 'rowheader' }= _('Description') + .table-section.section-10{ role: 'rowheader' }= _('Version') + .table-section.section-10{ role: 'rowheader' }= _('IP Address') + .table-section.section-5{ role: 'rowheader' }= _('Projects') + .table-section.section-5{ role: 'rowheader' }= _('Jobs') + .table-section.section-10{ role: 'rowheader' }= _('Tags') + .table-section.section-10{ role: 'rowheader' }= _('Last contact') + .table-section.section-10{ role: 'rowheader' } - - @runners.each do |runner| - = render 'admin/runners/runner', runner: runner - = paginate @runners, theme: 'gitlab' - - else - .nothing-here-block= _('No runners found') + - @runners.each do |runner| + = render 'admin/runners/runner', runner: runner + = paginate @runners, theme: 'gitlab' +- else + .nothing-here-block= _('No runners found') diff --git a/app/views/admin/system_info/show.html.haml b/app/views/admin/system_info/show.html.haml index b19934e028d..948a11646f7 100644 --- a/app/views/admin/system_info/show.html.haml +++ b/app/views/admin/system_info/show.html.haml @@ -1,37 +1,35 @@ -- @no_container = true - page_title "System Info" -%div{ class: container_class } - .prepend-top-default - .row - .col-sm-4 - .card.bg-light.light-well - %h4 CPU - .data - - if @cpus - %h1 #{@cpus.length} cores - - else - = icon('warning', class: 'text-warning') - Unable to collect CPU info - .col-sm-4 - .card.bg-light.light-well - %h4 Memory Usage - .data - - if @memory - %h1 #{number_to_human_size(@memory.active_bytes)} / #{number_to_human_size(@memory.total_bytes)} - - else - = icon('warning', class: 'text-warning') - Unable to collect memory info - .col-sm-4 - .card.bg-light.light-well - %h4 Disk Usage - .data - - @disks.each do |disk| - %h1 #{number_to_human_size(disk[:bytes_used])} / #{number_to_human_size(disk[:bytes_total])} - %p= disk[:disk_name] - %p= disk[:mount_path] - .col-sm-4 - .card.bg-light.light-well - %h4 Uptime - .data - %h1= distance_of_time_in_words_to_now(Rails.application.config.booted_at) +.prepend-top-default +.row + .col-sm-4 + .card.bg-light.light-well + %h4 CPU + .data + - if @cpus + %h1 #{@cpus.length} cores + - else + = icon('warning', class: 'text-warning') + Unable to collect CPU info + .col-sm-4 + .card.bg-light.light-well + %h4 Memory Usage + .data + - if @memory + %h1 #{number_to_human_size(@memory.active_bytes)} / #{number_to_human_size(@memory.total_bytes)} + - else + = icon('warning', class: 'text-warning') + Unable to collect memory info + .col-sm-4 + .card.bg-light.light-well + %h4 Disk Usage + .data + - @disks.each do |disk| + %h1 #{number_to_human_size(disk[:bytes_used])} / #{number_to_human_size(disk[:bytes_total])} + %p= disk[:disk_name] + %p= disk[:mount_path] + .col-sm-4 + .card.bg-light.light-well + %h4 Uptime + .data + %h1= distance_of_time_in_words_to_now(Rails.application.config.booted_at) diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index 6fc7ec1bb6f..36b62557fa6 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -1,79 +1,77 @@ -- @no_container = true - page_title "Users" -%div{ class: container_class } - .top-area.scrolling-tabs-container.inner-page-scroll-tabs - .fade-left - = icon('angle-left') - .fade-right - = icon('angle-right') - %ul.nav-links.nav.nav-tabs.scrolling-tabs - = nav_link(html_options: { class: active_when(params[:filter].nil?) }) do - = link_to admin_users_path do - = s_('AdminUsers|Active') - %small.badge.badge-pill= limited_counter_with_delimiter(User.active) - = nav_link(html_options: { class: active_when(params[:filter] == 'admins') }) do - = link_to admin_users_path(filter: "admins") do - = s_('AdminUsers|Admins') - %small.badge.badge-pill= limited_counter_with_delimiter(User.admins) - = nav_link(html_options: { class: "#{active_when(params[:filter] == 'two_factor_enabled')} filter-two-factor-enabled" }) do - = link_to admin_users_path(filter: 'two_factor_enabled') do - = s_('AdminUsers|2FA Enabled') - %small.badge.badge-pill= limited_counter_with_delimiter(User.with_two_factor) - = nav_link(html_options: { class: "#{active_when(params[:filter] == 'two_factor_disabled')} filter-two-factor-disabled" }) do - = link_to admin_users_path(filter: 'two_factor_disabled') do - = s_('AdminUsers|2FA Disabled') - %small.badge.badge-pill= limited_counter_with_delimiter(User.without_two_factor) - = nav_link(html_options: { class: active_when(params[:filter] == 'external') }) do - = link_to admin_users_path(filter: 'external') do - = s_('AdminUsers|External') - %small.badge.badge-pill= limited_counter_with_delimiter(User.external) - = nav_link(html_options: { class: active_when(params[:filter] == 'blocked') }) do - = link_to admin_users_path(filter: "blocked") do - = s_('AdminUsers|Blocked') - %small.badge.badge-pill= limited_counter_with_delimiter(User.blocked) - = nav_link(html_options: { class: active_when(params[:filter] == 'wop') }) do - = link_to admin_users_path(filter: "wop") do - = s_('AdminUsers|Without projects') - %small.badge.badge-pill= limited_counter_with_delimiter(User.without_projects) - .nav-controls - = render_if_exists 'admin/users/admin_email_users' - = link_to s_('AdminUsers|New user'), new_admin_user_path, class: 'btn btn-success btn-search float-right' +.top-area.scrolling-tabs-container.inner-page-scroll-tabs + .fade-left + = icon('angle-left') + .fade-right + = icon('angle-right') + %ul.nav-links.nav.nav-tabs.scrolling-tabs + = nav_link(html_options: { class: active_when(params[:filter].nil?) }) do + = link_to admin_users_path do + = s_('AdminUsers|Active') + %small.badge.badge-pill= limited_counter_with_delimiter(User.active) + = nav_link(html_options: { class: active_when(params[:filter] == 'admins') }) do + = link_to admin_users_path(filter: "admins") do + = s_('AdminUsers|Admins') + %small.badge.badge-pill= limited_counter_with_delimiter(User.admins) + = nav_link(html_options: { class: "#{active_when(params[:filter] == 'two_factor_enabled')} filter-two-factor-enabled" }) do + = link_to admin_users_path(filter: 'two_factor_enabled') do + = s_('AdminUsers|2FA Enabled') + %small.badge.badge-pill= limited_counter_with_delimiter(User.with_two_factor) + = nav_link(html_options: { class: "#{active_when(params[:filter] == 'two_factor_disabled')} filter-two-factor-disabled" }) do + = link_to admin_users_path(filter: 'two_factor_disabled') do + = s_('AdminUsers|2FA Disabled') + %small.badge.badge-pill= limited_counter_with_delimiter(User.without_two_factor) + = nav_link(html_options: { class: active_when(params[:filter] == 'external') }) do + = link_to admin_users_path(filter: 'external') do + = s_('AdminUsers|External') + %small.badge.badge-pill= limited_counter_with_delimiter(User.external) + = nav_link(html_options: { class: active_when(params[:filter] == 'blocked') }) do + = link_to admin_users_path(filter: "blocked") do + = s_('AdminUsers|Blocked') + %small.badge.badge-pill= limited_counter_with_delimiter(User.blocked) + = nav_link(html_options: { class: active_when(params[:filter] == 'wop') }) do + = link_to admin_users_path(filter: "wop") do + = s_('AdminUsers|Without projects') + %small.badge.badge-pill= limited_counter_with_delimiter(User.without_projects) + .nav-controls + = render_if_exists 'admin/users/admin_email_users' + = link_to s_('AdminUsers|New user'), new_admin_user_path, class: 'btn btn-success btn-search float-right' - .filtered-search-block.row-content-block.border-top-0 - = form_tag admin_users_path, method: :get do - - if params[:filter].present? - = hidden_field_tag "filter", h(params[:filter]) - .search-holder - .search-field-holder - = search_field_tag :search_query, params[:search_query], placeholder: s_('AdminUsers|Search by name, email or username'), class: 'form-control search-text-input js-search-input', spellcheck: false - - if @sort.present? - = hidden_field_tag :sort, @sort - = icon("search", class: "search-icon") - = button_tag s_('AdminUsers|Search users') if Rails.env.test? - .dropdown.user-sort-dropdown - - toggle_text = @sort.present? ? users_sort_options_hash[@sort] : sort_title_name - = dropdown_toggle(toggle_text, { toggle: 'dropdown' }) - %ul.dropdown-menu.dropdown-menu-right - %li.dropdown-header - = s_('AdminUsers|Sort by') - %li - - users_sort_options_hash.each do |value, title| - = link_to admin_users_path(sort: value, filter: params[:filter], search_query: params[:search_query]) do - = title +.filtered-search-block.row-content-block.border-top-0 + = form_tag admin_users_path, method: :get do + - if params[:filter].present? + = hidden_field_tag "filter", h(params[:filter]) + .search-holder + .search-field-holder + = search_field_tag :search_query, params[:search_query], placeholder: s_('AdminUsers|Search by name, email or username'), class: 'form-control search-text-input js-search-input', spellcheck: false + - if @sort.present? + = hidden_field_tag :sort, @sort + = icon("search", class: "search-icon") + = button_tag s_('AdminUsers|Search users') if Rails.env.test? + .dropdown.user-sort-dropdown + - toggle_text = @sort.present? ? users_sort_options_hash[@sort] : sort_title_name + = dropdown_toggle(toggle_text, { toggle: 'dropdown' }) + %ul.dropdown-menu.dropdown-menu-right + %li.dropdown-header + = s_('AdminUsers|Sort by') + %li + - users_sort_options_hash.each do |value, title| + = link_to admin_users_path(sort: value, filter: params[:filter], search_query: params[:search_query]) do + = title - - if @users.empty? - .nothing-here-block.border-top-0 - = s_('AdminUsers|No users found') - - else - .table-holder - .thead-white.text-nowrap.gl-responsive-table-row.table-row-header{ role: 'row' } - .table-section.section-40{ role: 'rowheader' }= _('Name') - .table-section.section-25{ role: 'rowheader' }= _('Created on') - .table-section.section-15{ role: 'rowheader' }= _('Last activity') +- if @users.empty? + .nothing-here-block.border-top-0 + = s_('AdminUsers|No users found') +- else + .table-holder + .thead-white.text-nowrap.gl-responsive-table-row.table-row-header{ role: 'row' } + .table-section.section-40{ role: 'rowheader' }= _('Name') + .table-section.section-25{ role: 'rowheader' }= _('Created on') + .table-section.section-15{ role: 'rowheader' }= _('Last activity') - = render partial: 'admin/users/user', collection: @users + = render partial: 'admin/users/user', collection: @users - = paginate @users, theme: "gitlab" += paginate @users, theme: "gitlab" #delete-user-modal diff --git a/app/views/clusters/clusters/user/_form.html.haml b/app/views/clusters/clusters/user/_form.html.haml index 1d212553c3b..5507f12b73b 100644 --- a/app/views/clusters/clusters/user/_form.html.haml +++ b/app/views/clusters/clusters/user/_form.html.haml @@ -25,6 +25,7 @@ help: '%{help_text} %{help_link}'.html_safe % { help_text: api_url_help_text, help_link: more_info_link } = platform_kubernetes_field.text_area :ca_cert, + rows: '10', placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)'), label: s_('ClusterIntegration|CA Certificate'), label_class: 'label-bold', help: '%{help_text} %{help_link}'.html_safe % { help_text: ca_cert_help_text, help_link: more_info_link } diff --git a/app/views/clusters/platforms/kubernetes/_form.html.haml b/app/views/clusters/platforms/kubernetes/_form.html.haml index e50c573bd90..41701b5614a 100644 --- a/app/views/clusters/platforms/kubernetes/_form.html.haml +++ b/app/views/clusters/platforms/kubernetes/_form.html.haml @@ -19,7 +19,7 @@ - copy_ca_cert_btn = clipboard_button(text: platform.ca_cert, title: s_('ClusterIntegration|Copy CA Certificate'), class: 'input-group-text btn-default') if cluster.read_only_kubernetes_platform_fields? - = platform_field.text_area :ca_cert, class: 'js-select-on-focus', rows: '5', + = platform_field.text_area :ca_cert, class: 'js-select-on-focus', rows: '10', readonly: cluster.read_only_kubernetes_platform_fields?, placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)'), label: s_('ClusterIntegration|CA Certificate'), label_class: 'label-bold', diff --git a/app/views/dashboard/activity.html.haml b/app/views/dashboard/activity.html.haml index b1c192d7bad..d7306f5932d 100644 --- a/app/views/dashboard/activity.html.haml +++ b/app/views/dashboard/activity.html.haml @@ -1,18 +1,15 @@ - @hide_top_links = true -- @no_container = true = content_for :meta_tags do = auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity") - = render_dashboard_gold_trial(current_user) - page_title "Activity" - header_title "Activity", activity_dashboard_path -%div{ class: container_class } - = render "projects/last_push" - = render 'dashboard/activity_head' += render "projects/last_push" += render 'dashboard/activity_head' - %section.activities - = render 'activities' +%section.activities + = render 'activities' diff --git a/app/views/dashboard/projects/index.html.haml b/app/views/dashboard/projects/index.html.haml index 0298f539b4b..d2aa07bab22 100644 --- a/app/views/dashboard/projects/index.html.haml +++ b/app/views/dashboard/projects/index.html.haml @@ -1,4 +1,3 @@ -- @no_container = true - @hide_top_links = true = content_for :meta_tags do @@ -9,11 +8,10 @@ - page_title "Projects" - header_title "Projects", dashboard_projects_path -%div{ class: container_class } - = render "projects/last_push" - - if show_projects?(@projects, params) - = render 'dashboard/projects_head' - = render 'nav' unless Feature.enabled?(:project_list_filter_bar) - = render 'projects' - - else - = render "zero_authorized_projects" += render "projects/last_push" +- if show_projects?(@projects, params) + = render 'dashboard/projects_head' + = render 'nav' unless Feature.enabled?(:project_list_filter_bar) + = render 'projects' +- else + = render "zero_authorized_projects" diff --git a/app/views/dashboard/projects/starred.html.haml b/app/views/dashboard/projects/starred.html.haml index 0fcc6894b68..2924918aa4f 100644 --- a/app/views/dashboard/projects/starred.html.haml +++ b/app/views/dashboard/projects/starred.html.haml @@ -1,16 +1,14 @@ - @hide_top_links = true -- @no_container = true - breadcrumb_title _("Projects") - page_title _("Starred Projects") - header_title _("Projects"), dashboard_projects_path = render_dashboard_gold_trial(current_user) -%div{ class: container_class } - = render "projects/last_push" - = render 'dashboard/projects_head', project_tab_filter: :starred += render "projects/last_push" += render 'dashboard/projects_head', project_tab_filter: :starred - - if params[:filter_projects] || any_projects?(@projects) - = render 'projects' - - else - = render 'starred_empty_state' +- if params[:filter_projects] || any_projects?(@projects) + = render 'projects' +- else + = render 'starred_empty_state' diff --git a/app/views/groups/labels/index.html.haml b/app/views/groups/labels/index.html.haml index a8358704b03..41c1d3e84b7 100644 --- a/app/views/groups/labels/index.html.haml +++ b/app/views/groups/labels/index.html.haml @@ -1,4 +1,3 @@ -- @no_container = true - page_title 'Labels' - can_admin_label = can?(current_user, :admin_label, @group) - search = params[:search] @@ -7,24 +6,23 @@ - if labels_or_filters #promote-label-modal - %div{ class: container_class } - = render 'shared/labels/nav', labels_or_filters: labels_or_filters, can_admin_label: can_admin_label + = render 'shared/labels/nav', labels_or_filters: labels_or_filters, can_admin_label: can_admin_label - .labels-container.prepend-top-5 - - if @labels.any? - .text-muted - = _('Labels can be applied to %{features}. Group labels are available for any project within the group.') % { features: issuable_types.to_sentence } - .other-labels - %h5= _('Labels') - %ul.content-list.manage-labels-list.js-other-labels - = render partial: 'shared/label', collection: @labels, as: :label, locals: { use_label_priority: false, subject: @group } - = paginate @labels, theme: 'gitlab' - - elsif search.present? - .nothing-here-block - = _('No labels with such name or description') - - elsif subscribed.present? - .nothing-here-block - = _('You do not have any subscriptions yet') + .labels-container.prepend-top-5 + - if @labels.any? + .text-muted + = _('Labels can be applied to %{features}. Group labels are available for any project within the group.') % { features: issuable_types.to_sentence } + .other-labels + %h5= _('Labels') + %ul.content-list.manage-labels-list.js-other-labels + = render partial: 'shared/label', collection: @labels, as: :label, locals: { use_label_priority: false, subject: @group } + = paginate @labels, theme: 'gitlab' + - elsif search.present? + .nothing-here-block + = _('No labels with such name or description') + - elsif subscribed.present? + .nothing-here-block + = _('You do not have any subscriptions yet') - else = render 'shared/empty_states/labels' diff --git a/app/views/groups/milestones/new.html.haml b/app/views/groups/milestones/new.html.haml index 248cb3b0ba5..2c93b0e4efd 100644 --- a/app/views/groups/milestones/new.html.haml +++ b/app/views/groups/milestones/new.html.haml @@ -1,12 +1,10 @@ -- @no_container = true - add_to_breadcrumbs _("Milestones"), group_milestones_path(@group) - breadcrumb_title _("New") - page_title _("Milestones"), @milestone.name, _("Milestones") -%div{ class: container_class } - %h3.page-title - New Milestone +%h3.page-title + New Milestone - %hr +%hr - = render "form" += render "form" diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index 255a9ad038c..0e6c16f0f06 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -1,11 +1,10 @@ -- @no_container = true - breadcrumb_title _("Details") - @content_class = "limit-container-width" unless fluid_layout = content_for :meta_tags do = auto_discovery_link_tag(:atom, group_url(@group, rss_url_options), title: "#{@group.name} activity") -%div{ class: [container_class, ("limit-container-width" unless fluid_layout)] } +%div{ class: [("limit-container-width" unless fluid_layout)] } = render 'groups/home_panel' .groups-listing{ data: { endpoints: { default: group_children_path(@group, format: :json), shared: group_shared_projects_path(@group, format: :json) } } } diff --git a/app/views/instance_statistics/cohorts/index.html.haml b/app/views/instance_statistics/cohorts/index.html.haml index e135bab10d8..c438566cb05 100644 --- a/app/views/instance_statistics/cohorts/index.html.haml +++ b/app/views/instance_statistics/cohorts/index.html.haml @@ -1,16 +1,14 @@ - breadcrumb_title _("Cohorts") -- @no_container = true -%div{ class: container_class } - - if @cohorts - = render 'cohorts_table' - - else - .bs-callout.bs-callout-warning.clearfix - %p - - usage_ping_path = help_page_path('user/admin_area/settings/usage_statistics', anchor: 'usage-ping') - - usage_ping_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: usage_ping_path } - = s_('User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled.').html_safe % { usage_ping_link_start: usage_ping_link_start, usage_ping_link_end: '</a>'.html_safe } - - if current_user.admin? - - application_settings_path = admin_application_settings_path(anchor: 'usage-statistics') - - application_settings_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: application_settings_path } - = s_('To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}.').html_safe % { application_settings_link_start: application_settings_link_start, application_settings_link_end: '</a>'.html_safe } +- if @cohorts + = render 'cohorts_table' +- else + .bs-callout.bs-callout-warning.clearfix + %p + - usage_ping_path = help_page_path('user/admin_area/settings/usage_statistics', anchor: 'usage-ping') + - usage_ping_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: usage_ping_path } + = s_('User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled.').html_safe % { usage_ping_link_start: usage_ping_link_start, usage_ping_link_end: '</a>'.html_safe } + - if current_user.admin? + - application_settings_path = admin_application_settings_path(anchor: 'usage-statistics') + - application_settings_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: application_settings_path } + = s_('To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}.').html_safe % { application_settings_link_start: application_settings_link_start, application_settings_link_end: '</a>'.html_safe } diff --git a/app/views/instance_statistics/conversational_development_index/index.html.haml b/app/views/instance_statistics/conversational_development_index/index.html.haml index 23f90b876a0..49c8fdc9630 100644 --- a/app/views/instance_statistics/conversational_development_index/index.html.haml +++ b/app/views/instance_statistics/conversational_development_index/index.html.haml @@ -1,4 +1,3 @@ -- @no_container = true - page_title _('ConvDev Index') - usage_ping_enabled = Gitlab::CurrentSettings.usage_ping_enabled diff --git a/app/views/layouts/_flash.html.haml b/app/views/layouts/_flash.html.haml index 2cdaa85bdaa..d673d7164b3 100644 --- a/app/views/layouts/_flash.html.haml +++ b/app/views/layouts/_flash.html.haml @@ -1,10 +1,8 @@ -- extra_flash_class = local_assigns.fetch(:extra_flash_class, nil) - -.flash-container.flash-container-page +.flash-container.flash-container-page.sticky -# We currently only support `alert`, `notice`, `success` - flash.each do |key, value| -# Don't show a flash message if the message is nil - if value - %div{ class: "flash-#{key}" } - %div{ class: "#{(container_class unless fluid_layout)} #{(extra_flash_class unless @no_container)} #{@content_class}" } - %span= value + %div{ class: "flash-content flash-#{key} rounded" } + %span= value + = sprite_icon('close', size: 16, css_class: 'close-icon') diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml index 006334ade07..443a73f5cce 100644 --- a/app/views/layouts/_page.html.haml +++ b/app/views/layouts/_page.html.haml @@ -13,8 +13,8 @@ = render "shared/ping_consent" - unless @hide_breadcrumbs = render "layouts/nav/breadcrumbs" - = render "layouts/flash", extra_flash_class: 'limit-container-width' .d-flex %div{ class: "#{(container_class unless @no_container)} #{@content_class}" } .content{ id: "content-body" } + = render "layouts/flash", extra_flash_class: 'limit-container-width' = yield diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml index 9e92ced9f89..f76268bc29b 100644 --- a/app/views/layouts/nav/sidebar/_admin.html.haml +++ b/app/views/layouts/nav/sidebar/_admin.html.haml @@ -270,7 +270,7 @@ %span = _('Geo') = nav_link(path: 'application_settings#preferences') do - = link_to preferences_admin_application_settings_path, title: _('Preferences') do + = link_to preferences_admin_application_settings_path, title: _('Preferences'), data: { qa_selector: 'admin_settings_preferences_link' } do %span = _('Preferences') diff --git a/app/views/projects/activity.html.haml b/app/views/projects/activity.html.haml index b28a375e956..6a4760c3954 100644 --- a/app/views/projects/activity.html.haml +++ b/app/views/projects/activity.html.haml @@ -1,8 +1,4 @@ -- @no_container = true - - page_title _("Activity") -%div{ class: container_class } - = render 'projects/last_push' - += render 'projects/last_push' = render 'projects/activity' diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml index ef6f5c76de6..f2215765974 100644 --- a/app/views/projects/blame/show.html.haml +++ b/app/views/projects/blame/show.html.haml @@ -1,44 +1,42 @@ -- @no_container = true - project_duration = age_map_duration(@blame_groups, @project) - page_title "Blame", @blob.path, @ref -%div{ class: container_class } - #blob-content-holder.tree-holder - = render "projects/blob/breadcrumb", blob: @blob, blame: true +#blob-content-holder.tree-holder + = render "projects/blob/breadcrumb", blob: @blob, blame: true - .file-holder - = render "projects/blob/header", blob: @blob, blame: true - .file-blame-legend - = render 'age_map_legend' - .table-responsive.file-content.blame.code.js-syntax-highlight - %table - - current_line = 1 - - @blame_groups.each do |blame_group| - %tr - - commit = blame_group[:commit] - %td.blame-commit{ class: age_map_class(commit.committed_date, project_duration) } - .commit - = author_avatar(commit, size: 36, has_tooltip: false) - .commit-row-title - %span.item-title.str-truncated-100 - = link_to_markdown commit.title, project_commit_path(@project, commit.id), class: "cdark", title: commit.title - .float-right - = link_to commit.short_id, project_commit_path(@project, commit), class: "commit-sha" - - .light - = commit_author_link(commit, avatar: false) - committed - #{time_ago_with_tooltip(commit.committed_date)} - %td.line-numbers - - line_count = blame_group[:lines].count - - (current_line...(current_line + line_count)).each do |i| - %a.diff-line-num{ href: "#L#{i}", id: "L#{i}", 'data-line-number' => i } - = icon("link") - = i - \ - - current_line += line_count - %td.lines - %pre.code.highlight - %code - - blame_group[:lines].each do |line| - #{line} + .file-holder + = render "projects/blob/header", blob: @blob, blame: true + .file-blame-legend + = render 'age_map_legend' + .table-responsive.file-content.blame.code.js-syntax-highlight + %table + - current_line = 1 + - @blame_groups.each do |blame_group| + %tr + - commit = blame_group[:commit] + %td.blame-commit{ class: age_map_class(commit.committed_date, project_duration) } + .commit + = author_avatar(commit, size: 36, has_tooltip: false) + .commit-row-title + %span.item-title.str-truncated-100 + = link_to_markdown commit.title, project_commit_path(@project, commit.id), class: "cdark", title: commit.title + .float-right + = link_to commit.short_id, project_commit_path(@project, commit), class: "commit-sha" + + .light + = commit_author_link(commit, avatar: false) + committed + #{time_ago_with_tooltip(commit.committed_date)} + %td.line-numbers + - line_count = blame_group[:lines].count + - (current_line...(current_line + line_count)).each do |i| + %a.diff-line-num{ href: "#L#{i}", id: "L#{i}", 'data-line-number' => i } + = icon("link") + = i + \ + - current_line += line_count + %td.lines + %pre.code.highlight + %code + - blame_group[:lines].each do |line| + #{line} diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml index 4520cca8cf5..51e42091ab8 100644 --- a/app/views/projects/blob/edit.html.haml +++ b/app/views/projects/blob/edit.html.haml @@ -1,33 +1,31 @@ - breadcrumb_title "Repository" -- @no_container = true - page_title "Edit", @blob.path, @ref - content_for :page_specific_javascripts do = page_specific_javascript_tag('lib/ace.js') -%div{ class: container_class } - - if @conflict - .alert.alert-danger - Someone edited the file the same time you did. Please check out - = link_to "the file", project_blob_path(@project, tree_join(@branch_name, @file_path)), target: "_blank", rel: 'noopener noreferrer' - and make sure your changes will not unintentionally remove theirs. - .editor-title-row - %h3.page-title.blob-edit-page-title - Edit file - = render 'template_selectors' - .file-editor - %ul.nav-links.no-bottom.js-edit-mode.nav.nav-tabs - %li.active - = link_to '#editor' do - Write +- if @conflict + .alert.alert-danger + Someone edited the file the same time you did. Please check out + = link_to "the file", project_blob_path(@project, tree_join(@branch_name, @file_path)), target: "_blank", rel: 'noopener noreferrer' + and make sure your changes will not unintentionally remove theirs. +.editor-title-row + %h3.page-title.blob-edit-page-title + Edit file + = render 'template_selectors' +.file-editor + %ul.nav-links.no-bottom.js-edit-mode.nav.nav-tabs + %li.active + = link_to '#editor' do + Write - %li - = link_to '#preview', 'data-preview-url' => project_preview_blob_path(@project, @id) do - = editing_preview_title(@blob.name) + %li + = link_to '#preview', 'data-preview-url' => project_preview_blob_path(@project, @id) do + = editing_preview_title(@blob.name) - = form_tag(project_update_blob_path(@project, @id), method: :put, class: 'js-quick-submit js-requires-input js-edit-blob-form', data: blob_editor_paths(@project)) do - = render 'projects/blob/editor', ref: @ref, path: @path, blob_data: @blob.data - = render 'shared/new_commit_form', placeholder: "Update #{@blob.name}" - = hidden_field_tag 'last_commit_sha', @last_commit_sha - = hidden_field_tag 'content', '', id: "file-content" - = hidden_field_tag 'from_merge_request_iid', params[:from_merge_request_iid] - = render 'projects/commit_button', ref: @ref, cancel_path: project_blob_path(@project, @id) + = form_tag(project_update_blob_path(@project, @id), method: :put, class: 'js-quick-submit js-requires-input js-edit-blob-form', data: blob_editor_paths(@project)) do + = render 'projects/blob/editor', ref: @ref, path: @path, blob_data: @blob.data + = render 'shared/new_commit_form', placeholder: "Update #{@blob.name}" + = hidden_field_tag 'last_commit_sha', @last_commit_sha + = hidden_field_tag 'content', '', id: "file-content" + = hidden_field_tag 'from_merge_request_iid', params[:from_merge_request_iid] + = render 'projects/commit_button', ref: @ref, cancel_path: project_blob_path(@project, @id) diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml index a0b0384d78d..688b8f001c3 100644 --- a/app/views/projects/blob/show.html.haml +++ b/app/views/projects/blob/show.html.haml @@ -1,19 +1,16 @@ - breadcrumb_title "Repository" -- @no_container = true - - page_title @blob.path, @ref - - signatures_path = namespace_project_signatures_path(namespace_id: @project.namespace.full_path, project_id: @project.path, id: @last_commit) + .js-signature-container{ data: { 'signatures-path': signatures_path } } -%div{ class: container_class } - = render 'projects/last_push' += render 'projects/last_push' - #tree-holder.tree-holder - = render 'blob', blob: @blob +#tree-holder.tree-holder + = render 'blob', blob: @blob - - if can_modify_blob?(@blob) - = render 'projects/blob/remove' + - if can_modify_blob?(@blob) + = render 'projects/blob/remove' - - title = "Replace #{@blob.name}" - = render 'projects/blob/upload', title: title, placeholder: title, button_title: 'Replace file', form_path: project_update_blob_path(@project, @id), method: :put + - title = "Replace #{@blob.name}" + = render 'projects/blob/upload', title: title, placeholder: title, button_title: 'Replace file', form_path: project_update_blob_path(@project, @id), method: :put diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml index 11340d12423..6bdc6f716fe 100644 --- a/app/views/projects/branches/index.html.haml +++ b/app/views/projects/branches/index.html.haml @@ -1,70 +1,68 @@ -- @no_container = true - page_title _('Branches') - add_to_breadcrumbs(_('Repository'), project_tree_path(@project)) -%div{ class: container_class } - .top-area.adjust - %ul.nav-links.issues-state-filters.nav.nav-tabs - %li{ class: active_when(@mode == 'overview') }> - = link_to s_('Branches|Overview'), project_branches_path(@project), title: s_('Branches|Show overview of the branches') +.top-area.adjust + %ul.nav-links.issues-state-filters.nav.nav-tabs + %li{ class: active_when(@mode == 'overview') }> + = link_to s_('Branches|Overview'), project_branches_path(@project), title: s_('Branches|Show overview of the branches') - %li{ class: active_when(@mode == 'active') }> - = link_to s_('Branches|Active'), project_branches_filtered_path(@project, state: 'active'), title: s_('Branches|Show active branches') + %li{ class: active_when(@mode == 'active') }> + = link_to s_('Branches|Active'), project_branches_filtered_path(@project, state: 'active'), title: s_('Branches|Show active branches') - %li{ class: active_when(@mode == 'stale') }> - = link_to s_('Branches|Stale'), project_branches_filtered_path(@project, state: 'stale'), title: s_('Branches|Show stale branches') + %li{ class: active_when(@mode == 'stale') }> + = link_to s_('Branches|Stale'), project_branches_filtered_path(@project, state: 'stale'), title: s_('Branches|Show stale branches') - %li{ class: active_when(!%w[overview active stale].include?(@mode)) }> - = link_to s_('Branches|All'), project_branches_filtered_path(@project, state: 'all'), title: s_('Branches|Show all branches') + %li{ class: active_when(!%w[overview active stale].include?(@mode)) }> + = link_to s_('Branches|All'), project_branches_filtered_path(@project, state: 'all'), title: s_('Branches|Show all branches') - .nav-controls - = form_tag(project_branches_filtered_path(@project, state: 'all'), method: :get) do - = search_field_tag :search, params[:search], { placeholder: s_('Branches|Filter by branch name'), id: 'branch-search', class: 'form-control search-text-input input-short', spellcheck: false } + .nav-controls + = form_tag(project_branches_filtered_path(@project, state: 'all'), method: :get) do + = search_field_tag :search, params[:search], { placeholder: s_('Branches|Filter by branch name'), id: 'branch-search', class: 'form-control search-text-input input-short', spellcheck: false } - - unless @mode == 'overview' - .dropdown.inline> - %button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' } - %span.light - = branches_sort_options_hash[@sort] - = icon('chevron-down') - %ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable - %li.dropdown-header - = s_('Branches|Sort by') - - branches_sort_options_hash.each do |value, title| - %li - = link_to title, project_branches_filtered_path(@project, state: 'all', search: params[:search], sort: value), class: ("is-active" if @sort == value) + - unless @mode == 'overview' + .dropdown.inline> + %button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' } + %span.light + = branches_sort_options_hash[@sort] + = icon('chevron-down') + %ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable + %li.dropdown-header + = s_('Branches|Sort by') + - branches_sort_options_hash.each do |value, title| + %li + = link_to title, project_branches_filtered_path(@project, state: 'all', search: params[:search], sort: value), class: ("is-active" if @sort == value) - - if can? current_user, :push_code, @project - = link_to project_merged_branches_path(@project), - class: 'btn btn-inverted btn-remove has-tooltip qa-delete-merged-branches', - title: s_("Branches|Delete all branches that are merged into '%{default_branch}'") % { default_branch: @project.repository.root_ref }, - method: :delete, - data: { confirm: s_('Branches|Deleting the merged branches cannot be undone. Are you sure?'), - container: 'body' } do - = s_('Branches|Delete merged branches') - = link_to new_project_branch_path(@project), class: 'btn btn-success' do - = s_('Branches|New branch') + - if can? current_user, :push_code, @project + = link_to project_merged_branches_path(@project), + class: 'btn btn-inverted btn-remove has-tooltip qa-delete-merged-branches', + title: s_("Branches|Delete all branches that are merged into '%{default_branch}'") % { default_branch: @project.repository.root_ref }, + method: :delete, + data: { confirm: s_('Branches|Deleting the merged branches cannot be undone. Are you sure?'), + container: 'body' } do + = s_('Branches|Delete merged branches') + = link_to new_project_branch_path(@project), class: 'btn btn-success' do + = s_('Branches|New branch') - = render_if_exists 'projects/commits/mirror_status' += render_if_exists 'projects/commits/mirror_status' - .js-branch-list{ data: { diverging_counts_endpoint: diverging_commit_counts_namespace_project_branches_path(@project.namespace, @project, format: :json) } } - - if can?(current_user, :admin_project, @project) - - project_settings_link = link_to s_('Branches|project settings'), project_protected_branches_path(@project) - .row-content-block - %h5 - = s_('Branches|Protected branches can be managed in %{project_settings_link}.').html_safe % { project_settings_link: project_settings_link } +.js-branch-list{ data: { diverging_counts_endpoint: diverging_commit_counts_namespace_project_branches_path(@project.namespace, @project, format: :json) } } +- if can?(current_user, :admin_project, @project) + - project_settings_link = link_to s_('Branches|project settings'), project_protected_branches_path(@project) + .row-content-block + %h5 + = s_('Branches|Protected branches can be managed in %{project_settings_link}.').html_safe % { project_settings_link: project_settings_link } - - if @mode == 'overview' && (@active_branches.any? || @stale_branches.any?) - = render "projects/branches/panel", branches: @active_branches, state: 'active', panel_title: s_('Branches|Active branches'), show_more_text: s_('Branches|Show more active branches'), project: @project, overview_max_branches: @overview_max_branches - = render "projects/branches/panel", branches: @stale_branches, state: 'stale', panel_title: s_('Branches|Stale branches'), show_more_text: s_('Branches|Show more stale branches'), project: @project, overview_max_branches: @overview_max_branches +- if @mode == 'overview' && (@active_branches.any? || @stale_branches.any?) + = render "projects/branches/panel", branches: @active_branches, state: 'active', panel_title: s_('Branches|Active branches'), show_more_text: s_('Branches|Show more active branches'), project: @project, overview_max_branches: @overview_max_branches + = render "projects/branches/panel", branches: @stale_branches, state: 'stale', panel_title: s_('Branches|Stale branches'), show_more_text: s_('Branches|Show more stale branches'), project: @project, overview_max_branches: @overview_max_branches - - elsif @branches.any? - %ul.content-list.all-branches - - @branches.each do |branch| - = render "projects/branches/branch", branch: branch, merged: @merged_branch_names.include?(branch.name) - = paginate @branches, theme: 'gitlab' - - else - .nothing-here-block - = s_('Branches|No branches to show') +- elsif @branches.any? + %ul.content-list.all-branches + - @branches.each do |branch| + = render "projects/branches/branch", branch: branch, merged: @merged_branch_names.include?(branch.name) + = paginate @branches, theme: 'gitlab' +- else + .nothing-here-block + = s_('Branches|No branches to show') = render 'projects/branches/delete_protected_modal' diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml index 34226167288..40b96ca477e 100644 --- a/app/views/projects/commit/show.html.haml +++ b/app/views/projects/commit/show.html.haml @@ -1,3 +1,4 @@ +-# no_container is needed here because of full width side-by-side diff view - @no_container = true - add_to_breadcrumbs _('Commits'), project_commits_path(@project) - breadcrumb_title @commit.short_id diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml index 2db1efdd52f..e155e3758fb 100644 --- a/app/views/projects/commits/show.html.haml +++ b/app/views/projects/commits/show.html.haml @@ -1,4 +1,3 @@ -- @no_container = true - breadcrumb_title _("Commits") - page_title _("Commits"), @ref @@ -6,33 +5,32 @@ = auto_discovery_link_tag(:atom, project_commits_path(@project, @ref, rss_url_options), title: "#{@project.name}:#{@ref} commits") .js-project-commits-show{ 'data-commits-limit' => @limit } - %div{ class: container_class } - .tree-holder - .nav-block - .tree-ref-container - .tree-ref-holder - = render 'shared/ref_switcher', destination: 'commits' - - %ul.breadcrumb.repo-breadcrumb - = commits_breadcrumbs - .tree-controls.d-none.d-sm-none.d-md-block - - if @merge_request.present? - .control - = link_to _("View open merge request"), project_merge_request_path(@project, @merge_request), class: 'btn' - - elsif create_mr_button?(@repository.root_ref, @ref) - .control - = link_to _("Create merge request"), create_mr_path(@repository.root_ref, @ref), class: 'btn btn-success' + .tree-holder + .nav-block + .tree-ref-container + .tree-ref-holder + = render 'shared/ref_switcher', destination: 'commits' + %ul.breadcrumb.repo-breadcrumb + = commits_breadcrumbs + .tree-controls.d-none.d-sm-none.d-md-block + - if @merge_request.present? .control - = form_tag(project_commits_path(@project, @id), method: :get, class: 'commits-search-form js-signature-container', data: { 'signatures-path' => namespace_project_signatures_path }) do - = search_field_tag :search, params[:search], { placeholder: _('Filter by commit message'), id: 'commits-search', class: 'form-control search-text-input input-short', spellcheck: false } + = link_to _("View open merge request"), project_merge_request_path(@project, @merge_request), class: 'btn' + - elsif create_mr_button?(@repository.root_ref, @ref) .control - = link_to project_commits_path(@project, @ref, rss_url_options), title: _("Commits feed"), class: 'btn' do - = icon("rss") + = link_to _("Create merge request"), create_mr_path(@repository.root_ref, @ref), class: 'btn btn-success' + + .control + = form_tag(project_commits_path(@project, @id), method: :get, class: 'commits-search-form js-signature-container', data: { 'signatures-path' => namespace_project_signatures_path }) do + = search_field_tag :search, params[:search], { placeholder: _('Filter by commit message'), id: 'commits-search', class: 'form-control search-text-input input-short', spellcheck: false } + .control + = link_to project_commits_path(@project, @ref, rss_url_options), title: _("Commits feed"), class: 'btn' do + = icon("rss") - = render_if_exists 'projects/commits/mirror_status' + = render_if_exists 'projects/commits/mirror_status' - %div{ id: dom_id(@project) } - %ol#commits-list.list-unstyled.content_list - = render 'commits', project: @project, ref: @ref - = spinner + %div{ id: dom_id(@project) } + %ol#commits-list.list-unstyled.content_list + = render 'commits', project: @project, ref: @ref + = spinner diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml index 14c64b3534a..02f2b104ce3 100644 --- a/app/views/projects/compare/index.html.haml +++ b/app/views/projects/compare/index.html.haml @@ -1,18 +1,16 @@ -- @no_container = true - breadcrumb_title "Compare Revisions" - page_title "Compare" -%div{ class: container_class } - %h3.page-title - = _("Compare Git revisions") - .sub-header-block - - example_master = capture do - %code.ref-name master - - example_sha = capture do - %code.ref-name 4eedf23 - = (_("Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request.") % { master: example_master, sha: example_sha }).html_safe - %br - = (_("Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision.")).html_safe +%h3.page-title + = _("Compare Git revisions") +.sub-header-block + - example_master = capture do + %code.ref-name master + - example_sha = capture do + %code.ref-name 4eedf23 + = (_("Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request.") % { master: example_master, sha: example_sha }).html_safe + %br + = (_("Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision.")).html_safe - .prepend-top-20 - = render "form" +.prepend-top-20 + = render "form" diff --git a/app/views/projects/compare/show.html.haml b/app/views/projects/compare/show.html.haml index 5774b48a054..51cf95dc84b 100644 --- a/app/views/projects/compare/show.html.haml +++ b/app/views/projects/compare/show.html.haml @@ -1,25 +1,23 @@ -- @no_container = true - add_to_breadcrumbs _("Compare Revisions"), project_compare_index_path(@project) - page_title "#{params[:from]}...#{params[:to]}" -%div{ class: container_class } - .sub-header-block.no-bottom-space - = render "form" +.sub-header-block.no-bottom-space + = render "form" - - if @commits.present? - = render "projects/commits/commit_list" - = render "projects/diffs/diffs", diffs: @diffs, environment: @environment, diff_page_context: "is-compare" - - else - .card.bg-light - .center - %h4 - = s_("CompareBranches|There isn't anything to compare.") - %p.slead - - if params[:to] == params[:from] - - source_branch = capture do - %span.ref-name= params[:from] - - target_branch = capture do - %span.ref-name= params[:to] - = (s_("CompareBranches|%{source_branch} and %{target_branch} are the same.") % { source_branch: source_branch, target_branch: target_branch }).html_safe - - else - = _("You'll need to use different branch names to get a valid comparison.") +- if @commits.present? + = render "projects/commits/commit_list" + = render "projects/diffs/diffs", diffs: @diffs, environment: @environment, diff_page_context: "is-compare" +- else + .card.bg-light + .center + %h4 + = s_("CompareBranches|There isn't anything to compare.") + %p.slead + - if params[:to] == params[:from] + - source_branch = capture do + %span.ref-name= params[:from] + - target_branch = capture do + %span.ref-name= params[:to] + = (s_("CompareBranches|%{source_branch} and %{target_branch} are the same.") % { source_branch: source_branch, target_branch: target_branch }).html_safe + - else + = _("You'll need to use different branch names to get a valid comparison.") diff --git a/app/views/projects/cycle_analytics/show.html.haml b/app/views/projects/cycle_analytics/show.html.haml index 2b594c125f4..6b56a4ee7ab 100644 --- a/app/views/projects/cycle_analytics/show.html.haml +++ b/app/views/projects/cycle_analytics/show.html.haml @@ -1,7 +1,6 @@ -- @no_container = true - page_title "Cycle Analytics" -#cycle-analytics{ class: container_class, "v-cloak" => "true", data: { request_path: project_cycle_analytics_path(@project) } } +#cycle-analytics{ "v-cloak" => "true", data: { request_path: project_cycle_analytics_path(@project) } } - if @cycle_analytics_no_data %banner{ "v-if" => "!isOverviewDialogDismissed", "documentation-link": help_page_path('user/project/cycle_analytics'), diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml index 9fa31c147eb..a9b6b397968 100644 --- a/app/views/projects/empty.html.haml +++ b/app/views/projects/empty.html.haml @@ -1,10 +1,9 @@ - @content_class = "limit-container-width" unless fluid_layout -- @no_container = true - breadcrumb_title _("Details") = render partial: 'flash_messages', locals: { project: @project } -%div{ class: [container_class, ("limit-container-width" unless fluid_layout)] } +%div{ class: [("limit-container-width" unless fluid_layout)] } = render "home_panel" %h4.prepend-top-0.append-bottom-8 diff --git a/app/views/projects/environments/edit.html.haml b/app/views/projects/environments/edit.html.haml index d581bd3aeab..56af252d785 100644 --- a/app/views/projects/environments/edit.html.haml +++ b/app/views/projects/environments/edit.html.haml @@ -1,8 +1,6 @@ -- @no_container = true - page_title _("Edit"), @environment.name, _("Environments") -%div{ class: container_class } - %h3.page-title - = _('Edit environment') - %hr - = render 'form' +%h3.page-title + = _('Edit environment') +%hr += render 'form' diff --git a/app/views/projects/environments/folder.html.haml b/app/views/projects/environments/folder.html.haml index aebd176af9b..f85c57d9aa1 100644 --- a/app/views/projects/environments/folder.html.haml +++ b/app/views/projects/environments/folder.html.haml @@ -1,5 +1,3 @@ -- @no_container = true - page_title _("Environments") -#environments-folder-list-view{ data: { environments_data: environments_folder_list_view_data, - "css-class" => container_class } } +#environments-folder-list-view{ data: { environments_data: environments_folder_list_view_data } } diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml index 3ec92676cde..2ba88da3375 100644 --- a/app/views/projects/environments/index.html.haml +++ b/app/views/projects/environments/index.html.haml @@ -1,4 +1,3 @@ -- @no_container = true - page_title _("Environments") #environments-list-view{ data: { environments_data: environments_list_data, @@ -6,5 +5,4 @@ "can-create-environment" => can?(current_user, :create_environment, @project).to_s, "new-environment-path" => new_project_environment_path(@project), "help-page-path" => help_page_path("ci/environments"), - "deploy-boards-help-path" => help_page_path("user/project/deploy_boards", anchor: "enabling-deploy-boards"), - "css-class" => container_class } } + "deploy-boards-help-path" => help_page_path("user/project/deploy_boards", anchor: "enabling-deploy-boards") } } diff --git a/app/views/projects/environments/metrics.html.haml b/app/views/projects/environments/metrics.html.haml index 7b847a85686..aab30af5ed4 100644 --- a/app/views/projects/environments/metrics.html.haml +++ b/app/views/projects/environments/metrics.html.haml @@ -1,5 +1,4 @@ -- @no_container = true - page_title _("Metrics for environment"), @environment.name -.prometheus-container{ class: container_class } +.prometheus-container #prometheus-graphs{ data: metrics_data(@project, @environment) } diff --git a/app/views/projects/environments/new.html.haml b/app/views/projects/environments/new.html.haml index c1067fdff78..96edd3f0bd7 100644 --- a/app/views/projects/environments/new.html.haml +++ b/app/views/projects/environments/new.html.haml @@ -1,9 +1,7 @@ -- @no_container = true - breadcrumb_title _("Environments") - page_title _("New Environment") -%div{ class: container_class } - %h3.page-title - = _("New environment") - %hr - = render 'form' +%h3.page-title + = _("New environment") +%hr += render 'form' diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml index 6100fd3ad37..75da151f329 100644 --- a/app/views/projects/environments/show.html.haml +++ b/app/views/projects/environments/show.html.haml @@ -1,4 +1,3 @@ -- @no_container = true - add_to_breadcrumbs _("Environments"), project_environments_path(@project) - breadcrumb_title @environment.name - page_title _("Environments") @@ -6,67 +5,66 @@ - content_for :page_specific_javascripts do = stylesheet_link_tag 'page_bundles/xterm' -%div{ class: container_class } - - if can?(current_user, :stop_environment, @environment) - #stop-environment-modal.modal.fade{ tabindex: -1 } - .modal-dialog - .modal-content - .modal-header - %h4.modal-title.d-flex.mw-100 - = s_("Environments|Stopping") - %span.has-tooltip.text-truncate.ml-1.mr-1.flex-fill{ title: @environment.name, data: { container: '#stop-environment-modal' } } - = @environment.name - ? - .modal-body - %p= s_('Environments|Are you sure you want to stop this environment?') - - unless @environment.stop_action_available? - .warning_message - %p= s_('Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action” being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file.').html_safe % { emphasis_start: '<strong>'.html_safe, - emphasis_end: '</strong>'.html_safe, - ci_config_link_start: '<a href="https://docs.gitlab.com/ee/ci/yaml/" target="_blank" rel="noopener noreferrer">'.html_safe, - ci_config_link_end: '</a>'.html_safe } - %a{ href: 'https://docs.gitlab.com/ee/ci/environments.html#stopping-an-environment', - target: '_blank', - rel: 'noopener noreferrer' } - = s_('Environments|Learn more about stopping environments') - .modal-footer - = button_tag _('Cancel'), type: 'button', class: 'btn btn-cancel', data: { dismiss: 'modal' } - = button_to stop_project_environment_path(@project, @environment), class: 'btn btn-danger has-tooltip', method: :post do - = s_('Environments|Stop environment') +- if can?(current_user, :stop_environment, @environment) + #stop-environment-modal.modal.fade{ tabindex: -1 } + .modal-dialog + .modal-content + .modal-header + %h4.modal-title.d-flex.mw-100 + = s_("Environments|Stopping") + %span.has-tooltip.text-truncate.ml-1.mr-1.flex-fill{ title: @environment.name, data: { container: '#stop-environment-modal' } } + = @environment.name + ? + .modal-body + %p= s_('Environments|Are you sure you want to stop this environment?') + - unless @environment.stop_action_available? + .warning_message + %p= s_('Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action” being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file.').html_safe % { emphasis_start: '<strong>'.html_safe, + emphasis_end: '</strong>'.html_safe, + ci_config_link_start: '<a href="https://docs.gitlab.com/ee/ci/yaml/" target="_blank" rel="noopener noreferrer">'.html_safe, + ci_config_link_end: '</a>'.html_safe } + %a{ href: 'https://docs.gitlab.com/ee/ci/environments.html#stopping-an-environment', + target: '_blank', + rel: 'noopener noreferrer' } + = s_('Environments|Learn more about stopping environments') + .modal-footer + = button_tag _('Cancel'), type: 'button', class: 'btn btn-cancel', data: { dismiss: 'modal' } + = button_to stop_project_environment_path(@project, @environment), class: 'btn btn-danger has-tooltip', method: :post do + = s_('Environments|Stop environment') - .top-area - %h3.page-title= @environment.name - .nav-controls.ml-auto.my-2 - = render 'projects/environments/terminal_button', environment: @environment - = render 'projects/environments/external_url', environment: @environment - = render 'projects/environments/metrics_button', environment: @environment - - if can?(current_user, :update_environment, @environment) - = link_to _('Edit'), edit_project_environment_path(@project, @environment), class: 'btn' - - if can?(current_user, :stop_environment, @environment) - = button_tag class: 'btn btn-danger', type: 'button', data: { toggle: 'modal', - target: '#stop-environment-modal' } do - = sprite_icon('stop') - = s_('Environments|Stop') +.top-area + %h3.page-title= @environment.name + .nav-controls.ml-auto.my-2 + = render 'projects/environments/terminal_button', environment: @environment + = render 'projects/environments/external_url', environment: @environment + = render 'projects/environments/metrics_button', environment: @environment + - if can?(current_user, :update_environment, @environment) + = link_to _('Edit'), edit_project_environment_path(@project, @environment), class: 'btn' + - if can?(current_user, :stop_environment, @environment) + = button_tag class: 'btn btn-danger', type: 'button', data: { toggle: 'modal', + target: '#stop-environment-modal' } do + = sprite_icon('stop') + = s_('Environments|Stop') - .environments-container - - if @deployments.blank? - .empty-state - .text-content - %h4.state-title - = _("You don't have any deployments right now.") - %p.blank-state-text - = _("Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here.").html_safe - .text-center - = link_to _("Read more"), help_page_path("ci/environments"), class: "btn btn-success" - - else - .table-holder - .ci-table.environments{ role: 'grid' } - .gl-responsive-table-row.table-row-header{ role: 'row' } - .table-section.section-10{ role: 'columnheader' }= _('ID') - .table-section.section-30{ role: 'columnheader' }= _('Commit') - .table-section.section-25{ role: 'columnheader' }= _('Job') - .table-section.section-15{ role: 'columnheader' }= _('Created') +.environments-container + - if @deployments.blank? + .empty-state + .text-content + %h4.state-title + = _("You don't have any deployments right now.") + %p.blank-state-text + = _("Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here.").html_safe + .text-center + = link_to _("Read more"), help_page_path("ci/environments"), class: "btn btn-success" + - else + .table-holder + .ci-table.environments{ role: 'grid' } + .gl-responsive-table-row.table-row-header{ role: 'row' } + .table-section.section-10{ role: 'columnheader' }= _('ID') + .table-section.section-30{ role: 'columnheader' }= _('Commit') + .table-section.section-25{ role: 'columnheader' }= _('Job') + .table-section.section-15{ role: 'columnheader' }= _('Created') - = render @deployments + = render @deployments - = paginate @deployments, theme: 'gitlab' + = paginate @deployments, theme: 'gitlab' diff --git a/app/views/projects/environments/terminal.html.haml b/app/views/projects/environments/terminal.html.haml index e837d3d56ac..3a705d736f3 100644 --- a/app/views/projects/environments/terminal.html.haml +++ b/app/views/projects/environments/terminal.html.haml @@ -1,23 +1,21 @@ -- @no_container = true - page_title _("Terminal for environment"), @environment.name - content_for :page_specific_javascripts do = stylesheet_link_tag "xterm.css" -%div{ class: container_class } - .top-area - .row - .col-sm-6 - %h3.page-title - = _("Terminal for environment") - = @environment.name +.top-area + .row + .col-sm-6 + %h3.page-title + = _("Terminal for environment") + = @environment.name - .col-sm-6 - .nav-controls - - if @environment.external_url.present? - = link_to @environment.external_url, class: 'btn btn-default', target: '_blank', rel: 'noopener noreferrer nofollow' do - = sprite_icon('external-link') - = render 'projects/deployments/actions', deployment: @environment.last_deployment + .col-sm-6 + .nav-controls + - if @environment.external_url.present? + = link_to @environment.external_url, class: 'btn btn-default', target: '_blank', rel: 'noopener noreferrer nofollow' do + = sprite_icon('external-link') + = render 'projects/deployments/actions', deployment: @environment.last_deployment .terminal-container{ class: container_class } #terminal{ data: { project_path: "#{terminal_project_environment_path(@project, @environment)}.ws" } } diff --git a/app/views/projects/graphs/charts.html.haml b/app/views/projects/graphs/charts.html.haml index 60160f521ad..2a2ccf8a6de 100644 --- a/app/views/projects/graphs/charts.html.haml +++ b/app/views/projects/graphs/charts.html.haml @@ -1,7 +1,6 @@ -- @no_container = true - page_title _("Contribution Charts") -.repo-charts{ class: container_class } +.repo-charts %h4.sub-header = _("Programming languages used in this repository") @@ -20,7 +19,7 @@ .col-md-8 %canvas#languages-chart{ height: 400 } -.repo-charts{ class: container_class } +.repo-charts .sub-header-block.border-top .row.tree-ref-header diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml index 4b2417ff43b..6e5e4607232 100644 --- a/app/views/projects/graphs/show.html.haml +++ b/app/views/projects/graphs/show.html.haml @@ -1,7 +1,6 @@ -- @no_container = true - page_title _('Contributors') -.js-graphs-show{ class: container_class, 'data-project-graph-path': project_graph_path(@project, current_ref, format: :json) } +.js-graphs-show{ 'data-project-graph-path': project_graph_path(@project, current_ref, format: :json) } .sub-header-block .tree-ref-holder.inline.vertical-align-middle = render 'shared/ref_switcher', destination: 'graphs' diff --git a/app/views/projects/imports/show.html.haml b/app/views/projects/imports/show.html.haml index 422a3a22f87..87b027a1802 100644 --- a/app/views/projects/imports/show.html.haml +++ b/app/views/projects/imports/show.html.haml @@ -1,5 +1,4 @@ - page_title import_in_progress_title -- @no_container = true - @content_class = "limit-container-width" unless fluid_layout .save-project-loader diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index 39e9e9171cf..49e482ff1df 100644 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -1,4 +1,3 @@ -- @no_container = true - @can_bulk_update = can?(current_user, :admin_issue, @project) - page_title "Issues" @@ -8,18 +7,17 @@ = auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{@project.name} issues") - if project_issues(@project).exists? - %div{ class: (container_class) } - .top-area - = render 'shared/issuable/nav', type: :issues - = render "projects/issues/nav_btns" - = render 'shared/issuable/search_bar', type: :issues + .top-area + = render 'shared/issuable/nav', type: :issues + = render "projects/issues/nav_btns" + = render 'shared/issuable/search_bar', type: :issues - - if @can_bulk_update - = render 'shared/issuable/bulk_update_sidebar', type: :issues + - if @can_bulk_update + = render 'shared/issuable/bulk_update_sidebar', type: :issues - .issues-holder - = render 'issues' - - if new_issue_email - = render 'projects/issuable_by_email', email: new_issue_email, issuable_type: 'issue' + .issues-holder + = render 'issues' + - if new_issue_email + = render 'projects/issuable_by_email', email: new_issue_email, issuable_type: 'issue' - else = render 'shared/empty_states/issues', button_path: new_project_issue_path(@project), show_import_button: true diff --git a/app/views/projects/jobs/index.html.haml b/app/views/projects/jobs/index.html.haml index afea5268006..5acb2af08e4 100644 --- a/app/views/projects/jobs/index.html.haml +++ b/app/views/projects/jobs/index.html.haml @@ -1,18 +1,16 @@ -- @no_container = true - page_title "Jobs" -%div{ class: container_class } - .top-area - - build_path_proc = ->(scope) { project_jobs_path(@project, scope: scope) } - = render "shared/builds/tabs", build_path_proc: build_path_proc, all_builds: @all_builds, scope: @scope +.top-area + - build_path_proc = ->(scope) { project_jobs_path(@project, scope: scope) } + = render "shared/builds/tabs", build_path_proc: build_path_proc, all_builds: @all_builds, scope: @scope - .nav-controls - - if can?(current_user, :update_build, @project) - - unless @repository.gitlab_ci_yml - = link_to 'Get started with Pipelines', help_page_path('ci/quick_start/README'), class: 'btn btn-info' + .nav-controls + - if can?(current_user, :update_build, @project) + - unless @repository.gitlab_ci_yml + = link_to 'Get started with Pipelines', help_page_path('ci/quick_start/README'), class: 'btn btn-info' - = link_to project_ci_lint_path(@project), class: 'btn btn-default' do - %span CI lint + = link_to project_ci_lint_path(@project), class: 'btn btn-default' do + %span CI lint - .content-list.builds-content-list - = render "table", builds: @builds, project: @project +.content-list.builds-content-list + = render "table", builds: @builds, project: @project diff --git a/app/views/projects/jobs/show.html.haml b/app/views/projects/jobs/show.html.haml index a3688c17041..6bb27a65142 100644 --- a/app/views/projects/jobs/show.html.haml +++ b/app/views/projects/jobs/show.html.haml @@ -1,4 +1,3 @@ -- @no_container = true - add_to_breadcrumbs _("Jobs"), project_jobs_path(@project) - breadcrumb_title "##{@build.id}" - page_title "#{@build.name} (##{@build.id})", _("Jobs") @@ -6,11 +5,10 @@ - content_for :page_specific_javascripts do = stylesheet_link_tag 'page_bundles/xterm' -%div{ class: container_class } - #js-job-vue-app{ data: { endpoint: project_job_path(@project, @build, format: :json), project_path: @project.full_path, - deployment_help_url: help_page_path('user/project/clusters/index.html', anchor: 'troubleshooting-failed-deployment-jobs'), - runner_help_url: help_page_path('ci/runners/README.html', anchor: 'setting-maximum-job-timeout-for-a-runner'), - runner_settings_url: project_runners_path(@build.project, anchor: 'js-runners-settings'), - variables_settings_url: project_variables_path(@build.project, anchor: 'js-cicd-variables-settings'), - page_path: project_job_path(@project, @build), build_status: @build.status, build_stage: @build.stage, log_state: '', - build_options: javascript_build_options } } +#js-job-vue-app{ data: { endpoint: project_job_path(@project, @build, format: :json), project_path: @project.full_path, + deployment_help_url: help_page_path('user/project/clusters/index.html', anchor: 'troubleshooting-failed-deployment-jobs'), + runner_help_url: help_page_path('ci/runners/README.html', anchor: 'setting-maximum-job-timeout-for-a-runner'), + runner_settings_url: project_runners_path(@build.project, anchor: 'js-runners-settings'), + variables_settings_url: project_variables_path(@build.project, anchor: 'js-cicd-variables-settings'), + page_path: project_job_path(@project, @build), build_status: @build.status, build_stage: @build.stage, log_state: '', + build_options: javascript_build_options } } diff --git a/app/views/projects/jobs/terminal.html.haml b/app/views/projects/jobs/terminal.html.haml index f7e7535ee92..5439a4b5d5c 100644 --- a/app/views/projects/jobs/terminal.html.haml +++ b/app/views/projects/jobs/terminal.html.haml @@ -1,4 +1,3 @@ -- @no_container = true - add_to_breadcrumbs 'Jobs', project_jobs_path(@project) - add_to_breadcrumbs "##{@build.id}", project_job_path(@project, @build) - breadcrumb_title 'Terminal' @@ -7,5 +6,5 @@ - content_for :page_specific_javascripts do = stylesheet_link_tag "xterm.css" -.terminal-container{ class: container_class } +.terminal-container #terminal{ data: { project_path: terminal_project_job_path(@project, @build, format: :ws) } } diff --git a/app/views/projects/labels/edit.html.haml b/app/views/projects/labels/edit.html.haml index b9d45e83032..b7996f0dad1 100644 --- a/app/views/projects/labels/edit.html.haml +++ b/app/views/projects/labels/edit.html.haml @@ -1,10 +1,8 @@ -- @no_container = true - add_to_breadcrumbs "Labels", project_labels_path(@project) - breadcrumb_title "Edit" - page_title "Edit", @label.name, "Labels" -%div{ class: container_class } - %h3.page-title - Edit Label - %hr - = render 'shared/labels/form', url: project_label_path(@project, @label), back_path: project_labels_path(@project) +%h3.page-title + Edit Label +%hr += render 'shared/labels/form', url: project_label_path(@project, @label), back_path: project_labels_path(@project) diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml index 511d7a82d1b..0328751c68c 100644 --- a/app/views/projects/labels/index.html.haml +++ b/app/views/projects/labels/index.html.haml @@ -1,4 +1,3 @@ -- @no_container = true - page_title "Labels" - can_admin_label = can?(current_user, :admin_label, @project) - search = params[:search] @@ -7,48 +6,47 @@ - if labels_or_filters #promote-label-modal - %div{ class: container_class } - = render 'shared/labels/nav', labels_or_filters: labels_or_filters, can_admin_label: can_admin_label + = render 'shared/labels/nav', labels_or_filters: labels_or_filters, can_admin_label: can_admin_label - .labels-container.prepend-top-10 - - if can_admin_label && search.blank? - %p.text-muted - = _('Labels can be applied to issues and merge requests.') - %br - = _('Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging.') + .labels-container.prepend-top-10 + - if can_admin_label && search.blank? + %p.text-muted + = _('Labels can be applied to issues and merge requests.') + %br + = _('Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging.') - -# Only show it in the first page - - hide = @available_labels.empty? || (params[:page].present? && params[:page] != '1') - .prioritized-labels{ class: [('hide' if hide), ('is-not-draggable' unless can_admin_label)] } - %h5.prepend-top-10= _('Prioritized Labels') - .content-list.manage-labels-list.js-prioritized-labels{ data: { url: set_priorities_project_labels_path(@project), sortable: can_admin_label } } - #js-priority-labels-empty-state.priority-labels-empty-state{ class: "#{'hidden' unless @prioritized_labels.empty? && search.blank?}" } - = render 'shared/empty_states/priority_labels' - - if @prioritized_labels.present? - = render partial: 'shared/label', collection: @prioritized_labels, as: :label, locals: { force_priority: true, subject: @project } - - elsif search.present? - .nothing-here-block - = _('No prioritised labels with such name or description') + -# Only show it in the first page + - hide = @available_labels.empty? || (params[:page].present? && params[:page] != '1') + .prioritized-labels{ class: [('hide' if hide), ('is-not-draggable' unless can_admin_label)] } + %h5.prepend-top-10= _('Prioritized Labels') + .content-list.manage-labels-list.js-prioritized-labels{ data: { url: set_priorities_project_labels_path(@project), sortable: can_admin_label } } + #js-priority-labels-empty-state.priority-labels-empty-state{ class: "#{'hidden' unless @prioritized_labels.empty? && search.blank?}" } + = render 'shared/empty_states/priority_labels' + - if @prioritized_labels.present? + = render partial: 'shared/label', collection: @prioritized_labels, as: :label, locals: { force_priority: true, subject: @project } + - elsif search.present? + .nothing-here-block + = _('No prioritised labels with such name or description') - - if @labels.present? - .other-labels - %h5{ class: ('hide' if hide) }= _('Other Labels') - .content-list.manage-labels-list.js-other-labels - = render partial: 'shared/label', collection: @labels, as: :label, locals: { subject: @project } - = paginate @labels, theme: 'gitlab' - - elsif search.present? - .other-labels - - if @available_labels.any? - %h5 - = _('Other Labels') - .nothing-here-block - = _('No other labels with such name or description') - - else - .nothing-here-block - = _('No labels with such name or description') - - elsif subscribed.present? - .nothing-here-block - = _('You do not have any subscriptions yet') + - if @labels.present? + .other-labels + %h5{ class: ('hide' if hide) }= _('Other Labels') + .content-list.manage-labels-list.js-other-labels + = render partial: 'shared/label', collection: @labels, as: :label, locals: { subject: @project } + = paginate @labels, theme: 'gitlab' + - elsif search.present? + .other-labels + - if @available_labels.any? + %h5 + = _('Other Labels') + .nothing-here-block + = _('No other labels with such name or description') + - else + .nothing-here-block + = _('No labels with such name or description') + - elsif subscribed.present? + .nothing-here-block + = _('You do not have any subscriptions yet') - else = render 'shared/empty_states/labels' diff --git a/app/views/projects/labels/new.html.haml b/app/views/projects/labels/new.html.haml index c6739231e36..96ce0eba2c6 100644 --- a/app/views/projects/labels/new.html.haml +++ b/app/views/projects/labels/new.html.haml @@ -1,10 +1,8 @@ -- @no_container = true - add_to_breadcrumbs "Labels", project_labels_path(@project) - breadcrumb_title "New" - page_title "New Label" -%div{ class: container_class } - %h3.page-title - New Label - %hr - = render 'shared/labels/form', url: project_labels_path(@project), back_path: project_labels_path(@project) +%h3.page-title + New Label +%hr += render 'shared/labels/form', url: project_labels_path(@project), back_path: project_labels_path(@project) diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml index 623380c9c61..4e30f09b9a2 100644 --- a/app/views/projects/merge_requests/index.html.haml +++ b/app/views/projects/merge_requests/index.html.haml @@ -1,4 +1,3 @@ -- @no_container = true - @can_bulk_update = can?(current_user, :admin_merge_request, @project) - merge_project = merge_request_source_project_for_project(@project) - new_merge_request_path = project_new_merge_request_path(merge_project) if merge_project @@ -6,24 +5,22 @@ - page_title "Merge Requests" - new_merge_request_email = @project.new_issuable_address(current_user, 'merge_request') -%div{ class: container_class } - = render 'projects/last_push' += render 'projects/last_push' - if @project.merge_requests.exists? - %div{ class: container_class } - .top-area - = render 'shared/issuable/nav', type: :merge_requests - .nav-controls - = render "projects/merge_requests/nav_btns", merge_project: merge_project, new_merge_request_path: new_merge_request_path + .top-area + = render 'shared/issuable/nav', type: :merge_requests + .nav-controls + = render "projects/merge_requests/nav_btns", merge_project: merge_project, new_merge_request_path: new_merge_request_path - = render 'shared/issuable/search_bar', type: :merge_requests + = render 'shared/issuable/search_bar', type: :merge_requests - - if @can_bulk_update - = render 'shared/issuable/bulk_update_sidebar', type: :merge_requests + - if @can_bulk_update + = render 'shared/issuable/bulk_update_sidebar', type: :merge_requests - .merge-requests-holder - = render 'merge_requests' - - if new_merge_request_email - = render 'projects/issuable_by_email', email: new_merge_request_email, issuable_type: 'merge_request' + .merge-requests-holder + = render 'merge_requests' + - if new_merge_request_email + = render 'projects/issuable_by_email', email: new_merge_request_email, issuable_type: 'merge_request' - else = render 'shared/empty_states/merge_requests', button_path: new_merge_request_path diff --git a/app/views/projects/milestones/_deprecation_message.html.haml b/app/views/projects/milestones/_deprecation_message.html.haml deleted file mode 100644 index b2cca3690d6..00000000000 --- a/app/views/projects/milestones/_deprecation_message.html.haml +++ /dev/null @@ -1,7 +0,0 @@ -.banner-callout.compact.milestone-deprecation-message.prepend-top-20 - .banner-graphic= image_tag 'illustrations/milestone_removing-page.svg' - .banner-body.prepend-left-10.append-right-10 - %h5.banner-title.prepend-top-0 - = _('The tabs below will be removed in a future version') - %p.milestone-banner-text - = _('Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}.').html_safe % { issue_boards_url: link_to(_('issue boards'), help_page_url('user/project/issue_board'), target: '_blank', rel: 'noopener noreferrer'), gitlab_issues_url: link_to(_('GitLab’s issue tracker'), 'https://gitlab.com/gitlab-org/gitlab-ce/issues', target: '_blank', rel: 'noopener noreferrer') } diff --git a/app/views/projects/milestones/edit.html.haml b/app/views/projects/milestones/edit.html.haml index aa564e00af9..0d040a5cdb3 100644 --- a/app/views/projects/milestones/edit.html.haml +++ b/app/views/projects/milestones/edit.html.haml @@ -1,14 +1,10 @@ -- @no_container = true - breadcrumb_title _('Edit') - add_to_breadcrumbs _('Milestones'), project_milestones_path(@project) - page_title _('Edit'), @milestone.title, _('Milestones') +%h3.page-title + = _('Edit Milestone') -%div{ class: container_class } +%hr - %h3.page-title - = _('Edit Milestone') - - %hr - - = render 'form' += render 'form' diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml index a3414c16d73..c89566dac90 100644 --- a/app/views/projects/milestones/index.html.haml +++ b/app/views/projects/milestones/index.html.haml @@ -1,26 +1,24 @@ -- @no_container = true - page_title _('Milestones') -%div{ class: container_class } - .top-area - = render 'shared/milestones_filter', counts: milestone_counts(@project.milestones) +.top-area + = render 'shared/milestones_filter', counts: milestone_counts(@project.milestones) - .nav-controls - = render 'shared/milestones/search_form' - = render 'shared/milestones_sort_dropdown' - - if can?(current_user, :admin_milestone, @project) - = link_to new_project_milestone_path(@project), class: 'btn btn-success qa-new-project-milestone', title: _('New milestone') do - = _('New milestone') + .nav-controls + = render 'shared/milestones/search_form' + = render 'shared/milestones_sort_dropdown' + - if can?(current_user, :admin_milestone, @project) + = link_to new_project_milestone_path(@project), class: 'btn btn-success qa-new-project-milestone', title: _('New milestone') do + = _('New milestone') - .milestones - #delete-milestone-modal - #promote-milestone-modal +.milestones + #delete-milestone-modal + #promote-milestone-modal - %ul.content-list - = render @milestones + %ul.content-list + = render @milestones - - if @milestones.blank? - %li - .nothing-here-block= _('No milestones to show') + - if @milestones.blank? + %li + .nothing-here-block= _('No milestones to show') - = paginate @milestones, theme: 'gitlab' + = paginate @milestones, theme: 'gitlab' diff --git a/app/views/projects/milestones/new.html.haml b/app/views/projects/milestones/new.html.haml index 79207fd70b5..721506a2201 100644 --- a/app/views/projects/milestones/new.html.haml +++ b/app/views/projects/milestones/new.html.haml @@ -1,12 +1,10 @@ -- @no_container = true - add_to_breadcrumbs _('Milestones'), project_milestones_path(@project) - breadcrumb_title _('New') - page_title _('New Milestone') -%div{ class: container_class } - %h3.page-title - = _('New Milestone') +%h3.page-title + = _('New Milestone') - %hr +%hr - = render 'form' += render 'form' diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml index 1cee8be604a..49d3039d0c9 100644 --- a/app/views/projects/milestones/show.html.haml +++ b/app/views/projects/milestones/show.html.haml @@ -1,71 +1,68 @@ -- @no_container = true - add_to_breadcrumbs _('Milestones'), project_milestones_path(@project) - breadcrumb_title @milestone.title - page_title @milestone.title, _('Milestones') - page_description @milestone.description -%div{ class: container_class } - .detail-page-header.milestone-page-header - .status-box{ class: status_box_class(@milestone) } - - if @milestone.closed? - = _('Closed') - - elsif @milestone.expired? - = _('Past due') - - elsif @milestone.upcoming? - = _('Upcoming') - - else - = _('Open') - .header-text-content - %span.identifier - %strong - = _('Milestone') - - if @milestone.due_date || @milestone.start_date - = milestone_date_range(@milestone) - .milestone-buttons - - if can?(current_user, :admin_milestone, @project) - = link_to edit_project_milestone_path(@project, @milestone), class: 'btn btn-grouped btn-nr' do - = _('Edit') +.detail-page-header.milestone-page-header + .status-box{ class: status_box_class(@milestone) } + - if @milestone.closed? + = _('Closed') + - elsif @milestone.expired? + = _('Past due') + - elsif @milestone.upcoming? + = _('Upcoming') + - else + = _('Open') + .header-text-content + %span.identifier + %strong + = _('Milestone') + - if @milestone.due_date || @milestone.start_date + = milestone_date_range(@milestone) + .milestone-buttons + - if can?(current_user, :admin_milestone, @project) + = link_to edit_project_milestone_path(@project, @milestone), class: 'btn btn-grouped btn-nr' do + = _('Edit') - - if @project.group - %button.js-promote-project-milestone-button.btn.btn-grouped{ data: { toggle: 'modal', - target: '#promote-milestone-modal', - milestone_title: @milestone.title, - group_name: @project.group.name, - url: promote_project_milestone_path(@milestone.project, @milestone), - container: 'body' }, - disabled: true, - type: 'button' } - = _('Promote') - #promote-milestone-modal + - if @project.group + %button.js-promote-project-milestone-button.btn.btn-grouped{ data: { toggle: 'modal', + target: '#promote-milestone-modal', + milestone_title: @milestone.title, + group_name: @project.group.name, + url: promote_project_milestone_path(@milestone.project, @milestone), + container: 'body' }, + disabled: true, + type: 'button' } + = _('Promote') + #promote-milestone-modal - - if @milestone.active? - = link_to _('Close milestone'), project_milestone_path(@project, @milestone, milestone: {state_event: :close }), method: :put, class: 'btn btn-close btn-nr btn-grouped' - - else - = link_to _('Reopen milestone'), project_milestone_path(@project, @milestone, milestone: {state_event: :activate }), method: :put, class: 'btn btn-reopen btn-nr btn-grouped' + - if @milestone.active? + = link_to _('Close milestone'), project_milestone_path(@project, @milestone, milestone: {state_event: :close }), method: :put, class: 'btn btn-close btn-nr btn-grouped' + - else + = link_to _('Reopen milestone'), project_milestone_path(@project, @milestone, milestone: {state_event: :activate }), method: :put, class: 'btn btn-reopen btn-nr btn-grouped' - = render 'shared/milestones/delete_button' + = render 'shared/milestones/delete_button' - %a.btn.btn-default.btn-grouped.float-right.d-block.d-sm-none.js-sidebar-toggle{ href: '#' } - = icon('angle-double-left') + %a.btn.btn-default.btn-grouped.float-right.d-block.d-sm-none.js-sidebar-toggle{ href: '#' } + = icon('angle-double-left') - .detail-page-description.milestone-detail - %h2.title.qa-milestone-title - = markdown_field(@milestone, :title) +.detail-page-description.milestone-detail + %h2.title.qa-milestone-title + = markdown_field(@milestone, :title) - %div - - if @milestone.description.present? - .description.md - = markdown_field(@milestone, :description) + %div + - if @milestone.description.present? + .description.md + = markdown_field(@milestone, :description) - = render_if_exists 'shared/milestones/burndown', milestone: @milestone, project: @project += render_if_exists 'shared/milestones/burndown', milestone: @milestone, project: @project - - if can?(current_user, :read_issue, @project) && @milestone.total_issues_count(current_user).zero? - .alert.alert-success.prepend-top-default - %span= _('Assign some issues to this milestone.') - - elsif @milestone.complete?(current_user) && @milestone.active? - .alert.alert-success.prepend-top-default - %span= _('All issues for this milestone are closed. You may close this milestone now.') +- if can?(current_user, :read_issue, @project) && @milestone.total_issues_count(current_user).zero? + .alert.alert-success.prepend-top-default + %span= _('Assign some issues to this milestone.') +- elsif @milestone.complete?(current_user) && @milestone.active? + .alert.alert-success.prepend-top-default + %span= _('All issues for this milestone are closed. You may close this milestone now.') - = render 'deprecation_message' - = render 'shared/milestones/tabs', milestone: @milestone - = render 'shared/milestones/sidebar', milestone: @milestone, project: @project, affix_offset: 153 += render 'shared/milestones/tabs', milestone: @milestone += render 'shared/milestones/sidebar', milestone: @milestone, project: @project, affix_offset: 153 diff --git a/app/views/projects/network/_head.html.haml b/app/views/projects/network/_head.html.haml index f08526f485e..701cb37a1c8 100644 --- a/app/views/projects/network/_head.html.haml +++ b/app/views/projects/network/_head.html.haml @@ -1,9 +1,6 @@ -- @no_container = true +.row-content-block.second-block.content-component-block + .tree-ref-holder + = render partial: 'shared/ref_switcher', locals: {destination: 'graph'} -%div{ class: container_class } - .row-content-block.second-block.content-component-block - .tree-ref-holder - = render partial: 'shared/ref_switcher', locals: {destination: 'graph'} - - .oneline - = _("You can move around the graph by using the arrow keys.") + .oneline + = _("You can move around the graph by using the arrow keys.") diff --git a/app/views/projects/pipeline_schedules/index.html.haml b/app/views/projects/pipeline_schedules/index.html.haml index 0580c15ad15..4a0be9e67cb 100644 --- a/app/views/projects/pipeline_schedules/index.html.haml +++ b/app/views/projects/pipeline_schedules/index.html.haml @@ -1,22 +1,20 @@ - breadcrumb_title _("Schedules") -- @no_container = true - page_title _("Pipeline Schedules") -%div{ class: container_class } - #pipeline-schedules-callout{ data: { docs_url: help_page_path('user/project/pipelines/schedules') } } - .top-area - - schedule_path_proc = ->(scope) { pipeline_schedules_path(@project, scope: scope) } - = render "tabs", schedule_path_proc: schedule_path_proc, all_schedules: @all_schedules, scope: @scope +#pipeline-schedules-callout{ data: { docs_url: help_page_path('user/project/pipelines/schedules') } } +.top-area + - schedule_path_proc = ->(scope) { pipeline_schedules_path(@project, scope: scope) } + = render "tabs", schedule_path_proc: schedule_path_proc, all_schedules: @all_schedules, scope: @scope - - if can?(current_user, :create_pipeline_schedule, @project) - .nav-controls - = link_to new_project_pipeline_schedule_path(@project), class: 'btn btn-success' do - %span= _('New schedule') + - if can?(current_user, :create_pipeline_schedule, @project) + .nav-controls + = link_to new_project_pipeline_schedule_path(@project), class: 'btn btn-success' do + %span= _('New schedule') - - if @schedules.present? - %ul.content-list - = render partial: "table" - - else - .card.bg-light - .nothing-here-block= _("No schedules") +- if @schedules.present? + %ul.content-list + = render partial: "table" +- else + .card.bg-light + .nothing-here-block= _("No schedules") diff --git a/app/views/projects/pipelines/charts.html.haml b/app/views/projects/pipelines/charts.html.haml index 6b4110e07d2..c9a50b97fea 100644 --- a/app/views/projects/pipelines/charts.html.haml +++ b/app/views/projects/pipelines/charts.html.haml @@ -1,10 +1,6 @@ -- @no_container = true - page_title _('CI / CD Charts') -%div{ class: container_class } - - #charts.ci-charts - = render 'projects/pipelines/charts/overall' - - %hr - = render 'projects/pipelines/charts/pipelines' +#charts.ci-charts + = render 'projects/pipelines/charts/overall' + %hr + = render 'projects/pipelines/charts/pipelines' diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml index 4e4638085fd..f64f07487fd 100644 --- a/app/views/projects/pipelines/index.html.haml +++ b/app/views/projects/pipelines/index.html.haml @@ -1,17 +1,15 @@ -- @no_container = true - page_title _('Pipelines') = render_if_exists "shared/shared_runners_minutes_limit_flash_message" -%div{ 'class' => container_class } - #pipelines-list-vue{ data: { endpoint: project_pipelines_path(@project, format: :json), - "help-page-path" => help_page_path('ci/quick_start/README'), - "help-auto-devops-path" => help_page_path('topics/autodevops/index.md'), - "empty-state-svg-path" => image_path('illustrations/pipelines_empty.svg'), - "error-state-svg-path" => image_path('illustrations/pipelines_failed.svg'), - "no-pipelines-svg-path" => image_path('illustrations/pipelines_pending.svg'), - "can-create-pipeline" => can?(current_user, :create_pipeline, @project).to_s, - "new-pipeline-path" => can?(current_user, :create_pipeline, @project) && new_project_pipeline_path(@project), - "ci-lint-path" => can?(current_user, :create_pipeline, @project) && project_ci_lint_path(@project), - "reset-cache-path" => can?(current_user, :admin_pipeline, @project) && reset_cache_project_settings_ci_cd_path(@project) , - "has-gitlab-ci" => (@project.has_ci? && @project.builds_enabled?).to_s } } +#pipelines-list-vue{ data: { endpoint: project_pipelines_path(@project, format: :json), + "help-page-path" => help_page_path('ci/quick_start/README'), + "help-auto-devops-path" => help_page_path('topics/autodevops/index.md'), + "empty-state-svg-path" => image_path('illustrations/pipelines_empty.svg'), + "error-state-svg-path" => image_path('illustrations/pipelines_failed.svg'), + "no-pipelines-svg-path" => image_path('illustrations/pipelines_pending.svg'), + "can-create-pipeline" => can?(current_user, :create_pipeline, @project).to_s, + "new-pipeline-path" => can?(current_user, :create_pipeline, @project) && new_project_pipeline_path(@project), + "ci-lint-path" => can?(current_user, :create_pipeline, @project) && project_ci_lint_path(@project), + "reset-cache-path" => can?(current_user, :admin_pipeline, @project) && reset_cache_project_settings_ci_cd_path(@project) , + "has-gitlab-ci" => (@project.has_ci? && @project.builds_enabled?).to_s } } diff --git a/app/views/projects/pipelines/show.html.haml b/app/views/projects/pipelines/show.html.haml index 8a6d7b082e3..2b2133b8296 100644 --- a/app/views/projects/pipelines/show.html.haml +++ b/app/views/projects/pipelines/show.html.haml @@ -1,9 +1,8 @@ -- @no_container = true - add_to_breadcrumbs _('Pipelines'), project_pipelines_path(@project) - breadcrumb_title "##{@pipeline.id}" - page_title _('Pipeline') -.js-pipeline-container{ class: container_class, data: { controller_action: "#{controller.action_name}" } } +.js-pipeline-container{ data: { controller_action: "#{controller.action_name}" } } #js-pipeline-header-vue.pipeline-header-container - if @pipeline.commit.present? diff --git a/app/views/projects/project_templates/_built_in_templates.html.haml b/app/views/projects/project_templates/_built_in_templates.html.haml index d1c09e83fd3..a583eb39eb3 100644 --- a/app/views/projects/project_templates/_built_in_templates.html.haml +++ b/app/views/projects/project_templates/_built_in_templates.html.haml @@ -1,5 +1,5 @@ - Gitlab::ProjectTemplate.all.each do |template| - .template-option.d-flex.align-items-center + .template-option.d-flex.align-items-center{ data: { qa_selector: 'template_option_row' } } .logo.append-right-10.px-1 = image_tag template.logo, size: 32, class: "btn-template-icon icon-#{template.name}" .description @@ -13,5 +13,5 @@ = _("Preview") %label.btn.btn-success.template-button.choose-template.append-bottom-0{ for: template.name } %input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: template.name, value: template.name, data: { track_label: "template_use", track_property: template.name, track_event: "click_button", track_value: "" } } - %span + %span{ data: { qa_selector: 'use_template_button' } } = _("Use template") diff --git a/app/views/projects/releases/index.html.haml b/app/views/projects/releases/index.html.haml index 28bb4e032eb..326b83c856e 100644 --- a/app/views/projects/releases/index.html.haml +++ b/app/views/projects/releases/index.html.haml @@ -1,5 +1,3 @@ -- @no_container = true - page_title _('Releases') -%div{ class: container_class } - #js-releases-page{ data: { project_id: @project.id, illustration_path: image_path('illustrations/releases.svg'), documentation_path: help_page_path('user/project/releases/index') } } +#js-releases-page{ data: { project_id: @project.id, illustration_path: image_path('illustrations/releases.svg'), documentation_path: help_page_path('user/project/releases/index') } } diff --git a/app/views/projects/serverless/functions/index.html.haml b/app/views/projects/serverless/functions/index.html.haml index bac6c76684b..09f4e556949 100644 --- a/app/views/projects/serverless/functions/index.html.haml +++ b/app/views/projects/serverless/functions/index.html.haml @@ -1,4 +1,3 @@ -- @no_container = true - @content_class = "limit-container-width" unless fluid_layout - breadcrumb_title 'Serverless' - page_title 'Serverless' @@ -10,7 +9,7 @@ clusters_path: clusters_path, help_path: help_page_path('user/project/clusters/serverless/index') } } -%div{ class: [container_class, ('limit-container-width' unless fluid_layout)] } +%div{ class: [('limit-container-width' unless fluid_layout)] } .js-serverless-functions-notice .flash-container diff --git a/app/views/projects/serverless/functions/show.html.haml b/app/views/projects/serverless/functions/show.html.haml index d1fe208ce60..79bb943d6ed 100644 --- a/app/views/projects/serverless/functions/show.html.haml +++ b/app/views/projects/serverless/functions/show.html.haml @@ -1,4 +1,3 @@ -- @no_container = true - @content_class = "limit-container-width" unless fluid_layout - clusters_path = project_clusters_path(@project) - help_path = help_page_path('user/project/clusters/serverless/index') @@ -12,7 +11,7 @@ clusters_path: clusters_path, help_path: help_path } } -%div{ class: [container_class, ('limit-container-width' unless fluid_layout)] } +%div{ class: [('limit-container-width' unless fluid_layout)] } .serverless-function-details#js-serverless-function-details .js-serverless-function-notice diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index c87a084740b..b58af545439 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -1,4 +1,3 @@ -- @no_container = true - breadcrumb_title _("Details") - @content_class = "limit-container-width" unless fluid_layout @@ -11,7 +10,7 @@ - signatures_path = project_signatures_path(@project, @project.default_branch) .js-signature-container{ data: { 'signatures-path': signatures_path } } -%div{ class: [container_class, ("limit-container-width" unless fluid_layout)] } +%div{ class: [("limit-container-width" unless fluid_layout)] } = render "projects/last_push" = render "home_panel" diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml index 1f0de1e2603..6ad7cf1848f 100644 --- a/app/views/projects/tags/index.html.haml +++ b/app/views/projects/tags/index.html.haml @@ -1,10 +1,9 @@ -- @no_container = true - @sort ||= sort_value_recently_updated - page_title s_('TagsPage|Tags') = content_for :meta_tags do = auto_discovery_link_tag(:atom, project_tags_url(@project, rss_url_options), title: "#{@project.name} tags") -.flex-list{ class: container_class } +.flex-list .top-area.adjust .nav-text.row-main-content = s_('TagsPage|Tags give the ability to mark specific points in history as being important') diff --git a/app/views/projects/tags/releases/edit.html.haml b/app/views/projects/tags/releases/edit.html.haml index e4efeed04f0..40d886ff1af 100644 --- a/app/views/projects/tags/releases/edit.html.haml +++ b/app/views/projects/tags/releases/edit.html.haml @@ -1,22 +1,19 @@ -- @no_container = true - add_to_breadcrumbs "Tags", project_tags_path(@project) - breadcrumb_title @tag.name - page_title "Edit", @tag.name, "Tags" -%div{ class: container_class } - .sub-header-block.no-bottom-space - .oneline - .title - Release notes for tag - %strong= @tag.name +.sub-header-block.no-bottom-space + .oneline + .title + Release notes for tag + %strong= @tag.name - - = form_for(@release, method: :put, url: project_tag_release_path(@project, @tag.name), - html: { class: 'common-note-form release-form js-quick-submit' }) do |f| - = render layout: 'projects/md_preview', locals: { url: preview_markdown_path(@project), referenced_users: true } do - = render 'projects/zen', f: f, attr: :description, classes: 'note-textarea', placeholder: "Write your release notes or drag files here…" - = render 'shared/notes/hints' - .error-alert - .prepend-top-default - = f.submit 'Save changes', class: 'btn btn-success' - = link_to "Cancel", project_tag_path(@project, @tag.name), class: "btn btn-default btn-cancel" += form_for(@release, method: :put, url: project_tag_release_path(@project, @tag.name), + html: { class: 'common-note-form release-form js-quick-submit' }) do |f| + = render layout: 'projects/md_preview', locals: { url: preview_markdown_path(@project), referenced_users: true } do + = render 'projects/zen', f: f, attr: :description, classes: 'note-textarea', placeholder: "Write your release notes or drag files here…" + = render 'shared/notes/hints' + .error-alert + .prepend-top-default + = f.submit 'Save changes', class: 'btn btn-success' + = link_to "Cancel", project_tag_path(@project, @tag.name), class: "btn btn-default btn-cancel" diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml index 78cce58938e..417cd7a8fee 100644 --- a/app/views/projects/tags/show.html.haml +++ b/app/views/projects/tags/show.html.haml @@ -1,45 +1,43 @@ -- @no_container = true - add_to_breadcrumbs s_('TagsPage|Tags'), project_tags_path(@project) - breadcrumb_title @tag.name - page_title @tag.name, s_('TagsPage|Tags') -%div{ class: container_class } - .top-area.multi-line.flex-wrap - .nav-text - .title - %span.item-title.ref-name - = icon('tag') - = @tag.name - - if protected_tag?(@project, @tag) - %span.badge.badge-success - = s_('TagsPage|protected') - - if @commit - = render 'projects/branches/commit', commit: @commit, project: @project - - else - = s_("TagsPage|Can't find HEAD commit for this tag") +.top-area.multi-line.flex-wrap + .nav-text + .title + %span.item-title.ref-name + = icon('tag') + = @tag.name + - if protected_tag?(@project, @tag) + %span.badge.badge-success + = s_('TagsPage|protected') + - if @commit + = render 'projects/branches/commit', commit: @commit, project: @project + - else + = s_("TagsPage|Can't find HEAD commit for this tag") - .nav-controls - - if can?(current_user, :admin_tag, @project) - = link_to edit_project_tag_release_path(@project, @tag.name), class: 'btn btn-edit controls-item has-tooltip', title: s_('TagsPage|Edit release notes') do - = icon("pencil") - = link_to project_tree_path(@project, @tag.name), class: 'btn controls-item has-tooltip', title: s_('TagsPage|Browse files') do - = sprite_icon('folder-open') - = link_to project_commits_path(@project, @tag.name), class: 'btn controls-item has-tooltip', title: s_('TagsPage|Browse commits') do - = icon('history') - .btn-container.controls-item - = render 'projects/buttons/download', project: @project, ref: @tag.name - - if can?(current_user, :admin_tag, @project) - .btn-container.controls-item-full - = link_to project_tag_path(@project, @tag.name), class: "btn btn-remove remove-row has-tooltip #{protected_tag?(@project, @tag) ? 'disabled' : ''}", title: s_('TagsPage|Delete tag'), method: :delete, data: { confirm: s_('TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?') % { tag_name: @tag.name } } do - %i.fa.fa-trash-o + .nav-controls + - if can?(current_user, :admin_tag, @project) + = link_to edit_project_tag_release_path(@project, @tag.name), class: 'btn btn-edit controls-item has-tooltip', title: s_('TagsPage|Edit release notes') do + = icon("pencil") + = link_to project_tree_path(@project, @tag.name), class: 'btn controls-item has-tooltip', title: s_('TagsPage|Browse files') do + = sprite_icon('folder-open') + = link_to project_commits_path(@project, @tag.name), class: 'btn controls-item has-tooltip', title: s_('TagsPage|Browse commits') do + = icon('history') + .btn-container.controls-item + = render 'projects/buttons/download', project: @project, ref: @tag.name + - if can?(current_user, :admin_tag, @project) + .btn-container.controls-item-full + = link_to project_tag_path(@project, @tag.name), class: "btn btn-remove remove-row has-tooltip #{protected_tag?(@project, @tag) ? 'disabled' : ''}", title: s_('TagsPage|Delete tag'), method: :delete, data: { confirm: s_('TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?') % { tag_name: @tag.name } } do + %i.fa.fa-trash-o - - if @tag.message.present? - %pre.wrap - = strip_gpg_signature(@tag.message) + - if @tag.message.present? + %pre.wrap + = strip_gpg_signature(@tag.message) - .append-bottom-default.prepend-top-default - - if @release.description.present? - .description.md - = markdown_field(@release, :description) - - else - = s_('TagsPage|This tag has no release notes.') +.append-bottom-default.prepend-top-default + - if @release.description.present? + .description.md + = markdown_field(@release, :description) + - else + = s_('TagsPage|This tag has no release notes.') diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml index 9d2aee7a8bd..39b29a20df6 100644 --- a/app/views/projects/tree/show.html.haml +++ b/app/views/projects/tree/show.html.haml @@ -1,4 +1,3 @@ -- @no_container = true - breadcrumb_title _("Repository") - @content_class = "limit-container-width" unless fluid_layout - signatures_path = namespace_project_signatures_path(namespace_id: @project.namespace.full_path, project_id: @project.path, id: @last_commit) @@ -9,6 +8,5 @@ .js-signature-container{ data: { 'signatures-path': signatures_path } } -%div{ class: [(container_class), ("limit-container-width" unless fluid_layout)] } - = render 'projects/last_push' - = render 'projects/files', commit: @last_commit, project: @project, ref: @ref, content_url: project_tree_path(@project, @id) += render 'projects/last_push' += render 'projects/files', commit: @last_commit, project: @project, ref: @ref, content_url: project_tree_path(@project, @id) diff --git a/app/views/projects/wikis/pages.html.haml b/app/views/projects/wikis/pages.html.haml index 275dc5dbd23..d9dcd8f9acd 100644 --- a/app/views/projects/wikis/pages.html.haml +++ b/app/views/projects/wikis/pages.html.haml @@ -1,34 +1,32 @@ -- @no_container = true - add_to_breadcrumbs "Wiki", project_wiki_path(@project, :home) - breadcrumb_title s_("Wiki|Pages") - page_title s_("Wiki|Pages"), _("Wiki") - sort_title = wiki_sort_title(params[:sort]) -%div{ class: container_class } - .wiki-page-header.top-area.flex-column.flex-lg-row +.wiki-page-header.top-area.flex-column.flex-lg-row - .nav-text.flex-fill - %h2.wiki-page-title - = s_("Wiki|Wiki Pages") + .nav-text.flex-fill + %h2.wiki-page-title + = s_("Wiki|Wiki Pages") - .nav-controls.pb-md-3.pb-lg-0 - = link_to project_wikis_git_access_path(@project), class: 'btn' do - = icon('cloud-download') - = _("Clone repository") + .nav-controls.pb-md-3.pb-lg-0 + = link_to project_wikis_git_access_path(@project), class: 'btn' do + = icon('cloud-download') + = _("Clone repository") - .dropdown.inline.wiki-sort-dropdown + .dropdown.inline.wiki-sort-dropdown + .btn-group{ role: 'group' } .btn-group{ role: 'group' } - .btn-group{ role: 'group' } - %button.dropdown-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' }, class: 'btn btn-default' } - = sort_title - = icon('chevron-down') - %ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable.dropdown-menu-sort - %li - = sortable_item(s_("Wiki|Title"), project_wikis_pages_path(@project, sort: ProjectWiki::TITLE_ORDER), sort_title) - = sortable_item(s_("Wiki|Created date"), project_wikis_pages_path(@project, sort: ProjectWiki::CREATED_AT_ORDER), sort_title) - = wiki_sort_controls(@project, params[:sort], params[:direction]) + %button.dropdown-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' }, class: 'btn btn-default' } + = sort_title + = icon('chevron-down') + %ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable.dropdown-menu-sort + %li + = sortable_item(s_("Wiki|Title"), project_wikis_pages_path(@project, sort: ProjectWiki::TITLE_ORDER), sort_title) + = sortable_item(s_("Wiki|Created date"), project_wikis_pages_path(@project, sort: ProjectWiki::CREATED_AT_ORDER), sort_title) + = wiki_sort_controls(@project, params[:sort], params[:direction]) - %ul.wiki-pages-list.content-list - = render @wiki_entries, context: 'pages' +%ul.wiki-pages-list.content-list + = render @wiki_entries, context: 'pages' - = paginate @wiki_pages, theme: 'gitlab' += paginate @wiki_pages, theme: 'gitlab' diff --git a/app/views/shared/issuable/_sidebar_assignees.html.haml b/app/views/shared/issuable/_sidebar_assignees.html.haml index 1dc538826dc..dfb0e7ed297 100644 --- a/app/views/shared/issuable/_sidebar_assignees.html.haml +++ b/app/views/shared/issuable/_sidebar_assignees.html.haml @@ -1,7 +1,7 @@ - issuable_type = issuable_sidebar[:type] - signed_in = !!issuable_sidebar.dig(:current_user, :id) -#js-vue-sidebar-assignees{ data: { field: "#{issuable_type}[assignee_ids]", signed_in: signed_in } } +#js-vue-sidebar-assignees{ data: { field: "#{issuable_type}", signed_in: signed_in } } .title.hide-collapsed = _('Assignee') = icon('spinner spin') diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 73bee7c2586..e1c75d5d0f4 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -1,9 +1,9 @@ - @hide_top_links = true - @hide_breadcrumbs = true +- @no_container = true - page_title @user.name - page_description @user.bio - header_title @user.name, user_path(@user) -- @no_container = true = content_for :meta_tags do = auto_discovery_link_tag(:atom, user_url(@user, format: :atom), title: "#{@user.name} activity") diff --git a/bin/rspec-stackprof b/bin/rspec-stackprof index 810863ea4a0..8058d165196 100755 --- a/bin/rspec-stackprof +++ b/bin/rspec-stackprof @@ -3,7 +3,7 @@ require 'bundler/setup' require 'stackprof' $:.unshift 'spec' -require 'rails_helper' +require 'spec_helper' filename = ARGV[0].split('/').last interval = ENV.fetch('INTERVAL', 1000).to_i diff --git a/changelogs/unreleased/36765-flash-notification.yml b/changelogs/unreleased/36765-flash-notification.yml new file mode 100644 index 00000000000..3229cf6235a --- /dev/null +++ b/changelogs/unreleased/36765-flash-notification.yml @@ -0,0 +1,5 @@ +--- +title: Make flash notifications sticky +merge_request: 30141 +author: +type: changed diff --git a/changelogs/unreleased/40096-allow-ci-token-to-delete-from-registry.yml b/changelogs/unreleased/40096-allow-ci-token-to-delete-from-registry.yml new file mode 100644 index 00000000000..3e5de08f6ae --- /dev/null +++ b/changelogs/unreleased/40096-allow-ci-token-to-delete-from-registry.yml @@ -0,0 +1,5 @@ +--- +title: Allow $CI_REGISTRY_USER to delete tags +merge_request: 31796 +author: +type: added diff --git a/changelogs/unreleased/51372-remove-milestone-tabs-deprecation-message.yml b/changelogs/unreleased/51372-remove-milestone-tabs-deprecation-message.yml new file mode 100644 index 00000000000..5f05b150b93 --- /dev/null +++ b/changelogs/unreleased/51372-remove-milestone-tabs-deprecation-message.yml @@ -0,0 +1,5 @@ +--- +title: Remove deprecation message for milestone tabs +merge_request: 32252 +author: +type: other diff --git a/changelogs/unreleased/62402-milestone-release-be.yml b/changelogs/unreleased/62402-milestone-release-be.yml new file mode 100644 index 00000000000..3b1f6edfe6b --- /dev/null +++ b/changelogs/unreleased/62402-milestone-release-be.yml @@ -0,0 +1,5 @@ +--- +title: Allow milestones to be associated with a release (backend) +merge_request: 30816 +author: +type: added diff --git a/changelogs/unreleased/62591-fix-milestone-due-date-today-wording.yml b/changelogs/unreleased/62591-fix-milestone-due-date-today-wording.yml new file mode 100644 index 00000000000..532b582f407 --- /dev/null +++ b/changelogs/unreleased/62591-fix-milestone-due-date-today-wording.yml @@ -0,0 +1,5 @@ +--- +title: Fix wording on milestone due date when milestone is due today +merge_request: 32096 +author: +type: changed diff --git a/changelogs/unreleased/65152-unfolded-lines-perf-improvement.yml b/changelogs/unreleased/65152-unfolded-lines-perf-improvement.yml new file mode 100644 index 00000000000..835ed037b83 --- /dev/null +++ b/changelogs/unreleased/65152-unfolded-lines-perf-improvement.yml @@ -0,0 +1,5 @@ +--- +title: Support selective highlighting of lines +merge_request: 32514 +author: +type: performance diff --git a/changelogs/unreleased/66066-dark-theme-style-for-expansion-on-mr-diffs.yml b/changelogs/unreleased/66066-dark-theme-style-for-expansion-on-mr-diffs.yml deleted file mode 100644 index 13607ae938a..00000000000 --- a/changelogs/unreleased/66066-dark-theme-style-for-expansion-on-mr-diffs.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Add syntax highlighting for line expansion -merge_request: 31821 -author: -type: fixed diff --git a/changelogs/unreleased/66454-utils-parser.yml b/changelogs/unreleased/66454-utils-parser.yml new file mode 100644 index 00000000000..80cd699937f --- /dev/null +++ b/changelogs/unreleased/66454-utils-parser.yml @@ -0,0 +1,5 @@ +--- +title: Creates utility parser for the job log +merge_request: 32555 +author: +type: added diff --git a/changelogs/unreleased/ab-admin-page-user-active-count.yml b/changelogs/unreleased/ab-admin-page-user-active-count.yml new file mode 100644 index 00000000000..e08715a1586 --- /dev/null +++ b/changelogs/unreleased/ab-admin-page-user-active-count.yml @@ -0,0 +1,5 @@ +--- +title: Replace indexes for counting active users +merge_request: 32538 +author: +type: performance diff --git a/changelogs/unreleased/ab-remove-support-bot-column.yml b/changelogs/unreleased/ab-remove-support-bot-column.yml new file mode 100644 index 00000000000..d256ded0410 --- /dev/null +++ b/changelogs/unreleased/ab-remove-support-bot-column.yml @@ -0,0 +1,5 @@ +--- +title: Remove Users.support_bot column +merge_request: 32554 +author: +type: other diff --git a/changelogs/unreleased/ab-routable-nplus1.yml b/changelogs/unreleased/ab-routable-nplus1.yml new file mode 100644 index 00000000000..7b59bc78dae --- /dev/null +++ b/changelogs/unreleased/ab-routable-nplus1.yml @@ -0,0 +1,5 @@ +--- +title: Preload routes information to fix N+1 issue +merge_request: 32352 +author: +type: performance diff --git a/changelogs/unreleased/add-notification-reason-to-note-emails.yml b/changelogs/unreleased/add-notification-reason-to-note-emails.yml new file mode 100644 index 00000000000..c27247b22cb --- /dev/null +++ b/changelogs/unreleased/add-notification-reason-to-note-emails.yml @@ -0,0 +1,5 @@ +--- +title: Add X-GitLab-NotificationReason header to note emails +merge_request: 32422 +author: +type: fixed diff --git a/changelogs/unreleased/change-role-system-hook.yml b/changelogs/unreleased/change-role-system-hook.yml new file mode 100644 index 00000000000..adc9e43b1f2 --- /dev/null +++ b/changelogs/unreleased/change-role-system-hook.yml @@ -0,0 +1,5 @@ +--- +title: Add system hooks for project/group membership updates +merge_request: 32371 +author: Brandon Williams +type: added diff --git a/changelogs/unreleased/cluster-form-ca-cert-larger.yml b/changelogs/unreleased/cluster-form-ca-cert-larger.yml new file mode 100644 index 00000000000..ed38d003a37 --- /dev/null +++ b/changelogs/unreleased/cluster-form-ca-cert-larger.yml @@ -0,0 +1,5 @@ +--- +title: Expand textarea for CA cert in cluster form +merge_request: 32508 +author: +type: fixed diff --git a/changelogs/unreleased/fe-fix-issuable-sidebar-icon-of-notification-disabled.yml b/changelogs/unreleased/fe-fix-issuable-sidebar-icon-of-notification-disabled.yml deleted file mode 100644 index 736e12ff694..00000000000 --- a/changelogs/unreleased/fe-fix-issuable-sidebar-icon-of-notification-disabled.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix issuable sidebar icon on notification disabled -merge_request: 32134 -author: -type: fixed diff --git a/changelogs/unreleased/remove-vue-resource-from-issue.yml b/changelogs/unreleased/remove-vue-resource-from-issue.yml new file mode 100644 index 00000000000..b2de1b0913a --- /dev/null +++ b/changelogs/unreleased/remove-vue-resource-from-issue.yml @@ -0,0 +1,5 @@ +--- +title: Remove vue resource from issue +merge_request: 32421 +author: Lee Tickett +type: other diff --git a/changelogs/unreleased/remove-vue-resource-from-sidebar-service.yml b/changelogs/unreleased/remove-vue-resource-from-sidebar-service.yml new file mode 100644 index 00000000000..f86e0a4259f --- /dev/null +++ b/changelogs/unreleased/remove-vue-resource-from-sidebar-service.yml @@ -0,0 +1,5 @@ +--- +title: Remove vue resource from sidebar service +merge_request: 32400 +author: Lee Tickett +type: other diff --git a/changelogs/unreleased/sh-fix-nplusone-issues.yml b/changelogs/unreleased/sh-fix-nplusone-issues.yml deleted file mode 100644 index f749b5eeb40..00000000000 --- a/changelogs/unreleased/sh-fix-nplusone-issues.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix N+1 Gitaly calls in /api/v4/projects/:id/issues -merge_request: 32171 -author: -type: performance diff --git a/changelogs/unreleased/sh-fix-piwik-template.yml b/changelogs/unreleased/sh-fix-piwik-template.yml deleted file mode 100644 index f0baed6a2e0..00000000000 --- a/changelogs/unreleased/sh-fix-piwik-template.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix Piwik not working -merge_request: 32234 -author: -type: fixed diff --git a/changelogs/unreleased/sh-fix-snippet-visibility-api.yml b/changelogs/unreleased/sh-fix-snippet-visibility-api.yml deleted file mode 100644 index 5cfb9cdedc0..00000000000 --- a/changelogs/unreleased/sh-fix-snippet-visibility-api.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix snippets API not working with visibility level -merge_request: 32286 -author: -type: fixed diff --git a/changelogs/unreleased/sh-mermaid-8-2-6.yml b/changelogs/unreleased/sh-mermaid-8-2-6.yml deleted file mode 100644 index d5cee250385..00000000000 --- a/changelogs/unreleased/sh-mermaid-8-2-6.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Update Mermaid to v8.2.6 -merge_request: 32502 -author: -type: fixed diff --git a/changelogs/unreleased/sh-suppress-diverging-count-commits-request.yml b/changelogs/unreleased/sh-suppress-diverging-count-commits-request.yml new file mode 100644 index 00000000000..68b95ff9318 --- /dev/null +++ b/changelogs/unreleased/sh-suppress-diverging-count-commits-request.yml @@ -0,0 +1,5 @@ +--- +title: Skip requesting diverging commit counts if no branches are listed +merge_request: 32496 +author: +type: performance diff --git a/changelogs/unreleased/sh-upgrade-mermaid-8-2-4.yml b/changelogs/unreleased/sh-upgrade-mermaid-8-2-4.yml deleted file mode 100644 index bdb64e43ecf..00000000000 --- a/changelogs/unreleased/sh-upgrade-mermaid-8-2-4.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Upgrade Mermaid to v8.2.4 -merge_request: 32186 -author: -type: fixed diff --git a/changelogs/unreleased/swagger-ui-ci-page-template.yml b/changelogs/unreleased/swagger-ui-ci-page-template.yml new file mode 100644 index 00000000000..6d17baf82c8 --- /dev/null +++ b/changelogs/unreleased/swagger-ui-ci-page-template.yml @@ -0,0 +1,5 @@ +--- +title: "Add SwaggerUI Pages template for .gitlab-ci.yml" +merge_request: 31183 +author: mdhtr +type: added diff --git a/db/fixtures/development/17_cycle_analytics.rb b/db/fixtures/development/17_cycle_analytics.rb index 78ceb74da65..9d293f425e6 100644 --- a/db/fixtures/development/17_cycle_analytics.rb +++ b/db/fixtures/development/17_cycle_analytics.rb @@ -18,6 +18,7 @@ class Gitlab::Seeder::CycleAnalytics # Milestones / Labels Timecop.travel 5.days.from_now + if index.even? issue_metrics.first_associated_with_milestone_at = rand(6..12).hours.from_now else @@ -146,7 +147,7 @@ class Gitlab::Seeder::CycleAnalytics commit_sha = issue.project.repository.create_file(@user, filename, "content", message: "Commit for #{issue.to_reference}", branch_name: branch_name) issue.project.repository.commit(commit_sha) - Git::BranchPushService.new( + ::Git::BranchPushService.new( issue.project, @user, oldrev: issue.project.repository.commit("master").sha, @@ -182,7 +183,8 @@ class Gitlab::Seeder::CycleAnalytics ref: "refs/heads/#{merge_request.source_branch}") pipeline = service.execute(:push, ignore_skip_ci: true, save_on_errors: false) - pipeline.builds.map(&:run!) + pipeline.builds.each(&:enqueue) # make sure all pipelines in pending state + pipeline.builds.each(&:run!) pipeline.update_status end end diff --git a/db/migrate/20190722144316_create_milestone_releases_table.rb b/db/migrate/20190722144316_create_milestone_releases_table.rb new file mode 100644 index 00000000000..55878bcec41 --- /dev/null +++ b/db/migrate/20190722144316_create_milestone_releases_table.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class CreateMilestoneReleasesTable < ActiveRecord::Migration[5.2] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def up + create_table :milestone_releases do |t| + t.references :milestone, foreign_key: { on_delete: :cascade }, null: false, index: false + t.references :release, foreign_key: { on_delete: :cascade }, null: false + end + + add_index :milestone_releases, [:milestone_id, :release_id], unique: true, name: 'index_miletone_releases_on_milestone_and_release' + end + + def down + drop_table :milestone_releases + end +end diff --git a/db/migrate/20190828110802_add_not_null_constraints_to_prometheus_metrics_y_label_and_unit.rb b/db/migrate/20190828110802_add_not_null_constraints_to_prometheus_metrics_y_label_and_unit.rb new file mode 100644 index 00000000000..6f3650ca966 --- /dev/null +++ b/db/migrate/20190828110802_add_not_null_constraints_to_prometheus_metrics_y_label_and_unit.rb @@ -0,0 +1,8 @@ +class AddNotNullConstraintsToPrometheusMetricsYLabelAndUnit < ActiveRecord::Migration[5.2] + DOWNTIME = false + + def change + change_column_null(:prometheus_metrics, :y_label, false) + change_column_null(:prometheus_metrics, :unit, false) + end +end diff --git a/db/migrate/20190902131045_replace_indexes_for_counting_active_users.rb b/db/migrate/20190902131045_replace_indexes_for_counting_active_users.rb new file mode 100644 index 00000000000..2c7c47bee96 --- /dev/null +++ b/db/migrate/20190902131045_replace_indexes_for_counting_active_users.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class ReplaceIndexesForCountingActiveUsers < ActiveRecord::Migration[5.2] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + remove_concurrent_index_by_name(:users, 'index_users_on_state_and_internal') + + add_concurrent_index(:users, :state, where: 'ghost IS NOT TRUE', name: 'index_users_on_state_and_internal') + add_concurrent_index(:users, :state, where: 'ghost IS NOT TRUE AND bot_type IS NULL', name: 'index_users_on_state_and_internal_ee') + end + + def down + remove_concurrent_index_by_name(:users, 'index_users_on_state_and_internal_ee') + remove_concurrent_index_by_name(:users, 'index_users_on_state_and_internal') + + add_concurrent_index(:users, :state, where: 'ghost <> true AND bot_type IS NULL', name: 'index_users_on_state_and_internal') + end +end diff --git a/db/post_migrate/20190902160015_remove_support_bot_column_from_users.rb b/db/post_migrate/20190902160015_remove_support_bot_column_from_users.rb new file mode 100644 index 00000000000..80d69b57f5d --- /dev/null +++ b/db/post_migrate/20190902160015_remove_support_bot_column_from_users.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class RemoveSupportBotColumnFromUsers < ActiveRecord::Migration[5.2] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + return unless column_exists?(:users, :support_bot) + + remove_column :users, :support_bot + end + + def down + # no-op because the column should not exist in the previous version + end +end diff --git a/db/schema.rb b/db/schema.rb index 5999a859e77..0f535e4d674 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2019_08_28_083843) do +ActiveRecord::Schema.define(version: 2019_09_02_160015) do # These are extensions that must be enabled in order to support this database enable_extension "pg_trgm" @@ -2158,6 +2158,13 @@ ActiveRecord::Schema.define(version: 2019_08_28_083843) do t.index ["user_id"], name: "index_merge_trains_on_user_id" end + create_table "milestone_releases", force: :cascade do |t| + t.bigint "milestone_id", null: false + t.bigint "release_id", null: false + t.index ["milestone_id", "release_id"], name: "index_miletone_releases_on_milestone_and_release", unique: true + t.index ["release_id"], name: "index_milestone_releases_on_release_id" + end + create_table "milestones", id: :serial, force: :cascade do |t| t.string "title", null: false t.integer "project_id" @@ -2869,8 +2876,8 @@ ActiveRecord::Schema.define(version: 2019_08_28_083843) do t.integer "project_id" t.string "title", null: false t.string "query", null: false - t.string "y_label" - t.string "unit" + t.string "y_label", null: false + t.string "unit", null: false t.string "legend" t.integer "group", null: false t.datetime_with_timezone "created_at", null: false @@ -3551,7 +3558,8 @@ ActiveRecord::Schema.define(version: 2019_08_28_083843) do t.index ["public_email"], name: "index_users_on_public_email", where: "((public_email)::text <> ''::text)" t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true t.index ["state"], name: "index_users_on_state" - t.index ["state"], name: "index_users_on_state_and_internal", where: "((ghost <> true) AND (bot_type IS NULL))" + t.index ["state"], name: "index_users_on_state_and_internal", where: "(ghost IS NOT TRUE)" + t.index ["state"], name: "index_users_on_state_and_internal_ee", where: "((ghost IS NOT TRUE) AND (bot_type IS NULL))" t.index ["username"], name: "index_users_on_username" t.index ["username"], name: "index_users_on_username_trigram", opclass: :gin_trgm_ops, using: :gin end @@ -3931,6 +3939,8 @@ ActiveRecord::Schema.define(version: 2019_08_28_083843) do add_foreign_key "merge_trains", "merge_requests", on_delete: :cascade add_foreign_key "merge_trains", "projects", column: "target_project_id", on_delete: :cascade add_foreign_key "merge_trains", "users", on_delete: :cascade + add_foreign_key "milestone_releases", "milestones", on_delete: :cascade + add_foreign_key "milestone_releases", "releases", on_delete: :cascade add_foreign_key "milestones", "namespaces", column: "group_id", name: "fk_95650a40d4", on_delete: :cascade add_foreign_key "milestones", "projects", name: "fk_9bd0a0c791", on_delete: :cascade add_foreign_key "namespace_aggregation_schedules", "namespaces", on_delete: :cascade diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md index eab4b2c6eea..53b354d2f92 100644 --- a/doc/administration/gitaly/index.md +++ b/doc/administration/gitaly/index.md @@ -148,7 +148,7 @@ Check the directory layout on your Gitaly server to be sure. <!-- updates to following example must also be made at - https://gitlab.com/charts/gitlab/blob/master/doc/advanced/external-gitaly/external-omnibus-gitaly.md#configure-omnibus-gitlab + https://gitlab.com/gitlab-org/charts/gitlab/blob/master/doc/advanced/external-gitaly/external-omnibus-gitaly.md#configure-omnibus-gitlab --> ```ruby diff --git a/doc/administration/troubleshooting/kubernetes_cheat_sheet.md b/doc/administration/troubleshooting/kubernetes_cheat_sheet.md index 260af333e8e..6bcd4c48e5a 100644 --- a/doc/administration/troubleshooting/kubernetes_cheat_sheet.md +++ b/doc/administration/troubleshooting/kubernetes_cheat_sheet.md @@ -75,7 +75,7 @@ and they will assist you with any issues you are having. ## GitLab-specific kubernetes information - Minimal config that can be used to test a Kubernetes helm chart can be found - [here](https://gitlab.com/charts/gitlab/issues/620). + [here](https://gitlab.com/gitlab-org/charts/gitlab/issues/620). - Tailing logs of a separate pod. An example for a unicorn pod: @@ -176,7 +176,7 @@ and they will assist you with any issues you are having. helm upgrade <release name> <chart path> -f gitlab.yaml ``` - After <https://canary.gitlab.com/charts/gitlab/issues/780> is fixed, it should + After <https://gitlab.com/gitlab-org/charts/gitlab/issues/780> is fixed, it should be possible to use [Updating GitLab using the Helm Chart](https://docs.gitlab.com/ee/install/kubernetes/gitlab_chart.html#updating-gitlab-using-the-helm-chart) for upgrades. @@ -191,8 +191,8 @@ and they will assist you with any issues you are having. ## Installation of minimal GitLab config via Minukube on macOS -This section is based on [Developing for Kubernetes with Minikube](https://gitlab.com/charts/gitlab/blob/master/doc/minikube/index.md) -and [Helm](https://gitlab.com/charts/gitlab/blob/master/doc/helm/index.md). Refer +This section is based on [Developing for Kubernetes with Minikube](https://gitlab.com/gitlab-org/charts/gitlab/blob/master/doc/minikube/index.md) +and [Helm](https://gitlab.com/gitlab-org/charts/gitlab/blob/master/doc/helm/index.md). Refer to those documents for details. - Install Kubectl via Homebrew: @@ -223,7 +223,7 @@ to those documents for details. helm init --service-account tiller ``` -- Copy the file <https://gitlab.com/charts/gitlab/raw/master/examples/values-minikube-minimum.yaml> +- Copy the file <https://gitlab.com/gitlab-org/charts/gitlab/raw/master/examples/values-minikube-minimum.yaml> to your workstation. - Find the IP address in the output of `minikube ip` and update the yaml file with diff --git a/doc/api/releases/index.md b/doc/api/releases/index.md index 850cf57a06f..8d5b3a65789 100644 --- a/doc/api/releases/index.md +++ b/doc/api/releases/index.md @@ -57,6 +57,19 @@ Example response: "committer_email":"admin@example.com", "committed_date":"2019-01-03T01:55:38.000Z" }, + "milestone":{ + "id":51, + "iid":1, + "project_id":24, + "title":"v1.0-rc", + "description":"Voluptate fugiat possimus quis quod aliquam expedita.", + "state":"closed", + "created_at":"2019-07-12T19:45:44.256Z", + "updated_at":"2019-07-12T19:45:44.256Z", + "due_date":"2019-08-16T11:00:00.256Z", + "start_date":"2019-07-30T12:00:00.256Z", + "web_url":"http://localhost:3000/root/awesome-app/-/milestones/1" + }, "assets":{ "count":6, "sources":[ @@ -205,6 +218,19 @@ Example response: "committer_email":"admin@example.com", "committed_date":"2019-01-03T01:53:28.000Z" }, + "milestone":{ + "id":51, + "iid":1, + "project_id":24, + "title":"v1.0-rc", + "description":"Voluptate fugiat possimus quis quod aliquam expedita.", + "state":"closed", + "created_at":"2019-07-12T19:45:44.256Z", + "updated_at":"2019-07-12T19:45:44.256Z", + "due_date":"2019-08-16T11:00:00.256Z", + "start_date":"2019-07-30T12:00:00.256Z", + "web_url":"http://localhost:3000/root/awesome-app/-/milestones/1" + }, "assets":{ "count":4, "sources":[ @@ -240,23 +266,24 @@ Create a Release. You need push access to the repository to create a Release. POST /projects/:id/releases ``` -| Attribute | Type | Required | Description | -| -------------------| -------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). | -| `name` | string | yes | The release name. | -| `tag_name` | string | yes | The tag where the release will be created from. | -| `description` | string | yes | The description of the release. You can use [markdown](../../user/markdown.md). | -| `ref` | string | no | If `tag_name` doesn't exist, the release will be created from `ref`. It can be a commit SHA, another tag name, or a branch name. | -| `assets:links` | array of hash | no | An array of assets links. | -| `assets:links:name`| string | required by: `assets:links` | The name of the link. | -| `assets:links:url` | string | required by: `assets:links` | The url of the link. | -| `released_at` | datetime | no | The date when the release will be/was ready. Defaults to the current time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | +| Attribute | Type | Required | Description | +| -------------------| --------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). | +| `name` | string | yes | The release name. | +| `tag_name` | string | yes | The tag where the release will be created from. | +| `description` | string | yes | The description of the release. You can use [markdown](../../user/markdown.md). | +| `ref` | string | no | If `tag_name` doesn't exist, the release will be created from `ref`. It can be a commit SHA, another tag name, or a branch name. | +| `milestone` | string | no | The title of the milestone the release is associated with. | +| `assets:links` | array of hash | no | An array of assets links. | +| `assets:links:name`| string | required by: `assets:links` | The name of the link. | +| `assets:links:url` | string | required by: `assets:links` | The url of the link. | +| `released_at` | datetime | no | The date when the release will be/was ready. Defaults to the current time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | Example request: ```sh curl --header 'Content-Type: application/json' --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" \ - --data '{ "name": "New release", "tag_name": "v0.3", "description": "Super nice release", "assets": { "links": [{ "name": "hoge", "url": "https://google.com" }] } }' \ + --data '{ "name": "New release", "tag_name": "v0.3", "description": "Super nice release", "milestone": "v1.0-rc", "assets": { "links": [{ "name": "hoge", "url": "https://google.com" }] } }' \ --request POST https://gitlab.example.com/api/v4/projects/24/releases ``` @@ -294,6 +321,19 @@ Example response: "committer_email":"admin@example.com", "committed_date":"2019-01-03T01:55:38.000Z" }, + "milestone":{ + "id":51, + "iid":1, + "project_id":24, + "title":"v1.0-rc", + "description":"Voluptate fugiat possimus quis quod aliquam expedita.", + "state":"active", + "created_at":"2019-07-12T19:45:44.256Z", + "updated_at":"2019-07-12T19:45:44.256Z", + "due_date":"2019-08-16T11:00:00.256Z", + "start_date":"2019-07-30T12:00:00.256Z", + "web_url":"http://localhost:3000/root/awesome-app/-/milestones/1" + }, "assets":{ "count":5, "sources":[ @@ -334,18 +374,19 @@ Update a Release. PUT /projects/:id/releases/:tag_name ``` -| Attribute | Type | Required | Description | -| ------------- | -------------- | -------- | -------------------------------------------------------------------------------------------------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). | -| `tag_name` | string | yes | The tag where the release will be created from. | -| `name` | string | no | The release name. | -| `description` | string | no | The description of the release. You can use [markdown](../../user/markdown.md). | -| `released_at` | datetime | no | The date when the release will be/was ready. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | +| Attribute | Type | Required | Description | +| ------------- | -------------- | -------- | --------------------------------------------------------------------------------------------------------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). | +| `tag_name` | string | yes | The tag where the release will be created from. | +| `name` | string | no | The release name. | +| `description` | string | no | The description of the release. You can use [markdown](../../user/markdown.md). | +| `milestone` | string | no | The title of the milestone to associate with the release (`""` to remove the milestone from the release). | +| `released_at` | datetime | no | The date when the release will be/was ready. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | Example request: ```sh -curl --request PUT --data name="new name" --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1" +curl --header 'Content-Type: application/json' --request PUT --data '{"name": "new name", "milestone": "v1.0"}' --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1" ``` Example response: @@ -382,6 +423,19 @@ Example response: "committer_email":"admin@example.com", "committed_date":"2019-01-03T01:53:28.000Z" }, + "milestone":{ + "id":53, + "iid":2, + "project_id":24, + "title":"v1.0", + "description":"Voluptate fugiat possimus quis quod aliquam expedita.", + "state":"active", + "created_at":"2019-09-01T13:00:00.256Z", + "updated_at":"2019-09-01T13:00:00.256Z", + "due_date":"2019-09-20T13:00:00.256Z", + "start_date":"2019-09-05T12:00:00.256Z", + "web_url":"http://localhost:3000/root/awesome-app/-/milestones/3" + }, "assets":{ "count":4, "sources":[ diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md index 730e46f994e..a48da557e09 100644 --- a/doc/ci/docker/using_docker_build.md +++ b/doc/ci/docker/using_docker_build.md @@ -580,9 +580,10 @@ For private and internal projects: If you want to use your own Docker images for docker-in-docker there are a few things you need to do in addition to the steps in the [docker-in-docker](#use-docker-in-docker-workflow-with-docker-executor) section: 1. Update the `image` and `service` to point to your registry. -1. Add a service [alias](https://docs.gitlab.com/ee/ci/yaml/#servicesalias) +1. Add a service [alias](https://docs.gitlab.com/ee/ci/yaml/#servicesalias). -Below is an example of how your `.gitlab-ci.yml` should look like, assuming you have it configured with [TLS enabled](#tls-enabled): +Below is an example of what your `.gitlab-ci.yml` should look like, +assuming you have it configured with [TLS enabled](#tls-enabled): ```yaml build: @@ -603,7 +604,7 @@ Below is an example of how your `.gitlab-ci.yml` should look like, assuming you - docker run my-docker-image /script/to/run/tests ``` -If you forget to set the service alias the `docker:19.03.1` image won't find the +If you forget to set the service alias, the `docker:19.03.1` image won't find the `dind` service, and an error like the following is thrown: ```sh diff --git a/doc/ci/multi_project_pipelines.md b/doc/ci/multi_project_pipelines.md index 61f260cb70d..377ae9717b2 100644 --- a/doc/ci/multi_project_pipelines.md +++ b/doc/ci/multi_project_pipelines.md @@ -176,6 +176,18 @@ Upstream pipelines take precedence over downstream ones. If there are two variables with the same name defined in both upstream and downstream projects, the ones defined in the upstream project will take precedence. +### Mirroring status from triggered pipeline + +You can mirror the pipeline status from the triggered pipeline to the source +bridge job by using `strategy: depend`. For example: + +```yaml +trigger_job: + trigger: + project: my/project + strategy: depend +``` + ### Mirroring status from upstream pipeline You can mirror the pipeline status from an upstream pipeline to a bridge job by diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index 06bd9e68a18..bfba21646b5 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -100,7 +100,7 @@ The following table lists available parameters for jobs: | [`stage`](#stage) | Defines a job stage (default: `test`). | | [`only`](#onlyexcept-basic) | Limit when jobs are created. Also available: [`only:refs`, `only:kubernetes`, `only:variables`, and `only:changes`](#onlyexcept-advanced). | | [`except`](#onlyexcept-basic) | Limit when jobs are not created. Also available: [`except:refs`, `except:kubernetes`, `except:variables`, and `except:changes`](#onlyexcept-advanced). | -| [`rules`](#rules) | List of conditions to evaluate and determine selected attributes of a build and whether or not it is created. May not be used alongside `only`/`except`. +| [`rules`](#rules) | List of conditions to evaluate and determine selected attributes of a job, and whether or not it is created. May not be used alongside `only`/`except`. | | [`tags`](#tags) | List of tags which are used to select Runner. | | [`allow_failure`](#allow_failure) | Allow job to fail. Failed job doesn't contribute to commit status. | | [`when`](#when) | When to run job. Also available: `when:manual` and `when:delayed`. | @@ -113,7 +113,7 @@ The following table lists available parameters for jobs: | [`parallel`](#parallel) | How many instances of a job should be run in parallel. | | [`trigger`](#trigger-premium) | Defines a downstream pipeline trigger. | | [`include`](#include) | Allows this job to include external YAML files. Also available: `include:local`, `include:file`, `include:template`, and `include:remote`. | -| [`extends`](#extends) | Configuration entries that this job is going to inherit from. | +| [`extends`](#extends) | Configuration entries that this job is going to inherit from. | | [`pages`](#pages) | Upload the result of a job to use with GitLab Pages. | | [`variables`](#variables) | Define job variables on a job level. | @@ -693,31 +693,41 @@ and triggers the `docker build service one` job. ### `rules` -Using `rules` allows for a list of individual rule objects to be evaluated +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/29011) in GitLab 12.3. + +`rules` allows for a list of individual rule objects to be evaluated *in order*, until one matches and dynamically provides attributes to the job. Available rule clauses include: -- `if` (similar to [`only:variables`](#onlyvariablesexceptvariables)). -- `changes` (same as [`only:changes`](#onlychangesexceptchanges)). +- [`if`](#rulesif) + (similar to [`only:variables`](#onlyvariablesexceptvariables)). +- [`changes`](#ruleschanges) + (same as [`only:changes`](#onlychangesexceptchanges)). -For example, using `if`: +For example, using `if`. This configuration specifies that `job` should be built +and run for every pipeline on merge requests targeting `master`, regardless of +the status of other builds: ```yaml job: script: "echo Hello, Rules!" rules: - - if: '$CI_MERGE_REQUEST_TARGET_BRANCH == "master"' # This rule will be evaluated + - if: '$CI_MERGE_REQUEST_TARGET_BRANCH == "master"' when: always - - if: '$VAR =~ /pattern/' # This rule will only be evaluated if the first does not match + - if: '$VAR =~ /pattern/' when: manual - - when: on_success # A Rule entry with no conditional clauses evaluates to true. If neither of the first two Rules match, this one will and set job:when to "on_success" + - when: on_success ``` -If the first rule does not match, further rules will be evaluated sequentially -until a match is found. The above configuration will specify that `job` should -be built and run for every pipeline on merge requests targeting `master`, -regardless of the status of other builds. +In this example, if the first rule: + +- Matches, the job will be given the `when:always` attribute. +- Does not match, the second and third rules will be evaluated sequentially + until a match is found. That is, the job will be given either the: + - `when: manual` attribute if the second rule matches. + - `when: on_success` attribute if the second rule does not match. The third + rule will always match when reached because it has no conditional clauses. #### `rules:if` @@ -744,10 +754,9 @@ at all, the behavior defaults to `job:when`, which continues to default to #### `rules:changes` `changes` works exactly the same way as [`only`/`except`](#onlychangesexceptchanges), -accepting an array of paths. The following configuration configures a job to be -run manually if `Dockerfile` has changed OR `$VAR == "string value"`. Otherwise -it is set to `when:on_success` by the last rule, where 0 clauses evaluate as -vacuously true. +accepting an array of paths. + +For example: ```yaml docker build: @@ -762,12 +771,20 @@ docker build: ``` -#### Complex Rule Clauses +In this example, a job either set to: + +- Run manually if `Dockerfile` has changed OR `$VAR == "string value"`. +- `when:on_success` by the last rule, where no earlier clauses evaluate to true. + +#### Complex rule clauses To conjoin `if` and `changes` clauses with an AND, use them in the same rule. -Here we run the job manually if `Dockerfile` or any file in `docker/scripts/` -has changed AND `$VAR == "string value"`. Otherwise, the job will not be -included in the pipeline. + +In the following example: + +- We run the job manually if `Dockerfile` or any file in `docker/scripts/` + has changed AND `$VAR == "string value"`. +- Otherwise, the job will not be included in the pipeline. ```yaml docker build: @@ -781,18 +798,27 @@ docker build: # - when: never would be redundant here, this is implied any time rules are listed. ``` -The only clauses currently available are `if` and `changes`. Keywords such as -`branches` or `refs` that are currently available for `only`/`except` are not -yet available in `rules` as they are being individually considered for their -usage and behavior in the newer context. +The only clauses currently available are: + +- `if` +- `changes` + +Keywords such as `branches` or `refs` that are currently available for +`only`/`except` are not yet available in `rules` as they are being individually +considered for their usage and behavior in this context. #### Permitted attributes -The only job attributes currently set by `rules` are `when` and `start_in`, if -`when` is set to `delayed`. A job will be included in a pipeline if `when` is -evaluated to any value except `never`. +The only job attributes currently set by `rules` are: + +- `when`. +- `start_in`, if `when` is set to `delayed`. + +A job will be included in a pipeline if `when` is evaluated to any value +except `never`. -Delayed jobs require a `start_in` value, so rule objects do as well. For example: +Delayed jobs require a `start_in` value, so rule objects do as well. For +example: ```yaml docker build: @@ -806,9 +832,9 @@ docker build: ``` -Additional Job configuration may be added to rules in the future, if something -useful isn't available, please open an issue on -[Gitlab CE](https://www.gitlab.com/gitlab-org/gitlab-ce/issues). +Additional job configuration may be added to rules in the future. If something +useful isn't available, please +[open an issue](https://www.gitlab.com/gitlab-org/gitlab-ce/issues). ### `tags` @@ -1801,7 +1827,8 @@ and bring back the old behavior. ### `needs` -> Introduced in GitLab 12.2. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/47063) in GitLab 12.2. +> - In GitLab 12.3, maximum number of jobs in `needs` array raised from five to 50. The `needs:` keyword enables executing jobs out-of-order, allowing you to implement a [directed acyclic graph](../directed_acyclic_graph/index.md) in your `.gitlab-ci.yml`. @@ -1852,30 +1879,26 @@ This example creates three paths of execution: #### Requirements and limitations -1. If `needs:` is set to point to a job that is not instantiated - because of `only/except` rules or otherwise does not exist, the - job will fail. -1. Note that on day one of the launch, we are temporarily limiting the - maximum number of jobs that a single job can need in the `needs:` array. Track - our [infrastructure issue](https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/7541) - for details on the current limit. -1. If you use `dependencies:` with `needs:`, it's important that you - do not mark a job as having a dependency on something that won't - have been run at the time it needs it. It's better to use both - keywords in this case so that GitLab handles the ordering appropriately. -1. It is impossible for now to have `needs: []` (empty needs), - the job always needs to depend on something, unless this is the job - in the first stage (see [gitlab-ce#65504](https://gitlab.com/gitlab-org/gitlab-ce/issues/65504)). -1. If `needs:` refers to a job that is marked as `parallel:`. - the current job will depend on all parallel jobs created. -1. `needs:` is similar to `dependencies:` in that it needs to use jobs from - prior stages, meaning it is impossible to create circular - dependencies or depend on jobs in the current stage (see [gitlab-ce#65505](https://gitlab.com/gitlab-org/gitlab-ce/issues/65505)). -1. Related to the above, stages must be explicitly defined for all jobs - that have the keyword `needs:` or are referred to by one. -1. For self-managed users, the feature must be turned on using the `ci_dag_support` - feature flag. The `ci_dag_limit_needs` option, if set, will limit the number of - jobs that a single job can need to `50`. If unset, the limit is `5`. +- If `needs:` is set to point to a job that is not instantiated + because of `only/except` rules or otherwise does not exist, the + pipeline will be created with YAML error. +- We are temporarily limiting the maximum number of jobs that a single job can + need in the `needs:` array: + - For GitLab.com, the limit is five. For more information, see our + [infrastructure issue](https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/7541). + - For self-managed instances, the limit is: + - Five by default (`ci_dag_limit_needs` feature flag is enabled). + - 50 if the `ci_dag_limit_needs` feature flag is disabled. +- It is impossible for now to have `needs: []` (empty needs), + the job always needs to depend on something, unless this is the job + in the first stage (see [gitlab-ce#65504](https://gitlab.com/gitlab-org/gitlab-ce/issues/65504)). +- If `needs:` refers to a job that is marked as `parallel:`. + the current job will depend on all parallel jobs created. +- `needs:` is similar to `dependencies:` in that it needs to use jobs from + prior stages, meaning it is impossible to create circular + dependencies or depend on jobs in the current stage (see [gitlab-ce#65505](https://gitlab.com/gitlab-org/gitlab-ce/issues/65505)). +- Related to the above, stages must be explicitly defined for all jobs + that have the keyword `needs:` or are referred to by one. ### `coverage` diff --git a/doc/development/README.md b/doc/development/README.md index 3912a828dec..bbe73570f49 100644 --- a/doc/development/README.md +++ b/doc/development/README.md @@ -22,6 +22,7 @@ description: 'Learn how to contribute to GitLab.' - [Guidelines for implementing Enterprise Edition features](ee_features.md) - [Security process for developers](https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md#security-releases-critical-non-critical-as-a-developer) - [Requesting access to Chatops on GitLab.com](chatops_on_gitlabcom.md#requesting-access) (for GitLabbers) +- [Danger bot](dangerbot.md) ## UX and Frontend guides diff --git a/doc/development/architecture.md b/doc/development/architecture.md index 2adca2dae28..ee5fc553e27 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -651,7 +651,7 @@ We've also detailed [our architecture of GitLab.com](https://about.gitlab.com/ha [shell-charts]: https://docs.gitlab.com/charts/charts/gitlab/gitlab-shell/ [shell-source]: ../install/installation.md#install-gitlab-shell [pages-omnibus]: ../administration/pages/index.md -[pages-charts]: https://gitlab.com/charts/gitlab/issues/37 +[pages-charts]: https://gitlab.com/gitlab-org/charts/gitlab/issues/37 [pages-source]: ../install/installation.md#install-gitlab-pages [pages-gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/pages.md [registry-omnibus]: ../administration/container_registry.md#container-registry-domain-configuration @@ -673,9 +673,9 @@ We've also detailed [our architecture of GitLab.com](https://about.gitlab.com/ha [grafana-omnibus]: ../administration/monitoring/performance/grafana_configuration.md [grafana-charts]: https://github.com/helm/charts/tree/master/stable/grafana [sentry-omnibus]: https://docs.gitlab.com/omnibus/settings/configuration.html#error-reporting-and-logging-with-sentry -[sentry-charts]: https://gitlab.com/charts/gitlab/issues/1319 +[sentry-charts]: https://gitlab.com/gitlab-org/charts/gitlab/issues/1319 [jaeger-omnibus]: https://gitlab.com/gitlab-org/omnibus-gitlab/issues/4104 -[jaeger-charts]: https://gitlab.com/charts/gitlab/issues/1320 +[jaeger-charts]: https://gitlab.com/gitlab-org/charts/gitlab/issues/1320 [jaeger-source]: ../development/distributed_tracing.md#enabling-distributed-tracing [jaeger-gdk]: ../development/distributed_tracing.html#using-jaeger-in-the-gitlab-development-kit [redis-exporter-omnibus]: ../administration/monitoring/prometheus/redis_exporter.md @@ -687,7 +687,7 @@ We've also detailed [our architecture of GitLab.com](https://about.gitlab.com/ha [gitlab-monitor-omnibus]: ../administration/monitoring/prometheus/gitlab_monitor_exporter.md [gitlab-monitor-charts]: https://docs.gitlab.com/charts/charts/gitlab/gitlab-monitor/index.html [node-exporter-omnibus]: ../administration/monitoring/prometheus/node_exporter.md -[node-exporter-charts]: https://gitlab.com/charts/gitlab/issues/1332 +[node-exporter-charts]: https://gitlab.com/gitlab-org/charts/gitlab/issues/1332 [mattermost-omnibus]: https://docs.gitlab.com/omnibus/gitlab-mattermost/ [mattermost-charts]: https://docs.mattermost.com/install/install-mmte-helm-gitlab-helm.html [minio-omnibus]: https://min.io/download @@ -705,7 +705,7 @@ We've also detailed [our architecture of GitLab.com](https://about.gitlab.com/ha [certificate-management-source]: ../install/installation.md#using-https [certificate-management-gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/https.md [geo-omnibus]: ../administration/geo/replication/index.md#setup-instructions -[geo-charts]: https://gitlab.com/charts/gitlab/issues/8 +[geo-charts]: https://gitlab.com/gitlab-org/charts/gitlab/issues/8 [geo-gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/geo.md [ldap-omnibus]: ../administration/auth/ldap.md [ldap-charts]: https://docs.gitlab.com/charts/charts/globals.html#ldap diff --git a/doc/development/code_review.md b/doc/development/code_review.md index b7d74b17eb3..80890d96159 100644 --- a/doc/development/code_review.md +++ b/doc/development/code_review.md @@ -34,7 +34,7 @@ more than one approval, the last maintainer to review and approve it will also m ### Reviewer roulette -The `danger-review` CI job will randomly pick a reviewer and a maintainer for +The [Danger bot](dangerbot.md) randomly picks a reviewer and a maintainer for each area of the codebase that your merge request seems to touch. It only makes recommendations - feel free to override it if you think someone else is a better fit! diff --git a/doc/development/dangerbot.md b/doc/development/dangerbot.md new file mode 100644 index 00000000000..5fc5886e3a2 --- /dev/null +++ b/doc/development/dangerbot.md @@ -0,0 +1,116 @@ +# Danger bot + +The GitLab CI pipeline includes a `danger-review` job that uses [Danger](https://github.com/danger/danger) +to perform a variety of automated checks on the code under test. + +Danger is a gem that runs in the CI environment, like any other analysis tool. +What sets it apart from, e.g., Rubocop, is that it's designed to allow you to +easily write arbitrary code to test properties of your code or changes. To this +end, it provides a set of common helpers and access to information about what +has actually changed in your environment, then simply runs your code! + +If Danger is asking you to change something about your merge request, it's best +just to make the change. If you want to learn how Danger works, or make changes +to the existing rules, then this is the document for you. + +## Operation + +On startup, Danger reads a [`Dangerfile`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/Dangerfile) +from the project root. GitLab's Danger code is decomposed into a set of helpers +and plugins, all within the [`danger/`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/danger/) +subdirectory, so ours just tells Danger to load it all. Danger will then run +each plugin against the merge request, collecting the output from each. A plugin +may output notifications, warnings, or errors, all of which are copied to the +CI job's log. If an error happens, the CI job (and so the entire pipeline) will +be failed. + +On merge requests, Danger will also copy the output to a comment on the MR +itself, increasing visibility. + +## Development guidelines + +Danger code is Ruby code, so all our [usual backend guidelines](README.md#backend-guides) +continue to apply. However, there are a few things that deserve special emphasis. + +### When to use Danger + +Danger is a powerful tool and flexible tool, but not always the most appropriate +way to solve a given problem or workflow. + +First, be aware of GitLab's [commitment to dogfooding](https://about.gitlab.com/handbook/engineering/#dogfooding). +The code we write for Danger is GitLab-specific, and it **may not** be most +appropriate place to implement functionality that addresses a need we encounter. +Our users, customers, and even our own satellite projects, such as [Gitaly](https://gitlab.com/gitlab-org/gitaly), +often face similar challenges, after all. Think about how you could fulfil the +same need while ensuring everyone can benefit from the work, and do that instead +if you can. + +If a standard tool (e.g. `rubocop`) exists for a task, it is better to use it +directly, rather than calling it via Danger. Running and debugging the results +of those tools locally is easier if Danger isn't involved, and unless you're +using some Danger-specific functionality, there's no benefit to including it in +the Danger run. + +Danger is well-suited to prototyping and rapidly iterating on solutions, so if +what we want to build is unclear, a solution in Danger can be thought of as a +trial run to gather information about a product area. If you're doing this, make +sure the problem you're trying to solve, and the outcomes of that prototyping, +are captured in an issue or epic as you go along. This will help us to address +the need as part of the product in a future version of GitLab! + +### Implementation details + +Implement each task as an isolated piece of functionality and place it in its +own directory under `danger` as `danger/<task-name>/Dangerfile`. + +Add a line to the top-level `Dangerfile` to ensure it is loaded like: + +```ruby +danger.import_dangerfile('danger/<task-name>') +``` + +Each task should be isolated from the others, and able to function in isolation. +If there is code that should be shared between multiple tasks, add a plugin to +`danger/plugins/...` and require it in each task that needs it. You can also +create plugins that are specific to a single task, which is a natural place for +complex logic related to that task. + +Danger code is just Ruby code. It should adhere to our coding standards, and +needs tests, like any other piece of Ruby in our codebase. However, we aren't +able to test a `Dangerfile` directly! So, to maximise test coverage, try to +minimize the number of lines of code in `danger/`. A non-trivial `Dangerfile` +should mostly call plugin code with arguments derived from the methods provided +by Danger. The plugin code itself should have unit tests. + +At present, we do this by putting the code in a module in `lib/gitlab/danger/...`, +and including it in the matching `danger/plugins/...` file. Specs can then be +added in `spec/lib/gitlab/danger/...`. + +You'll only know if your `Dangerfile` works by pushing the branch that contains +it to GitLab. This can be quite frustrating, as it significantly increases the +cycle time when developing a new task, or trying to debug something in an +existing one. If you've followed the guidelines above, most of your code can +be exercised locally in RSpec, minimizing the number of cycles you need to go +through in CI. However, you can speed these cycles up somewhat by emptying the +`.gitlab/ci/rails.gitlab-ci.yml` file in your merge request. Just don't forget +to revert the change before merging! + +You should add the `~Danger bot` label to the merge request before sending it +for review. + +## Current uses + +Here is a (non-exhaustive) list of the kinds of things Danger has been used for +at GitLab so far: + +- Coding style +- Database review workflow +- Documentation review workflow +- Merge request metrics +- Reviewer roulette workflow +- Single codebase effort + +## Limitations + +- [`danger local` does not work on GitLab](https://github.com/danger/danger/issues/458) +- Danger output is not added to a merge request comment if working on a fork. diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md index edd83f67d3b..719b9aa212a 100644 --- a/doc/development/documentation/index.md +++ b/doc/development/documentation/index.md @@ -4,9 +4,9 @@ description: Learn how to contribute to GitLab Documentation. # GitLab Documentation guidelines -GitLab's documentation is [intended as the single source of truth (SSOT)](https://about.gitlab.com/handbook/documentation/) for information about how to configure, use, and troubleshoot GitLab. The documentation contains use cases and usage instructions covering every GitLab feature, organized by product area and subject. This includes topics and workflows that span multiple GitLab features, as well as the use of GitLab with other applications. +GitLab's documentation is [intended as the single source of truth (SSOT)](https://about.gitlab.com/handbook/documentation/) for information about how to configure, use, and troubleshoot GitLab. The documentation contains use cases and usage instructions for every GitLab feature, organized by product area and subject. This includes topics and workflows that span multiple GitLab features, and the use of GitLab with other applications. -In addition to this page, the following resources to help craft and contribute documentation are available: +In addition to this page, the following resources can help you craft and contribute documentation: - [Style Guide](styleguide.md) - What belongs in the docs, language guidelines, and more. - [Structure and template](structure.md) - Learn the typical parts of a doc page and how to write each one. @@ -18,9 +18,9 @@ In addition to this page, the following resources to help craft and contribute d ## Source files and rendered web locations -Documentation for GitLab Community Edition (CE) and Enterprise Edition (EE), along with GitLab Runner and Omnibus, is published to [docs.gitlab.com](https://docs.gitlab.com). The documentation for CE and EE is also published within the application at `/help` on the domain of the GitLab instance, though there are [plans](https://gitlab.com/groups/gitlab-org/-/epics/693) to end this practice and instead link out from the GitLab application to docs.gitlab.com URLs. +Documentation for GitLab Community Edition (CE), Enterprise Edition (EE), GitLab Runner, and Omnibus is published to [docs.gitlab.com](https://docs.gitlab.com). Documentation for CE and EE is also published within the application at `/help` on the domain of the GitLab instance. -At `/help`, only content for your current edition and version is included, whereas multiple versions' content is available at docs.gitlab.com. +At `/help`, only help for your current edition and version is included. Help for other versions is available at docs.gitlab.com. The source of the documentation exists within the codebase of each GitLab application in the following repository locations: @@ -37,9 +37,9 @@ Documentation issues and merge requests are part of their respective repositorie [Contributions to GitLab docs](workflow.md) are welcome from the entire GitLab community. -To ensure that GitLab docs keep up with changes to the product, special processes and responsibilities are in place concerning all [feature changes](feature-change-workflow.md)—i.e. development work that impacts the appearance, usage, or administration of a feature. +To ensure that GitLab docs are current, there are special processes and responsibilities for all [feature changes](feature-change-workflow.md)—i.e. development work that impacts the appearance, usage, or administration of a feature. -Meanwhile, anyone can contribute [documentation improvements](improvement-workflow.md) large or small that are not associated with a feature change. For example, adding a new doc on how to accomplish a use case that's already possible with GitLab or with third-party tools and GitLab. +However, anyone can contribute [documentation improvements](improvement-workflow.md) that are not associated with a feature change. For example, adding a new doc on how to accomplish a use case that's already possible with GitLab or with third-party tools and GitLab. ## Markdown and styles @@ -54,16 +54,14 @@ See the [Structure](styleguide.md#structure) section of the [Documentation Style ## Single codebase -We currently maintain two sets of docs: one in the +We maintain two sets of docs: one in the [gitlab-ce](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc) repo and one in [gitlab-ee](https://gitlab.com/gitlab-org/gitlab-ee/tree/master/doc). -They are identical, but they are different repositories. When the -time comes to have only one codebase for the GitLab project, we'll be ready. +These are identical, but they are different repositories. ### CE first -All merge requests for documentation must be submitted to CE, regardless of the content -it has. This means that: +All merge requests for documentation must be submitted to CE. This means that: - For **EE-only docs changes**, you only have to submit an MR in the CE project. - For **EE-only features** that touch both the code and the docs, you have to submit @@ -74,20 +72,20 @@ This might seem like a duplicate effort, but it's only for the short term. Since the CE and EE docs are combined, it's crucial to add the relevant [product badges](styleguide.md#product-badges) for all EE documentation, so that -we can discern which features belong to which tier. +we can determine which features belong to which tier. ### EE specific lines check There's a special test in place ([`ee_specific_check.rb`](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/scripts/ee_specific_check/ee_specific_check.rb)), -which, among others, checks and prevents creating/editing new files and directories +which checks and prevents creating or editing new files or directories in EE under `doc/`. This should fail when changes to anything in `/doc` are submitted in an EE MR. To pass the test, simply remove the docs changes from the EE MR, and [submit them in CE](#ce-first). ## Changing document location -Changing a document's location requires specific steps to be followed to ensure that +Changing a document's location requires specific steps to ensure that users can seamlessly access the new doc page, whether they are accessing content on a GitLab instance domain at `/help` or at docs.gitlab.com. Be sure to ping a GitLab technical writer if you have any questions during the process (such as @@ -95,7 +93,7 @@ whether the move is necessary), and ensure that a technical writer reviews this change prior to merging. If you indeed need to change a document's location, do not remove the old -document, but rather replace all of its content with a new line: +document, but instead replace all of its content with a new line: ```md This document was moved to [another location](path/to/new_doc.md). @@ -105,7 +103,7 @@ where `path/to/new_doc.md` is the relative path to the root directory `doc/`. --- -For example, if you were to move `doc/workflow/lfs/lfs_administration.md` to +For example, if you move `doc/workflow/lfs/lfs_administration.md` to `doc/administration/lfs.md`, then the steps would be: 1. Copy `doc/workflow/lfs/lfs_administration.md` to `doc/administration/lfs.md` @@ -145,7 +143,7 @@ Things to note: ### Alternative redirection method -Alternatively to the method described above, you can simply replace the content +You can also replace the content of the old file with a frontmatter containing a redirect link: ```yaml @@ -163,7 +161,7 @@ land on the doc via `/help`. ### Redirections for pages with Disqus comments -If the documentation page being relocated already has any Disqus comments, +If the documentation page being relocated already has Disqus comments, we need to preserve the Disqus thread. Disqus uses an identifier per page, and for docs.gitlab.com, the page identifier @@ -189,8 +187,7 @@ even if it's `index.html` or `README.html`. ## Branch naming If your contribution contains **only** documentation changes, you can speed up -the CI process by following some branch naming conventions. You have three -choices: +the CI process by following these branch naming conventions: | Branch name | Valid example | |:----------------------|:-----------------------------| @@ -199,7 +196,7 @@ choices: | Ending in `-docs` | `123-update-api-issues-docs` | If your branch name matches any of the above, it will run only the docs -tests. If it does not, the whole application test suite will run (including docs tests). +tests. If not, the whole application test suite will run (including docs tests). ## Merge requests for GitLab documentation @@ -399,8 +396,8 @@ preview the changes. The docs URL can be found in two places: triggered pipeline so that you can investigate whether something went wrong TIP: **Tip:** -Someone that has no merge rights to the CE/EE projects (think of forks from -contributors) will not be able to run the manual job. In that case, you can +Someone with no merge rights to the CE/EE projects (think of forks from +contributors) cannot run the manual job. In that case, you can ask someone from the GitLab team who has the permissions to do that for you. NOTE: **Note:** @@ -458,8 +455,8 @@ The following GitLab features are used among others: ## Testing -We treat documentation as code, thus have implemented some testing. -Currently, the following tests are in place: +We treat documentation as code, and so use tests to maintain the standards and quality of the docs. +The current tests are: 1. `docs lint`: Check that all internal (relative) links work correctly and that all cURL examples in API docs use the full switches. It's recommended @@ -484,7 +481,7 @@ Currently, the following tests are in place: ### Linting -To help adhere to the [documentation style guidelines](styleguide.md), and to improve the content +To help adhere to the [documentation style guidelines](styleguide.md), and 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. diff --git a/doc/development/gotchas.md b/doc/development/gotchas.md index 941eea2609e..10e8008bad3 100644 --- a/doc/development/gotchas.md +++ b/doc/development/gotchas.md @@ -18,7 +18,7 @@ end Consider the following API spec: ```ruby -require 'rails_helper' +require 'spec_helper' describe API::Labels do it 'creates a first label' do @@ -69,7 +69,7 @@ is ok, but `create(:label, title: 'label1')` is not. Following is the fixed API spec: ```ruby -require 'rails_helper' +require 'spec_helper' describe API::Labels do it 'creates a first label' do diff --git a/doc/development/prometheus_metrics.md b/doc/development/prometheus_metrics.md index 576601372a3..2a34851d21c 100644 --- a/doc/development/prometheus_metrics.md +++ b/doc/development/prometheus_metrics.md @@ -44,3 +44,26 @@ class ImportCommonMetrics < ActiveRecord::Migration[4.2] end end ``` + +## GitLab Prometheus metrics + +GitLab provides [Prometheus metrics](../administration/monitoring/prometheus/gitlab_metrics.md) +to monitor itself. + +### Adding a new metric + +This section describes how to add new metrics for self-monitoring +([example](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/15440)). + +1. Select the [type of metric](https://gitlab.com/gitlab-org/prometheus-client-mmap#metrics): + + - `Gitlab::Metrics.counter` + - `Gitlab::Metrics.gauge` + - `Gitlab::Metrics.histogram` + - `Gitlab::Metrics.summary` + +1. Select the appropriate name for your metric. Refer to the guidelines + for [Prometheus metric names](https://prometheus.io/docs/practices/naming/#metric-names). +1. Update the list of [GitLab Prometheus metrics](../administration/monitoring/prometheus/gitlab_metrics.md). +1. Trigger the relevant page/code that will record the new metric. +1. Check that the new metric appears at `/-/metrics`. diff --git a/doc/development/testing_guide/end_to_end/index.md b/doc/development/testing_guide/end_to_end/index.md index 3ae3ce183d9..f6a2f642274 100644 --- a/doc/development/testing_guide/end_to_end/index.md +++ b/doc/development/testing_guide/end_to_end/index.md @@ -118,7 +118,7 @@ Helm chart][helm-chart], itself deployed with custom See [Review Apps][review-apps] for more details about Review Apps. -[helm-chart]: https://gitlab.com/charts/gitlab/ +[helm-chart]: https://gitlab.com/gitlab-org/charts/gitlab/ [cng]: https://gitlab.com/gitlab-org/build/CNG ## How do I run the tests? diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md index 28a60660995..13772cbe015 100644 --- a/doc/development/testing_guide/review_apps.md +++ b/doc/development/testing_guide/review_apps.md @@ -267,7 +267,7 @@ find a way to limit it to only us.** - [Review Apps integration for CE/EE (presentation)](https://docs.google.com/presentation/d/1QPLr6FO4LduROU8pQIPkX1yfGvD13GEJIBOenqoKxR8/edit?usp=sharing) -[charts-1068]: https://gitlab.com/charts/gitlab/issues/1068 +[charts-1068]: https://gitlab.com/gitlab-org/charts/gitlab/issues/1068 [gitlab-pipeline]: https://gitlab.com/gitlab-org/gitlab-ce/pipelines/44362587 [gitlab:assets:compile]: https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/149511610 [review-build-cng]: https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/149511623 @@ -276,7 +276,7 @@ find a way to limit it to only us.** [cng]: https://gitlab.com/gitlab-org/build/CNG [cng-mirror-pipeline]: https://gitlab.com/gitlab-org/build/CNG-mirror/pipelines/44364657 [cng-mirror-registry]: https://gitlab.com/gitlab-org/build/CNG-mirror/container_registry -[helm-chart]: https://gitlab.com/charts/gitlab/ +[helm-chart]: https://gitlab.com/gitlab-org/charts/gitlab/ [review-apps-ce]: https://console.cloud.google.com/kubernetes/clusters/details/us-central1-a/review-apps-ce?project=gitlab-review-apps [review-apps-ee]: https://console.cloud.google.com/kubernetes/clusters/details/us-central1-b/review-apps-ee?project=gitlab-review-apps [review-apps.sh]: https://gitlab.com/gitlab-org/gitlab-ee/blob/master/scripts/review_apps/review-apps.sh diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index 336000f6cb9..59b775d13bd 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -92,9 +92,9 @@ If you are running GitLab within a Docker container, you can run the backup from docker exec -t <container name> gitlab-backup create ``` -If you are using the [GitLab helm chart](https://gitlab.com/charts/gitlab) on a +If you are using the [GitLab helm chart](https://gitlab.com/gitlab-org/charts/gitlab) on a Kubernetes cluster, you can run the backup task using `backup-utility` script on -the GitLab task runner pod via `kubectl`. Refer to [backing up a GitLab installation](https://gitlab.com/charts/gitlab/blob/master/doc/backup-restore/backup.md#backing-up-a-gitlab-installation) for more details: +the GitLab task runner pod via `kubectl`. Refer to [backing up a GitLab installation](https://gitlab.com/gitlab-org/charts/gitlab/blob/master/doc/backup-restore/backup.md#backing-up-a-gitlab-installation) for more details: ```sh kubectl exec -it <gitlab task-runner pod> backup-utility @@ -764,7 +764,7 @@ docker exec -it <name of container> gitlab-backup restore ``` The GitLab helm chart uses a different process, documented in -[restoring a GitLab helm chart installation](https://gitlab.com/charts/gitlab/blob/master/doc/backup-restore/restore.md). +[restoring a GitLab helm chart installation](https://gitlab.com/gitlab-org/charts/gitlab/blob/master/doc/backup-restore/restore.md). ## Alternative backup strategies diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md index 1e9eb15533a..24a334e7067 100644 --- a/doc/system_hooks/system_hooks.md +++ b/doc/system_hooks/system_hooks.md @@ -13,6 +13,7 @@ Your GitLab instance can perform HTTP POST requests on the following events: - `project_update` - `user_add_to_team` - `user_remove_from_team` +- `user_update_for_team` - `user_create` - `user_destroy` - `user_failed_login` @@ -24,6 +25,7 @@ Your GitLab instance can perform HTTP POST requests on the following events: - `group_rename` - `user_add_to_group` - `user_remove_from_group` +- `user_update_for_group` The triggers for most of these are self-explanatory, but `project_update` and `project_rename` deserve some clarification: `project_update` is fired any time an attribute of a project is changed (name, description, tags, etc.) *unless* the `path` attribute is also changed. In that case, a `project_rename` is triggered instead (so that, for instance, if all you care about is the repo URL, you can just listen for `project_rename`). @@ -173,6 +175,26 @@ Please refer to `group_rename` and `user_rename` for that case. } ``` +**Team Member Updated:** + +```json +{ + "created_at": "2012-07-21T07:30:56Z", + "updated_at": "2012-07-21T07:38:22Z", + "event_name": "user_update_for_team", + "access_level": "Maintainer", + "project_id": 74, + "project_name": "StoreCloud", + "project_path": "storecloud", + "project_path_with_namespace": "jsmith/storecloud", + "user_email": "johnsmith@gmail.com", + "user_name": "John Smith", + "user_username": "johnsmith", + "user_id": 41, + "project_visibility": "visibilitylevel|private" +} +``` + **User created:** ```json @@ -349,6 +371,24 @@ If the user is blocked via LDAP, `state` will be `ldap_blocked`. } ``` +**Group Member Updated:** + +```json +{ + "created_at": "2012-07-21T07:30:56Z", + "updated_at": "2012-07-21T07:38:22Z", + "event_name": "user_update_for_group", + "group_access": "Maintainer", + "group_id": 78, + "group_name": "StoreCloud", + "group_path": "storecloud", + "user_email": "johnsmith@gmail.com", + "user_name": "John Smith", + "user_username": "johnsmith", + "user_id": 41 +} +``` + ## Push events Triggered when you push to the repository, except when pushing tags. diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md index b40392e12d5..3276dc40dc0 100644 --- a/doc/user/application_security/dependency_scanning/index.md +++ b/doc/user/application_security/dependency_scanning/index.md @@ -77,7 +77,7 @@ like Gemnasium require sending data to GitLab central servers to analyze them: The Gemnasium client does **NOT** send the exact package versions your project relies on. You can disable the remote checks by [using](#customizing-the-dependency-scanning-settings) -the `DS_DISABLE_REMOTE_CHECKS` environment variable and setting it to `true`. +the `DS_DISABLE_REMOTE_CHECKS` environment variable and setting it to `"true"`. ## Configuration @@ -115,7 +115,7 @@ include: template: Dependency-Scanning.gitlab-ci.yml variables: - DS_DISABLE_REMOTE_CHECKS: true + DS_DISABLE_REMOTE_CHECKS: "true" ``` Because template is [evaluated before](../../../ci/yaml/README.md#include) the pipeline diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md index 5a1cc0561fc..69529d7420b 100644 --- a/doc/user/application_security/index.md +++ b/doc/user/application_security/index.md @@ -28,7 +28,7 @@ GitLab can scan and report any vulnerabilities found in your project. | [Dependency List](dependency_list/index.md) **(ULTIMATE)** | View your project's dependencies and their known vulnerabilities. | | [Dependency Scanning](dependency_scanning/index.md) **(ULTIMATE)** | Analyze your dependencies for known vulnerabilities. | | [Dynamic Application Security Testing (DAST)](dast/index.md) **(ULTIMATE)** | Analyze running web applications for known vulnerabilities. | -| [License Compliance](license_management/index.md) **(ULTIMATE)** | Search your project's dependencies for their licenses. | +| [License Compliance](license_compliance/index.md) **(ULTIMATE)** | Search your project's dependencies for their licenses. | | [Security Dashboard](security_dashboard/index.md) **(ULTIMATE)** | View vulnerabilities in all your projects and groups. | | [Static Application Security Testing (SAST)](sast/index.md) **(ULTIMATE)** | Analyze source code for known vulnerabilities. | diff --git a/doc/user/application_security/license_compliance/img/license_compliance_add_license.png b/doc/user/application_security/license_compliance/img/license_compliance_add_license.png Binary files differdeleted file mode 100644 index c9a5dc14c57..00000000000 --- a/doc/user/application_security/license_compliance/img/license_compliance_add_license.png +++ /dev/null diff --git a/doc/user/application_security/license_compliance/img/license_compliance_add_license_v12_3.png b/doc/user/application_security/license_compliance/img/license_compliance_add_license_v12_3.png Binary files differnew file mode 100644 index 00000000000..79f6160e63f --- /dev/null +++ b/doc/user/application_security/license_compliance/img/license_compliance_add_license_v12_3.png diff --git a/doc/user/application_security/license_compliance/img/license_compliance_pipeline_tab.png b/doc/user/application_security/license_compliance/img/license_compliance_pipeline_tab.png Binary files differdeleted file mode 100644 index 80ffca815b9..00000000000 --- a/doc/user/application_security/license_compliance/img/license_compliance_pipeline_tab.png +++ /dev/null diff --git a/doc/user/application_security/license_compliance/img/license_compliance_pipeline_tab_v12_3.png b/doc/user/application_security/license_compliance/img/license_compliance_pipeline_tab_v12_3.png Binary files differnew file mode 100644 index 00000000000..fd519d63b3e --- /dev/null +++ b/doc/user/application_security/license_compliance/img/license_compliance_pipeline_tab_v12_3.png diff --git a/doc/user/application_security/license_compliance/img/license_compliance_search.png b/doc/user/application_security/license_compliance/img/license_compliance_search.png Binary files differdeleted file mode 100644 index b3ffd8d95a1..00000000000 --- a/doc/user/application_security/license_compliance/img/license_compliance_search.png +++ /dev/null diff --git a/doc/user/application_security/license_compliance/img/license_compliance_search_v12_3.png b/doc/user/application_security/license_compliance/img/license_compliance_search_v12_3.png Binary files differnew file mode 100644 index 00000000000..4a7cff2e85c --- /dev/null +++ b/doc/user/application_security/license_compliance/img/license_compliance_search_v12_3.png diff --git a/doc/user/application_security/license_compliance/img/license_compliance_settings.png b/doc/user/application_security/license_compliance/img/license_compliance_settings.png Binary files differdeleted file mode 100644 index 2e3e8888e93..00000000000 --- a/doc/user/application_security/license_compliance/img/license_compliance_settings.png +++ /dev/null diff --git a/doc/user/application_security/license_compliance/img/license_compliance_settings_v12_3.png b/doc/user/application_security/license_compliance/img/license_compliance_settings_v12_3.png Binary files differnew file mode 100644 index 00000000000..72d0888a9dc --- /dev/null +++ b/doc/user/application_security/license_compliance/img/license_compliance_settings_v12_3.png diff --git a/doc/user/application_security/license_compliance/index.md b/doc/user/application_security/license_compliance/index.md index f74b958cf67..6de1db8650d 100644 --- a/doc/user/application_security/license_compliance/index.md +++ b/doc/user/application_security/license_compliance/index.md @@ -198,7 +198,7 @@ To approve or blacklist a license: **License Compliance** section. 1. Click the **Add a license** button. - ![License Compliance Add License](img/license_compliance_add_license.png) + ![License Compliance Add License](img/license_compliance_add_license_v12_3.png) 1. In the **License name** dropdown, either: - Select one of the available licenses. You can search for licenses in the field @@ -212,13 +212,13 @@ To modify an existing license: 1. In the **License Compliance** list, click the **Approved/Declined** dropdown to change it to the desired status. - ![License Compliance Settings](img/license_compliance_settings.png) + ![License Compliance Settings](img/license_compliance_settings_v12_3.png) Searching for Licenses: 1. Use the **Search** box to search for a specific license. - ![License Compliance Search](img/license_compliance_search.png) + ![License Compliance Search](img/license_compliance_search_v12_3.png) ## License Compliance report under pipelines @@ -228,7 +228,7 @@ From your project's left sidebar, navigate to **CI/CD > Pipelines** and click on pipeline ID that has a `license_management` job to see the Licenses tab with the listed licenses (if any). -![License Compliance Pipeline Tab](img/license_compliance_pipeline_tab.png) +![License Compliance Pipeline Tab](img/license_compliance_pipeline_tab_v12_3.png) <!-- ## Troubleshooting diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md index 3eead6ccd3f..5e7bc4142fb 100644 --- a/doc/user/application_security/sast/index.md +++ b/doc/user/application_security/sast/index.md @@ -125,6 +125,21 @@ variables: Because the template is [evaluated before](../../../ci/yaml/README.md#include) the pipeline configuration, the last mention of the variable will take precedence. +#### Using a variable to pass username and password to a private Maven repository + +If you have a private Apache Maven repository that requires login credentials, +you can use the `MAVEN_CLI_OPTS` [environment variable](#available-variables) +to pass a username and password. You can set it under your project's settings +so that your credentials aren't exposed in `.gitlab-ci.yml`. + +If the username is `myuser` and the password is `verysecret` then you would +set the following [variable](../../../ci/variables/README.md#via-the-ui) +under your project's settings: + +| Type | Key | Value | +| ---- | --- | ----- | +| Variable | `MAVEN_CLI_OPTS` | `-Drepository.password=verysecret -Drepository.user=myuser` | + ### Overriding the SAST template If you want to override the job definition (for example, change properties like diff --git a/doc/user/project/operations/feature_flags.md b/doc/user/project/operations/feature_flags.md index 6536a1a0a4b..28248ad3696 100644 --- a/doc/user/project/operations/feature_flags.md +++ b/doc/user/project/operations/feature_flags.md @@ -2,10 +2,6 @@ > [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11845) in GitLab 11.4. -CAUTION: **Warning:** -This an _alpha_ feature and is subject to change at any time without -prior notice. - Feature flags allow you to ship a project in different flavors by dynamically toggling certain functionality. diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md index e373d605098..1f7f85e9750 100644 --- a/doc/user/project/quick_actions.md +++ b/doc/user/project/quick_actions.md @@ -14,8 +14,11 @@ on a separate line in order to be properly detected and executed. Once executed, ## Quick Actions for issues, merge requests and epics -The following quick actions are applicable to descriptions, discussions and threads -in issues and merge requests, as well as epics.**(ULTIMATE)** +The following quick actions are applicable to descriptions, discussions and threads in: + +- Issues +- Merge requests +- Epics **(ULTIMATE)** | Command | Issue | Merge request | Epic | Action | |:--------------------------------------|:------|:--------------|:-----|:------ | diff --git a/lib/api/entities.rb b/lib/api/entities.rb index cfcf6228225..ba58e125568 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -1229,6 +1229,7 @@ module API expose :author, using: Entities::UserBasic, if: -> (release, _) { release.author.present? } expose :commit, using: Entities::Commit, if: lambda { |_, _| can_download_code? } expose :upcoming_release?, as: :upcoming_release + expose :milestone, using: Entities::Milestone, if: -> (release, _) { release.milestone.present? } expose :assets do expose :assets_count, as: :count do |release, _| diff --git a/lib/api/release/links.rb b/lib/api/release/links.rb index 5d1b40e3bff..def36dc8529 100644 --- a/lib/api/release/links.rb +++ b/lib/api/release/links.rb @@ -5,7 +5,7 @@ module API class Links < Grape::API include PaginationParams - RELEASE_ENDPOINT_REQUIREMETS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS + RELEASE_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS .merge(tag_name: API::NO_SLASH_URL_PART_REGEX) before { authorize! :read_release, user_project } @@ -17,7 +17,7 @@ module API params do requires :tag_name, type: String, desc: 'The name of the tag', as: :tag end - resource 'releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMETS do + resource 'releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMENTS do resource :assets do desc 'Get a list of links of a release' do detail 'This feature was introduced in GitLab 11.7.' diff --git a/lib/api/releases.rb b/lib/api/releases.rb index 7a3d804c30c..5a31581c4da 100644 --- a/lib/api/releases.rb +++ b/lib/api/releases.rb @@ -4,7 +4,7 @@ module API class Releases < Grape::API include PaginationParams - RELEASE_ENDPOINT_REQUIREMETS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS + RELEASE_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS .merge(tag_name: API::NO_SLASH_URL_PART_REGEX) before { authorize_read_releases! } @@ -33,7 +33,7 @@ module API params do requires :tag_name, type: String, desc: 'The name of the tag', as: :tag end - get ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMETS do + get ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMENTS do authorize_download_code! present release, with: Entities::Release, current_user: current_user @@ -54,6 +54,7 @@ module API requires :url, type: String end end + optional :milestone, type: String, desc: 'The title of the related milestone' optional :released_at, type: DateTime, desc: 'The date when the release will be/was ready. Defaults to the current time.' end post ':id/releases' do @@ -79,8 +80,9 @@ module API optional :name, type: String, desc: 'The name of the release' optional :description, type: String, desc: 'Release notes with markdown support' optional :released_at, type: DateTime, desc: 'The date when the release will be/was ready.' + optional :milestone, type: String, desc: 'The title of the related milestone' end - put ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMETS do + put ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMENTS do authorize_update_release! result = ::Releases::UpdateService @@ -101,7 +103,7 @@ module API params do requires :tag_name, type: String, desc: 'The name of the tag', as: :tag end - delete ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMETS do + delete ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMENTS do authorize_destroy_release! result = ::Releases::DestroyService diff --git a/lib/banzai/filter/relative_link_filter.rb b/lib/banzai/filter/relative_link_filter.rb index 846a7d46aad..2b734db5cfb 100644 --- a/lib/banzai/filter/relative_link_filter.rb +++ b/lib/banzai/filter/relative_link_filter.rb @@ -19,7 +19,6 @@ module Banzai def call return doc if context[:system_note] - return doc unless visible_to_user? @uri_types = {} clear_memoization(:linkable_files) @@ -50,7 +49,7 @@ module Banzai if html_attr.value.start_with?('/uploads/') process_link_to_upload_attr(html_attr) - elsif linkable_files? + elsif linkable_files? && repo_visible_to_user? process_link_to_repository_attr(html_attr) end end @@ -168,14 +167,8 @@ module Banzai Gitlab.config.gitlab.relative_url_root.presence || '/' end - def visible_to_user? - if project - Ability.allowed?(current_user, :download_code, project) - elsif group - Ability.allowed?(current_user, :read_group, group) - else # Objects detached from projects or groups, e.g. Personal Snippets. - true - end + def repo_visible_to_user? + project && Ability.allowed?(current_user, :download_code, project) end def ref diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb index 6769bd95c2b..bdc46abeb9f 100644 --- a/lib/gitlab/auth.rb +++ b/lib/gitlab/auth.rb @@ -265,7 +265,8 @@ module Gitlab :read_project, :build_download_code, :build_read_container_image, - :build_create_container_image + :build_create_container_image, + :build_destroy_container_image ] end diff --git a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml index 3adc6a72874..3cdb7b5420c 100644 --- a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml @@ -25,8 +25,9 @@ code_quality: expire_in: 1 week dependencies: [] only: - - branches - - tags + refs: + - branches + - tags except: variables: - $CODE_QUALITY_DISABLED diff --git a/lib/gitlab/ci/templates/Pages/SwaggerUI.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/SwaggerUI.gitlab-ci.yml new file mode 100644 index 00000000000..8fd08ea7995 --- /dev/null +++ b/lib/gitlab/ci/templates/Pages/SwaggerUI.gitlab-ci.yml @@ -0,0 +1,29 @@ +image: node:10-alpine + +# specify the location of the Open API Specification files within your project +# and the filename of the specification that you would like to display by default +variables: + DOCS_FOLDER: "api-docs" + SPEC_TO_DISPLAY: "my-project_specification_0.0.1.json" + +# These folders are cached between builds +cache: + paths: + - ./node_modules + +# publishes all files from the $DOCS_FOLDER together with the static version of SwaggerUI +# sets the specification file named in $SPEC_TO_DISPLAY to be displayed by default +pages: + stage: deploy + before_script: + - npm install swagger-ui-dist@3.22.1 + script: + - mkdir public + - cp -rp node_modules/swagger-ui-dist/* public + - cp -rp $DOCS_FOLDER/* public + - sed -i "s#https://petstore\.swagger\.io/v2/swagger\.json#$SPEC_TO_DISPLAY#g" public/index.html + artifacts: + paths: + - public + only: + - master diff --git a/lib/gitlab/correlation_id.rb b/lib/gitlab/correlation_id.rb deleted file mode 100644 index 0f9bde4390e..00000000000 --- a/lib/gitlab/correlation_id.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - module CorrelationId - LOG_KEY = 'correlation_id'.freeze - - class << self - def use_id(correlation_id, &blk) - # always generate a id if null is passed - correlation_id ||= new_id - - ids.push(correlation_id || new_id) - - begin - yield(current_id) - ensure - ids.pop - end - end - - def current_id - ids.last - end - - def current_or_new_id - current_id || new_id - end - - private - - def ids - Thread.current[:correlation_id] ||= [] - end - - def new_id - SecureRandom.uuid - end - end - end -end diff --git a/lib/gitlab/database_importers/self_monitoring/project/create_service.rb b/lib/gitlab/database_importers/self_monitoring/project/create_service.rb index 3a170e8b5f8..5422a8631a0 100644 --- a/lib/gitlab/database_importers/self_monitoring/project/create_service.rb +++ b/lib/gitlab/database_importers/self_monitoring/project/create_service.rb @@ -45,20 +45,20 @@ module Gitlab def validate_application_settings return success if application_settings - log_error(_('No application_settings found')) + log_error('No application_settings found') error(_('No application_settings found')) end def validate_project_created return success unless project_created? - log_error(_('Project already created')) + log_error('Project already created') error(_('Project already created')) end def validate_admins unless instance_admins.any? - log_error(_('No active admin user found')) + log_error('No active admin user found') return error(_('No active admin user found')) end @@ -83,7 +83,7 @@ module Gitlab def create_project if project_created? - log_info(_('Instance administration project already exists')) + log_info('Instance administration project already exists') @project = application_settings.instance_administration_project return success(project: project) end @@ -93,7 +93,7 @@ module Gitlab if project.persisted? success(project: project) else - log_error(_("Could not create instance administration project. Errors: %{errors}") % { errors: project.errors.full_messages }) + log_error("Could not create instance administration project. Errors: %{errors}" % { errors: project.errors.full_messages }) error(_('Could not create project')) end end @@ -106,7 +106,7 @@ module Gitlab if result success else - log_error(_("Could not save instance administration project ID, errors: %{errors}") % { errors: application_settings.errors.full_messages }) + log_error("Could not save instance administration project ID, errors: %{errors}" % { errors: application_settings.errors.full_messages }) error(_('Could not save project ID')) end end @@ -116,7 +116,7 @@ module Gitlab errors = members.flat_map { |member| member.errors.full_messages } if errors.any? - log_error(_('Could not add admins as members to self-monitoring project. Errors: %{errors}') % { errors: errors }) + log_error('Could not add admins as members to self-monitoring project. Errors: %{errors}' % { errors: errors }) error(_('Could not add admins as members')) else success @@ -128,7 +128,7 @@ module Gitlab return success unless prometheus_listen_address.present? uri = parse_url(internal_prometheus_listen_address_uri) - return error(_('Prometheus listen_address is not a valid URI')) unless uri + return error(_('Prometheus listen_address in config/gitlab.yml is not a valid URI')) unless uri application_settings.add_to_outbound_local_requests_whitelist([uri.normalized_host]) result = application_settings.save @@ -140,7 +140,7 @@ module Gitlab Gitlab::CurrentSettings.expire_current_application_settings success else - log_error(_("Could not add prometheus URL to whitelist, errors: %{errors}") % { errors: application_settings.errors.full_messages }) + log_error("Could not add prometheus URL to whitelist, errors: %{errors}" % { errors: application_settings.errors.full_messages }) error(_('Could not add prometheus URL to whitelist')) end end @@ -152,7 +152,7 @@ module Gitlab service = project.find_or_initialize_service('prometheus') unless service.update(prometheus_service_attributes) - log_error(_('Could not save prometheus manual configuration for self-monitoring project. Errors: %{errors}') % { errors: service.errors.full_messages }) + log_error('Could not save prometheus manual configuration for self-monitoring project. Errors: %{errors}' % { errors: service.errors.full_messages }) return error(_('Could not save prometheus manual configuration')) end @@ -175,15 +175,15 @@ module Gitlab def prometheus_enabled? Gitlab.config.prometheus.enable if Gitlab.config.prometheus rescue Settingslogic::MissingSetting - log_error(_('prometheus.enable is not present in gitlab.yml')) + log_error('prometheus.enable is not present in config/gitlab.yml') false end def prometheus_listen_address - Gitlab.config.prometheus.listen_address if Gitlab.config.prometheus + Gitlab.config.prometheus.listen_address.to_s if Gitlab.config.prometheus rescue Settingslogic::MissingSetting - log_error(_('prometheus.listen_address is not present in gitlab.yml')) + log_error('Prometheus listen_address is not present in config/gitlab.yml') nil end @@ -228,9 +228,21 @@ module Gitlab end def internal_prometheus_listen_address_uri - if prometheus_listen_address.starts_with?('http') + if prometheus_listen_address.starts_with?('0.0.0.0:') + # 0.0.0.0:9090 + port = ':' + prometheus_listen_address.split(':').second + 'http://localhost' + port + + elsif prometheus_listen_address.starts_with?(':') + # :9090 + 'http://localhost' + prometheus_listen_address + + elsif prometheus_listen_address.starts_with?('http') + # https://localhost:9090 prometheus_listen_address + else + # localhost:9090 'http://' + prometheus_listen_address end end diff --git a/lib/gitlab/metrics/samplers/ruby_sampler.rb b/lib/gitlab/metrics/samplers/ruby_sampler.rb index 3bfa3da35e0..c38769f39a9 100644 --- a/lib/gitlab/metrics/samplers/ruby_sampler.rb +++ b/lib/gitlab/metrics/samplers/ruby_sampler.rb @@ -6,7 +6,7 @@ module Gitlab module Metrics module Samplers class RubySampler < BaseSampler - GC_REPORT_BUCKETS = [0.001, 0.002, 0.005, 0.01, 0.05, 0.1, 0.5].freeze + GC_REPORT_BUCKETS = [0.005, 0.01, 0.02, 0.04, 0.07, 0.1, 0.5].freeze def initialize(interval) GC::Profiler.clear diff --git a/lib/gitlab/optimistic_locking.rb b/lib/gitlab/optimistic_locking.rb index 0c0f46d3b77..d51d718c826 100644 --- a/lib/gitlab/optimistic_locking.rb +++ b/lib/gitlab/optimistic_locking.rb @@ -4,7 +4,8 @@ module Gitlab module OptimisticLocking module_function - def retry_lock(subject, retries = 100, &block) + def retry_lock(subject, retries = nil, &block) + retries ||= 100 # TODO(Observability): We should be recording details of the number of retries and the duration of the total execution here ActiveRecord::Base.transaction do yield(subject) diff --git a/lib/gitlab/tracing.rb b/lib/gitlab/tracing.rb index 29517591c51..7732d7c9d9c 100644 --- a/lib/gitlab/tracing.rb +++ b/lib/gitlab/tracing.rb @@ -30,7 +30,7 @@ module Gitlab # Avoid using `format` since it can throw TypeErrors # which we want to avoid on unsanitised env var input tracing_url_template.to_s - .gsub(/\{\{\s*correlation_id\s*\}\}/, Gitlab::CorrelationId.current_id.to_s) + .gsub(/\{\{\s*correlation_id\s*\}\}/, Labkit::Correlation::CorrelationId.current_id.to_s) .gsub(/\{\{\s*service\s*\}\}/, Gitlab.process_name) end end diff --git a/lib/system_check/incoming_email/foreman_configured_check.rb b/lib/system_check/incoming_email/foreman_configured_check.rb deleted file mode 100644 index 944913087da..00000000000 --- a/lib/system_check/incoming_email/foreman_configured_check.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true - -module SystemCheck - module IncomingEmail - class ForemanConfiguredCheck < SystemCheck::BaseCheck - set_name 'Foreman configured correctly?' - - def check? - path = Rails.root.join('Procfile') - - File.exist?(path) && File.read(path) =~ /^mail_room:/ - end - - def show_error - try_fixing_it( - 'Enable mail_room in your Procfile.' - ) - for_more_information( - 'doc/administration/reply_by_email.md' - ) - fix_and_rerun - end - end - end -end diff --git a/lib/system_check/incoming_email_check.rb b/lib/system_check/incoming_email_check.rb index 155b6547595..e0e1147711c 100644 --- a/lib/system_check/incoming_email_check.rb +++ b/lib/system_check/incoming_email_check.rb @@ -14,8 +14,6 @@ module SystemCheck if Rails.env.production? checks << SystemCheck::IncomingEmail::InitdConfiguredCheck checks << SystemCheck::IncomingEmail::MailRoomRunningCheck - else - checks << SystemCheck::IncomingEmail::ForemanConfiguredCheck end SystemCheck.run('Reply by email', checks) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index e91061e74c2..a5619079988 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -3374,15 +3374,9 @@ msgstr "" msgid "Could not add admins as members" msgstr "" -msgid "Could not add admins as members to self-monitoring project. Errors: %{errors}" -msgstr "" - msgid "Could not add prometheus URL to whitelist" msgstr "" -msgid "Could not add prometheus URL to whitelist, errors: %{errors}" -msgstr "" - msgid "Could not authorize chat nickname. Try again!" msgstr "" @@ -3398,9 +3392,6 @@ msgstr "" msgid "Could not create group" msgstr "" -msgid "Could not create instance administration project. Errors: %{errors}" -msgstr "" - msgid "Could not create project" msgstr "" @@ -3419,18 +3410,12 @@ msgstr "" msgid "Could not revoke personal access token %{personal_access_token_name}." msgstr "" -msgid "Could not save instance administration project ID, errors: %{errors}" -msgstr "" - msgid "Could not save project ID" msgstr "" msgid "Could not save prometheus manual configuration" msgstr "" -msgid "Could not save prometheus manual configuration for self-monitoring project. Errors: %{errors}" -msgstr "" - msgid "Coverage" msgstr "" @@ -5349,9 +5334,6 @@ msgstr "" msgid "GitLab.com import" msgstr "" -msgid "GitLab’s issue tracker" -msgstr "" - msgid "Gitaly" msgstr "" @@ -6098,9 +6080,6 @@ msgstr "" msgid "Instance Statistics visibility" msgstr "" -msgid "Instance administration project already exists" -msgstr "" - msgid "Instance administrators group already exists" msgstr "" @@ -6604,9 +6583,6 @@ msgstr "" msgid "Learn more" msgstr "" -msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}." -msgstr "" - msgid "Learn more about Auto DevOps" msgstr "" @@ -8206,6 +8182,9 @@ msgstr "" msgid "Pipeline|Coverage" msgstr "" +msgid "Pipeline|Detached merge request pipeline" +msgstr "" + msgid "Pipeline|Duration" msgstr "" @@ -8215,6 +8194,12 @@ msgstr "" msgid "Pipeline|Key" msgstr "" +msgid "Pipeline|Merge train pipeline" +msgstr "" + +msgid "Pipeline|Merged result pipeline" +msgstr "" + msgid "Pipeline|Pipeline" msgstr "" @@ -9202,7 +9187,7 @@ msgstr "" msgid "ProjectsNew|Want to house several dependent projects under the same namespace? %{link_start}Create a group.%{link_end}" msgstr "" -msgid "Prometheus listen_address is not a valid URI" +msgid "Prometheus listen_address in config/gitlab.yml is not a valid URI" msgstr "" msgid "PrometheusService|%{exporters} with %{metrics} were found" @@ -11571,9 +11556,6 @@ msgstr "" msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time." msgstr "" -msgid "The tabs below will be removed in a future version" -msgstr "" - msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running." msgstr "" @@ -13832,9 +13814,6 @@ msgstr "" msgid "issue" msgstr "" -msgid "issue boards" -msgstr "" - msgid "it is stored externally" msgstr "" @@ -14177,12 +14156,6 @@ msgstr "" msgid "project avatar" msgstr "" -msgid "prometheus.enable is not present in gitlab.yml" -msgstr "" - -msgid "prometheus.listen_address is not present in gitlab.yml" -msgstr "" - msgid "quick actions" msgstr "" diff --git a/package.json b/package.json index 4244dc2d52b..782bb3a96a7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "private": true, "scripts": { - "check-dependencies": "yarn check --integrity", + "check-dependencies": "scripts/frontend/check_dependencies.sh", "clean": "rm -rf public/assets tmp/cache/*-loader", "dev-server": "NODE_OPTIONS=\"--max-old-space-size=3584\" nodemon -w 'config/webpack.config.js' --exec 'webpack-dev-server --config config/webpack.config.js'", "eslint": "eslint --max-warnings 0 --report-unused-disable-directives --ext .js,.vue .", diff --git a/qa/qa/page/admin/menu.rb b/qa/qa/page/admin/menu.rb index 7c214da8486..5a18ebd7af8 100644 --- a/qa/qa/page/admin/menu.rb +++ b/qa/qa/page/admin/menu.rb @@ -11,12 +11,21 @@ module QA element :admin_settings_repository_item element :admin_settings_general_item element :admin_settings_metrics_and_profiling_item + element :admin_settings_preferences_link end view 'app/views/layouts/nav/sidebar/_admin.html.haml' do element :integration_settings_link end + def go_to_preferences_settings + hover_settings do + within_submenu do + click_element :admin_settings_preferences_link + end + end + end + def go_to_repository_settings hover_settings do within_submenu do diff --git a/qa/qa/page/settings/common.rb b/qa/qa/page/settings/common.rb index bede3fde105..2d7b41c76e1 100644 --- a/qa/qa/page/settings/common.rb +++ b/qa/qa/page/settings/common.rb @@ -11,7 +11,7 @@ module QA within_element(element_name) do # Because it is possible to click the button before the JS toggle code is bound wait(reload: false) do - click_button 'Expand' unless has_css?('button', text: 'Collapse') + click_button 'Expand' unless has_css?('button', text: 'Collapse', wait: 1) has_content?('Collapse') end diff --git a/scripts/frontend/check_dependencies.sh b/scripts/frontend/check_dependencies.sh new file mode 100755 index 00000000000..64e7cf9da52 --- /dev/null +++ b/scripts/frontend/check_dependencies.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +if ! yarn check --integrity 2>&1 > /dev/null +then + echo + echo " $(tput setaf 1)yarn check --integrity$(tput sgr0) failed!" + echo " Your dependencies probably don't match the yarn.lock file." + echo " Please run $(tput setaf 2)yarn install$(tput sgr0) and try again." + echo + exit 1 +fi diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh index 4935c1342a3..fc5b57451de 100755 --- a/scripts/review_apps/review-apps.sh +++ b/scripts/review_apps/review-apps.sh @@ -164,7 +164,7 @@ function create_application_secret() { function download_chart() { echoinfo "Downloading the GitLab chart..." true - curl -o gitlab.tar.bz2 "https://gitlab.com/charts/gitlab/-/archive/${GITLAB_HELM_CHART_REF}/gitlab-${GITLAB_HELM_CHART_REF}.tar.bz2" + curl -o gitlab.tar.bz2 "https://gitlab.com/gitlab-org/charts/gitlab/-/archive/${GITLAB_HELM_CHART_REF}/gitlab-${GITLAB_HELM_CHART_REF}.tar.bz2" tar -xjf gitlab.tar.bz2 cd "gitlab-${GITLAB_HELM_CHART_REF}" diff --git a/spec/controllers/projects/blob_controller_spec.rb b/spec/controllers/projects/blob_controller_spec.rb index 45aebd1554c..17964c78e8d 100644 --- a/spec/controllers/projects/blob_controller_spec.rb +++ b/spec/controllers/projects/blob_controller_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Projects::BlobController do include ProjectForksHelper diff --git a/spec/controllers/sent_notifications_controller_spec.rb b/spec/controllers/sent_notifications_controller_spec.rb index 89857a9d21b..fafcd6927cd 100644 --- a/spec/controllers/sent_notifications_controller_spec.rb +++ b/spec/controllers/sent_notifications_controller_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe SentNotificationsController do let(:user) { create(:user) } diff --git a/spec/factories/milestone_releases.rb b/spec/factories/milestone_releases.rb new file mode 100644 index 00000000000..08e109480ab --- /dev/null +++ b/spec/factories/milestone_releases.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :milestone_release do + milestone + release + + before(:create, :build) do |mr| + project = create(:project) + mr.milestone.project = project + mr.release.project = project + end + end +end diff --git a/spec/features/admin/admin_disables_git_access_protocol_spec.rb b/spec/features/admin/admin_disables_git_access_protocol_spec.rb index ca8874a24f9..4c3c0904a06 100644 --- a/spec/features/admin/admin_disables_git_access_protocol_spec.rb +++ b/spec/features/admin/admin_disables_git_access_protocol_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Admin disables Git access protocol', :js do include StubENV diff --git a/spec/features/admin/admin_disables_two_factor_spec.rb b/spec/features/admin/admin_disables_two_factor_spec.rb index 6e6a4964541..7227141168e 100644 --- a/spec/features/admin/admin_disables_two_factor_spec.rb +++ b/spec/features/admin/admin_disables_two_factor_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Admin disables 2FA for a user' do it 'successfully', :js do diff --git a/spec/features/admin/admin_uses_repository_checks_spec.rb b/spec/features/admin/admin_uses_repository_checks_spec.rb index 8c1ec183286..3e8197588ed 100644 --- a/spec/features/admin/admin_uses_repository_checks_spec.rb +++ b/spec/features/admin/admin_uses_repository_checks_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Admin uses repository checks' do include StubENV diff --git a/spec/features/boards/add_issues_modal_spec.rb b/spec/features/boards/add_issues_modal_spec.rb index 6e477a93293..0412dc2b69c 100644 --- a/spec/features/boards/add_issues_modal_spec.rb +++ b/spec/features/boards/add_issues_modal_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Issue Boards add issue modal', :js do let(:project) { create(:project, :public) } diff --git a/spec/features/boards/boards_spec.rb b/spec/features/boards/boards_spec.rb index 902ecdcd3e8..57dc9de62fb 100644 --- a/spec/features/boards/boards_spec.rb +++ b/spec/features/boards/boards_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Issue Boards', :js do include DragTo diff --git a/spec/features/boards/issue_ordering_spec.rb b/spec/features/boards/issue_ordering_spec.rb index c8ea202169c..62abd914fcb 100644 --- a/spec/features/boards/issue_ordering_spec.rb +++ b/spec/features/boards/issue_ordering_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Issue Boards', :js do include DragTo diff --git a/spec/features/boards/keyboard_shortcut_spec.rb b/spec/features/boards/keyboard_shortcut_spec.rb index 5f3a2c409ed..6074c559701 100644 --- a/spec/features/boards/keyboard_shortcut_spec.rb +++ b/spec/features/boards/keyboard_shortcut_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Issue Boards shortcut', :js do context 'issues are enabled' do diff --git a/spec/features/boards/modal_filter_spec.rb b/spec/features/boards/modal_filter_spec.rb index 93de2750466..70bc067f79d 100644 --- a/spec/features/boards/modal_filter_spec.rb +++ b/spec/features/boards/modal_filter_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Issue Boards add issue modal filtering', :js do let(:project) { create(:project, :public) } diff --git a/spec/features/boards/multiple_boards_spec.rb b/spec/features/boards/multiple_boards_spec.rb index 9a2b7a80498..2389707be9c 100644 --- a/spec/features/boards/multiple_boards_spec.rb +++ b/spec/features/boards/multiple_boards_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Multiple Issue Boards', :js do set(:user) { create(:user) } diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb index abbec0ea810..36743650270 100644 --- a/spec/features/boards/new_issue_spec.rb +++ b/spec/features/boards/new_issue_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Issue Boards new issue', :js do let(:project) { create(:project, :public) } diff --git a/spec/features/boards/reload_boards_on_browser_back_spec.rb b/spec/features/boards/reload_boards_on_browser_back_spec.rb index 752c8c1052d..6528b8f58bb 100644 --- a/spec/features/boards/reload_boards_on_browser_back_spec.rb +++ b/spec/features/boards/reload_boards_on_browser_back_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Ensure Boards do not show stale data on browser back', :js do let(:project) {create(:project, :public)} diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb index 7ee3a839293..8497eaf102f 100644 --- a/spec/features/boards/sidebar_spec.rb +++ b/spec/features/boards/sidebar_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Issue Boards', :js do include BoardHelpers diff --git a/spec/features/boards/sub_group_project_spec.rb b/spec/features/boards/sub_group_project_spec.rb index 264e5e85505..4384a1a9379 100644 --- a/spec/features/boards/sub_group_project_spec.rb +++ b/spec/features/boards/sub_group_project_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Sub-group project issue boards', :js do let(:group) { create(:group) } diff --git a/spec/features/commits/user_uses_quick_actions_spec.rb b/spec/features/commits/user_uses_quick_actions_spec.rb index 4b7e7465df1..70ea920b7ec 100644 --- a/spec/features/commits/user_uses_quick_actions_spec.rb +++ b/spec/features/commits/user_uses_quick_actions_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Commit > User uses quick actions', :js do include Spec::Support::Helpers::Features::NotesHelpers diff --git a/spec/features/dashboard/todos/target_state_spec.rb b/spec/features/dashboard/todos/target_state_spec.rb index 931fc16a5eb..0ea1f43e34b 100644 --- a/spec/features/dashboard/todos/target_state_spec.rb +++ b/spec/features/dashboard/todos/target_state_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Dashboard > Todo target states' do let(:user) { create(:user) } diff --git a/spec/features/groups/board_sidebar_spec.rb b/spec/features/groups/board_sidebar_spec.rb index 9f597efa7b7..ed874141ef4 100644 --- a/spec/features/groups/board_sidebar_spec.rb +++ b/spec/features/groups/board_sidebar_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Group Issue Boards', :js do include BoardHelpers diff --git a/spec/features/groups/board_spec.rb b/spec/features/groups/board_spec.rb index ca33dbb7a33..f95e2e91cd7 100644 --- a/spec/features/groups/board_spec.rb +++ b/spec/features/groups/board_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Group Boards' do let(:group) { create(:group) } diff --git a/spec/features/groups/milestone_spec.rb b/spec/features/groups/milestone_spec.rb index 7f0155b63e0..17738905e8d 100644 --- a/spec/features/groups/milestone_spec.rb +++ b/spec/features/groups/milestone_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Group milestones' do let(:group) { create(:group) } diff --git a/spec/features/groups/user_browse_projects_group_page_spec.rb b/spec/features/groups/user_browse_projects_group_page_spec.rb index 075bc1128ca..68221e3fefe 100644 --- a/spec/features/groups/user_browse_projects_group_page_spec.rb +++ b/spec/features/groups/user_browse_projects_group_page_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'User browse group projects page' do let(:user) { create :user } diff --git a/spec/features/instance_statistics/cohorts_spec.rb b/spec/features/instance_statistics/cohorts_spec.rb index 61294ec9af2..3940e8fa389 100644 --- a/spec/features/instance_statistics/cohorts_spec.rb +++ b/spec/features/instance_statistics/cohorts_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Cohorts page' do before do diff --git a/spec/features/instance_statistics/instance_statistics_spec.rb b/spec/features/instance_statistics/instance_statistics_spec.rb index 40d0f1db207..0fb78c6eef8 100644 --- a/spec/features/instance_statistics/instance_statistics_spec.rb +++ b/spec/features/instance_statistics/instance_statistics_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Cohorts page', :js do before do diff --git a/spec/features/issuables/issuable_list_spec.rb b/spec/features/issuables/issuable_list_spec.rb index dc68e633e27..30c516459c5 100644 --- a/spec/features/issuables/issuable_list_spec.rb +++ b/spec/features/issuables/issuable_list_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'issuable list' do let(:project) { create(:project) } diff --git a/spec/features/issuables/markdown_references/internal_references_spec.rb b/spec/features/issuables/markdown_references/internal_references_spec.rb index e84629dc17f..f3b534bca49 100644 --- a/spec/features/issuables/markdown_references/internal_references_spec.rb +++ b/spec/features/issuables/markdown_references/internal_references_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require "rails_helper" +require 'spec_helper' describe "Internal references", :js do include Spec::Support::Helpers::Features::NotesHelpers diff --git a/spec/features/issuables/markdown_references/jira_spec.rb b/spec/features/issuables/markdown_references/jira_spec.rb index aecdeffe4a4..8085918f533 100644 --- a/spec/features/issuables/markdown_references/jira_spec.rb +++ b/spec/features/issuables/markdown_references/jira_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require "rails_helper" +require 'spec_helper' describe "Jira", :js do let(:user) { create(:user) } diff --git a/spec/features/issuables/user_sees_sidebar_spec.rb b/spec/features/issuables/user_sees_sidebar_spec.rb index d1e10c70414..52040eb8cbb 100644 --- a/spec/features/issuables/user_sees_sidebar_spec.rb +++ b/spec/features/issuables/user_sees_sidebar_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Issue Sidebar on Mobile' do include MobileHelpers diff --git a/spec/features/issues/bulk_assignment_labels_spec.rb b/spec/features/issues/bulk_assignment_labels_spec.rb index e8b828bd264..57d04f0bf40 100644 --- a/spec/features/issues/bulk_assignment_labels_spec.rb +++ b/spec/features/issues/bulk_assignment_labels_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Issues > Labels bulk assignment' do let(:user) { create(:user) } diff --git a/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb b/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb index f2e482faf5f..7d3df711555 100644 --- a/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb +++ b/spec/features/issues/create_issue_for_discussions_in_merge_request_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Resolving all open threads in a merge request from an issue', :js do let(:user) { create(:user) } diff --git a/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb b/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb index 08c98358544..8f4083533b3 100644 --- a/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb +++ b/spec/features/issues/create_issue_for_single_discussion_in_merge_request_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Resolve an open thread in a merge request by creating an issue', :js do let(:user) { create(:user) } diff --git a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb index 2ca551cec77..e1177bedd2d 100644 --- a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Dropdown assignee', :js do include FilteredSearchHelpers diff --git a/spec/features/issues/filtered_search/dropdown_author_spec.rb b/spec/features/issues/filtered_search/dropdown_author_spec.rb index b2905fc1dde..bd22eb1056b 100644 --- a/spec/features/issues/filtered_search/dropdown_author_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_author_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Dropdown author', :js do include FilteredSearchHelpers diff --git a/spec/features/issues/filtered_search/dropdown_emoji_spec.rb b/spec/features/issues/filtered_search/dropdown_emoji_spec.rb index 45344aeb8f5..7ec3d215fb1 100644 --- a/spec/features/issues/filtered_search/dropdown_emoji_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_emoji_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Dropdown emoji', :js do include FilteredSearchHelpers diff --git a/spec/features/issues/filtered_search/dropdown_hint_spec.rb b/spec/features/issues/filtered_search/dropdown_hint_spec.rb index 34313553b34..1c56902a27d 100644 --- a/spec/features/issues/filtered_search/dropdown_hint_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_hint_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Dropdown hint', :js do include FilteredSearchHelpers diff --git a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb index 8429fe44c43..9a782950bf6 100644 --- a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb +++ b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Dropdown milestone', :js do include FilteredSearchHelpers diff --git a/spec/features/issues/filtered_search/search_bar_spec.rb b/spec/features/issues/filtered_search/search_bar_spec.rb index 0fe03160e7a..e97314e02e6 100644 --- a/spec/features/issues/filtered_search/search_bar_spec.rb +++ b/spec/features/issues/filtered_search/search_bar_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Search bar', :js do include FilteredSearchHelpers diff --git a/spec/features/issues/filtered_search/visual_tokens_spec.rb b/spec/features/issues/filtered_search/visual_tokens_spec.rb index b20add1ea33..f8035ef4b85 100644 --- a/spec/features/issues/filtered_search/visual_tokens_spec.rb +++ b/spec/features/issues/filtered_search/visual_tokens_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Visual tokens', :js do include FilteredSearchHelpers diff --git a/spec/features/issues/form_spec.rb b/spec/features/issues/form_spec.rb index e840ac79916..8d7b6be5ea2 100644 --- a/spec/features/issues/form_spec.rb +++ b/spec/features/issues/form_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'New/edit issue', :js do include ActionView::Helpers::JavaScriptHelper diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb index 566441dc6f6..cc834df367b 100644 --- a/spec/features/issues/gfm_autocomplete_spec.rb +++ b/spec/features/issues/gfm_autocomplete_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'GFM autocomplete', :js do let(:issue_xss_title) { 'This will execute alert<img src=x onerror=alert(2)<img src=x onerror=alert(1)>' } diff --git a/spec/features/issues/group_label_sidebar_spec.rb b/spec/features/issues/group_label_sidebar_spec.rb index 746c55b6a26..fe6d95e1039 100644 --- a/spec/features/issues/group_label_sidebar_spec.rb +++ b/spec/features/issues/group_label_sidebar_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Group label on issue' do it 'renders link to the project issues page' do diff --git a/spec/features/issues/issue_detail_spec.rb b/spec/features/issues/issue_detail_spec.rb index 8f2e5b237ea..a1b53718577 100644 --- a/spec/features/issues/issue_detail_spec.rb +++ b/spec/features/issues/issue_detail_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Issue Detail', :js do let(:user) { create(:user) } diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb index b88d1bbeae5..9baba80bf06 100644 --- a/spec/features/issues/issue_sidebar_spec.rb +++ b/spec/features/issues/issue_sidebar_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Issue Sidebar' do include MobileHelpers diff --git a/spec/features/issues/keyboard_shortcut_spec.rb b/spec/features/issues/keyboard_shortcut_spec.rb index e1325e63e6b..c5d53cd1cd0 100644 --- a/spec/features/issues/keyboard_shortcut_spec.rb +++ b/spec/features/issues/keyboard_shortcut_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Issues shortcut', :js do context 'New Issue shortcut' do diff --git a/spec/features/issues/markdown_toolbar_spec.rb b/spec/features/issues/markdown_toolbar_spec.rb index b80b47a4c99..d174fdcb25e 100644 --- a/spec/features/issues/markdown_toolbar_spec.rb +++ b/spec/features/issues/markdown_toolbar_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Issue markdown toolbar', :js do let(:project) { create(:project, :public) } diff --git a/spec/features/issues/move_spec.rb b/spec/features/issues/move_spec.rb index 9e0be7d8935..1122504248f 100644 --- a/spec/features/issues/move_spec.rb +++ b/spec/features/issues/move_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'issue move to another project' do let(:user) { create(:user) } diff --git a/spec/features/issues/resource_label_events_spec.rb b/spec/features/issues/resource_label_events_spec.rb index 3d380c183ec..b367bbe2c99 100644 --- a/spec/features/issues/resource_label_events_spec.rb +++ b/spec/features/issues/resource_label_events_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'List issue resource label events', :js do let(:user) { create(:user) } diff --git a/spec/features/issues/spam_issues_spec.rb b/spec/features/issues/spam_issues_spec.rb index 85c72c42f45..0d009f47fff 100644 --- a/spec/features/issues/spam_issues_spec.rb +++ b/spec/features/issues/spam_issues_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'New issue', :js do include StubENV diff --git a/spec/features/issues/todo_spec.rb b/spec/features/issues/todo_spec.rb index 9282c31751a..4bb96ad069c 100644 --- a/spec/features/issues/todo_spec.rb +++ b/spec/features/issues/todo_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Manually create a todo item from issue', :js do let!(:project) { create(:project) } diff --git a/spec/features/issues/update_issues_spec.rb b/spec/features/issues/update_issues_spec.rb index 0e27d0231d0..45a0b1932a2 100644 --- a/spec/features/issues/update_issues_spec.rb +++ b/spec/features/issues/update_issues_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Multiple issue updating from issues#index', :js do let!(:project) { create(:project) } diff --git a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb index 878a73718d7..be31c45b373 100644 --- a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb +++ b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'User creates branch and merge request on issue page', :js do let(:membership_level) { :developer } diff --git a/spec/features/issues/user_creates_confidential_merge_request_spec.rb b/spec/features/issues/user_creates_confidential_merge_request_spec.rb index 4a32b7e2b73..24089bdeb81 100644 --- a/spec/features/issues/user_creates_confidential_merge_request_spec.rb +++ b/spec/features/issues/user_creates_confidential_merge_request_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'User creates confidential merge request on issue page', :js do include ProjectForksHelper diff --git a/spec/features/issues/user_sees_breadcrumb_links_spec.rb b/spec/features/issues/user_sees_breadcrumb_links_spec.rb index db8d3c5dd53..f31d730c337 100644 --- a/spec/features/issues/user_sees_breadcrumb_links_spec.rb +++ b/spec/features/issues/user_sees_breadcrumb_links_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'New issue breadcrumb' do let(:project) { create(:project) } diff --git a/spec/features/issues/user_uses_quick_actions_spec.rb b/spec/features/issues/user_uses_quick_actions_spec.rb index 8fec92031a9..26979e943d0 100644 --- a/spec/features/issues/user_uses_quick_actions_spec.rb +++ b/spec/features/issues/user_uses_quick_actions_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' # These are written as feature specs because they cover more specific test scenarios # than the ones described on spec/services/notes/create_service_spec.rb for quick actions, diff --git a/spec/features/merge_request/user_assigns_themselves_spec.rb b/spec/features/merge_request/user_assigns_themselves_spec.rb index d7918a9e9d7..549d6e50337 100644 --- a/spec/features/merge_request/user_assigns_themselves_spec.rb +++ b/spec/features/merge_request/user_assigns_themselves_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User assigns themselves' do let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_awards_emoji_spec.rb b/spec/features/merge_request/user_awards_emoji_spec.rb index 5e9b232760b..8aa90107251 100644 --- a/spec/features/merge_request/user_awards_emoji_spec.rb +++ b/spec/features/merge_request/user_awards_emoji_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User awards emoji', :js do let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_creates_mr_spec.rb b/spec/features/merge_request/user_creates_mr_spec.rb index 267097bd466..665bc352c0f 100644 --- a/spec/features/merge_request/user_creates_mr_spec.rb +++ b/spec/features/merge_request/user_creates_mr_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User creates MR' do include ProjectForksHelper diff --git a/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb b/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb index 3213efcb60b..895cbb8f02b 100644 --- a/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb +++ b/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request < User customizes merge commit message', :js do let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_locks_discussion_spec.rb b/spec/features/merge_request/user_locks_discussion_spec.rb index 365e9b60d90..0eaaf32dc31 100644 --- a/spec/features/merge_request/user_locks_discussion_spec.rb +++ b/spec/features/merge_request/user_locks_discussion_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User locks discussion', :js do let(:user) { create(:user) } diff --git a/spec/features/merge_request/user_merges_immediately_spec.rb b/spec/features/merge_request/user_merges_immediately_spec.rb index 2f01971c2e9..1188d3b2ceb 100644 --- a/spec/features/merge_request/user_merges_immediately_spec.rb +++ b/spec/features/merge_request/user_merges_immediately_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge requests > User merges immediately', :js do let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb index 3f9c27bbf9d..4afbf30ece4 100644 --- a/spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb +++ b/spec/features/merge_request/user_merges_only_if_pipeline_succeeds_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User merges only if pipeline succeeds', :js do let(:merge_request) { create(:merge_request_with_diffs) } diff --git a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb index 93938ac221a..ffc12ffdbaf 100644 --- a/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb +++ b/spec/features/merge_request/user_merges_when_pipeline_succeeds_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User merges when pipeline succeeds', :js do let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_posts_diff_notes_spec.rb b/spec/features/merge_request/user_posts_diff_notes_spec.rb index abae6ffbd71..8b16760606c 100644 --- a/spec/features/merge_request/user_posts_diff_notes_spec.rb +++ b/spec/features/merge_request/user_posts_diff_notes_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User posts diff notes', :js do include MergeRequestDiffHelpers diff --git a/spec/features/merge_request/user_posts_notes_spec.rb b/spec/features/merge_request/user_posts_notes_spec.rb index 1fad9eac1bd..435b3cd2555 100644 --- a/spec/features/merge_request/user_posts_notes_spec.rb +++ b/spec/features/merge_request/user_posts_notes_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User posts notes', :js do include NoteInteractionHelpers diff --git a/spec/features/merge_request/user_resolves_conflicts_spec.rb b/spec/features/merge_request/user_resolves_conflicts_spec.rb index fb089a9ffcb..dd1ec17ae51 100644 --- a/spec/features/merge_request/user_resolves_conflicts_spec.rb +++ b/spec/features/merge_request/user_resolves_conflicts_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User resolves conflicts', :js do let(:project) { create(:project, :repository) } diff --git a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb index b8e4852a748..8b41ef86791 100644 --- a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb +++ b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User resolves diff notes and threads', :js do let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb b/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb index 23b37c218e1..48c3ed7178d 100644 --- a/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb +++ b/spec/features/merge_request/user_scrolls_to_note_on_load_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User scrolls to note on load', :js do let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb b/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb index fae81758086..baef831c40e 100644 --- a/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb +++ b/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees avatars on diff notes', :js do include NoteInteractionHelpers diff --git a/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb b/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb index e1f0ddc4c6a..592ad3aae9b 100644 --- a/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb +++ b/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'New merge request breadcrumb' do let(:project) { create(:project, :repository) } diff --git a/spec/features/merge_request/user_sees_check_out_branch_modal_spec.rb b/spec/features/merge_request/user_sees_check_out_branch_modal_spec.rb index 93ae408a173..f54161fbaec 100644 --- a/spec/features/merge_request/user_sees_check_out_branch_modal_spec.rb +++ b/spec/features/merge_request/user_sees_check_out_branch_modal_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees check out branch modal', :js do let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb b/spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb index 8a2614c53af..1d62f7f0702 100644 --- a/spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb +++ b/spec/features/merge_request/user_sees_cherry_pick_modal_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User cherry-picks', :js do let(:group) { create(:group) } diff --git a/spec/features/merge_request/user_sees_closing_issues_message_spec.rb b/spec/features/merge_request/user_sees_closing_issues_message_spec.rb index 52163571175..f77ea82649c 100644 --- a/spec/features/merge_request/user_sees_closing_issues_message_spec.rb +++ b/spec/features/merge_request/user_sees_closing_issues_message_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees closing issues message', :js do let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_sees_deleted_target_branch_spec.rb b/spec/features/merge_request/user_sees_deleted_target_branch_spec.rb index f46921af1cd..224261dec00 100644 --- a/spec/features/merge_request/user_sees_deleted_target_branch_spec.rb +++ b/spec/features/merge_request/user_sees_deleted_target_branch_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees deleted target branch', :js do let(:merge_request) { create(:merge_request) } diff --git a/spec/features/merge_request/user_sees_deployment_widget_spec.rb b/spec/features/merge_request/user_sees_deployment_widget_spec.rb index 14fbfc2fd3f..87fb3f5b3e7 100644 --- a/spec/features/merge_request/user_sees_deployment_widget_spec.rb +++ b/spec/features/merge_request/user_sees_deployment_widget_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees deployment widget', :js do describe 'when merge request has associated environments' do diff --git a/spec/features/merge_request/user_sees_diff_spec.rb b/spec/features/merge_request/user_sees_diff_spec.rb index 32429bac5f9..8eeed7b0843 100644 --- a/spec/features/merge_request/user_sees_diff_spec.rb +++ b/spec/features/merge_request/user_sees_diff_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees diff', :js do include ProjectForksHelper diff --git a/spec/features/merge_request/user_sees_discussions_spec.rb b/spec/features/merge_request/user_sees_discussions_spec.rb index a11baf1dca3..48f5814322a 100644 --- a/spec/features/merge_request/user_sees_discussions_spec.rb +++ b/spec/features/merge_request/user_sees_discussions_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees threads', :js do let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_sees_empty_state_spec.rb b/spec/features/merge_request/user_sees_empty_state_spec.rb index f1ad5c2dffc..88eba976d62 100644 --- a/spec/features/merge_request/user_sees_empty_state_spec.rb +++ b/spec/features/merge_request/user_sees_empty_state_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees empty state' do let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_sees_merge_button_depending_on_unresolved_discussions_spec.rb b/spec/features/merge_request/user_sees_merge_button_depending_on_unresolved_discussions_spec.rb index 53cafb60dfb..4cc129e5d5f 100644 --- a/spec/features/merge_request/user_sees_merge_button_depending_on_unresolved_discussions_spec.rb +++ b/spec/features/merge_request/user_sees_merge_button_depending_on_unresolved_discussions_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees merge button depending on unresolved threads', :js do let(:project) { create(:project, :repository) } diff --git a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb index 28f88718ec1..dd5662d83f2 100644 --- a/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb +++ b/spec/features/merge_request/user_sees_merge_request_pipelines_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees pipelines triggered by merge request', :js do include ProjectForksHelper diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb index b5d0240e9de..3f2a676462b 100644 --- a/spec/features/merge_request/user_sees_merge_widget_spec.rb +++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees merge widget', :js do include ProjectForksHelper diff --git a/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb b/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb index eb89d616b14..4d801c6ff11 100644 --- a/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb +++ b/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request < User sees mini pipeline graph', :js do let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb b/spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb index 80ee35f2a91..b4fb844b943 100644 --- a/spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb +++ b/spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees MR from deleted forked project', :js do include ProjectForksHelper diff --git a/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb b/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb index d9dc32d0594..db0d632cdf2 100644 --- a/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb +++ b/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' # This test serves as a regression test for a bug that caused an error # message to be shown by JavaScript when the source branch was deleted. diff --git a/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb b/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb index 195592531f2..0391794649c 100644 --- a/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb +++ b/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees notes from forked project', :js do include ProjectForksHelper diff --git a/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb b/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb index 68c9e0b123d..3e15a9c136b 100644 --- a/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb +++ b/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees pipelines from forked project', :js do include ProjectForksHelper diff --git a/spec/features/merge_request/user_sees_pipelines_spec.rb b/spec/features/merge_request/user_sees_pipelines_spec.rb index e057f59e00c..f04317a59ee 100644 --- a/spec/features/merge_request/user_sees_pipelines_spec.rb +++ b/spec/features/merge_request/user_sees_pipelines_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees pipelines', :js do describe 'pipeline tab' do diff --git a/spec/features/merge_request/user_sees_system_notes_spec.rb b/spec/features/merge_request/user_sees_system_notes_spec.rb index 26cdd5ba21c..0482458d5ac 100644 --- a/spec/features/merge_request/user_sees_system_notes_spec.rb +++ b/spec/features/merge_request/user_sees_system_notes_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees system notes', :js do let(:public_project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_sees_versions_spec.rb b/spec/features/merge_request/user_sees_versions_spec.rb index dae5845adec..62abcff7bda 100644 --- a/spec/features/merge_request/user_sees_versions_spec.rb +++ b/spec/features/merge_request/user_sees_versions_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees versions', :js do let(:merge_request) do diff --git a/spec/features/merge_request/user_sees_wip_help_message_spec.rb b/spec/features/merge_request/user_sees_wip_help_message_spec.rb index 46209237faf..1179303171c 100644 --- a/spec/features/merge_request/user_sees_wip_help_message_spec.rb +++ b/spec/features/merge_request/user_sees_wip_help_message_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees WIP help message' do let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb b/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb index a1f027cbb1d..6262f1ce055 100644 --- a/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb +++ b/spec/features/merge_request/user_selects_branches_for_new_mr_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User selects branches for new MR', :js do let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/merge_request/user_toggles_whitespace_changes_spec.rb b/spec/features/merge_request/user_toggles_whitespace_changes_spec.rb index 61b9904dde5..4db067a4e41 100644 --- a/spec/features/merge_request/user_toggles_whitespace_changes_spec.rb +++ b/spec/features/merge_request/user_toggles_whitespace_changes_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User toggles whitespace changes', :js do let(:merge_request) { create(:merge_request) } diff --git a/spec/features/merge_request/user_uses_quick_actions_spec.rb b/spec/features/merge_request/user_uses_quick_actions_spec.rb index 3948c0c5c89..318f8812263 100644 --- a/spec/features/merge_request/user_uses_quick_actions_spec.rb +++ b/spec/features/merge_request/user_uses_quick_actions_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' # These are written as feature specs because they cover more specific test scenarios # than the ones described on spec/services/notes/create_service_spec.rb for quick actions, diff --git a/spec/features/merge_requests/filters_generic_behavior_spec.rb b/spec/features/merge_requests/filters_generic_behavior_spec.rb index 404e591cf4b..58aad1b7e91 100644 --- a/spec/features/merge_requests/filters_generic_behavior_spec.rb +++ b/spec/features/merge_requests/filters_generic_behavior_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge Requests > Filters generic behavior', :js do include FilteredSearchHelpers diff --git a/spec/features/merge_requests/user_filters_by_assignees_spec.rb b/spec/features/merge_requests/user_filters_by_assignees_spec.rb index b896b6392f1..00bd8455ae1 100644 --- a/spec/features/merge_requests/user_filters_by_assignees_spec.rb +++ b/spec/features/merge_requests/user_filters_by_assignees_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge Requests > User filters by assignees', :js do include FilteredSearchHelpers diff --git a/spec/features/merge_requests/user_filters_by_labels_spec.rb b/spec/features/merge_requests/user_filters_by_labels_spec.rb index 9fb149ca58d..fd2b4b23f96 100644 --- a/spec/features/merge_requests/user_filters_by_labels_spec.rb +++ b/spec/features/merge_requests/user_filters_by_labels_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge Requests > User filters by labels', :js do include FilteredSearchHelpers diff --git a/spec/features/merge_requests/user_filters_by_milestones_spec.rb b/spec/features/merge_requests/user_filters_by_milestones_spec.rb index 2fb3c86ea94..e0ee69d7a5b 100644 --- a/spec/features/merge_requests/user_filters_by_milestones_spec.rb +++ b/spec/features/merge_requests/user_filters_by_milestones_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge Requests > User filters by milestones', :js do include FilteredSearchHelpers diff --git a/spec/features/merge_requests/user_filters_by_multiple_criteria_spec.rb b/spec/features/merge_requests/user_filters_by_multiple_criteria_spec.rb index 3dd0f93ddfa..bc6e2ac5132 100644 --- a/spec/features/merge_requests/user_filters_by_multiple_criteria_spec.rb +++ b/spec/features/merge_requests/user_filters_by_multiple_criteria_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge requests > User filters by multiple criteria', :js do include FilteredSearchHelpers diff --git a/spec/features/merge_requests/user_filters_by_target_branch_spec.rb b/spec/features/merge_requests/user_filters_by_target_branch_spec.rb index b5969f656b0..0d03c5eae31 100644 --- a/spec/features/merge_requests/user_filters_by_target_branch_spec.rb +++ b/spec/features/merge_requests/user_filters_by_target_branch_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge Requests > User filters by target branch', :js do include FilteredSearchHelpers diff --git a/spec/features/merge_requests/user_lists_merge_requests_spec.rb b/spec/features/merge_requests/user_lists_merge_requests_spec.rb index 69d4650d1ac..f145bdd044b 100644 --- a/spec/features/merge_requests/user_lists_merge_requests_spec.rb +++ b/spec/features/merge_requests/user_lists_merge_requests_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge requests > User lists merge requests' do include MergeRequestHelpers diff --git a/spec/features/merge_requests/user_mass_updates_spec.rb b/spec/features/merge_requests/user_mass_updates_spec.rb index 48c92a87c63..4d3461bf1ae 100644 --- a/spec/features/merge_requests/user_mass_updates_spec.rb +++ b/spec/features/merge_requests/user_mass_updates_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge requests > User mass updates', :js do let(:project) { create(:project, :repository) } diff --git a/spec/features/milestone_spec.rb b/spec/features/milestone_spec.rb index 6d5acc894b1..bfff33f3956 100644 --- a/spec/features/milestone_spec.rb +++ b/spec/features/milestone_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Milestone' do let(:group) { create(:group, :public) } diff --git a/spec/features/milestones/user_creates_milestone_spec.rb b/spec/features/milestones/user_creates_milestone_spec.rb index 73f4f187501..5c93ddcf6f8 100644 --- a/spec/features/milestones/user_creates_milestone_spec.rb +++ b/spec/features/milestones/user_creates_milestone_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require "rails_helper" +require 'spec_helper' describe "User creates milestone", :js do set(:user) { create(:user) } diff --git a/spec/features/milestones/user_deletes_milestone_spec.rb b/spec/features/milestones/user_deletes_milestone_spec.rb index 5666c1dd507..7c1d88f7798 100644 --- a/spec/features/milestones/user_deletes_milestone_spec.rb +++ b/spec/features/milestones/user_deletes_milestone_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require "rails_helper" +require 'spec_helper' describe "User deletes milestone", :js do let(:user) { create(:user) } diff --git a/spec/features/milestones/user_edits_milestone_spec.rb b/spec/features/milestones/user_edits_milestone_spec.rb index f8e96eac3ea..b41b8f3282f 100644 --- a/spec/features/milestones/user_edits_milestone_spec.rb +++ b/spec/features/milestones/user_edits_milestone_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require "rails_helper" +require 'spec_helper' describe "User edits milestone", :js do set(:user) { create(:user) } diff --git a/spec/features/milestones/user_promotes_milestone_spec.rb b/spec/features/milestones/user_promotes_milestone_spec.rb index acceb5cad62..7678b6cbfa5 100644 --- a/spec/features/milestones/user_promotes_milestone_spec.rb +++ b/spec/features/milestones/user_promotes_milestone_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'User promotes milestone' do set(:group) { create(:group) } diff --git a/spec/features/milestones/user_sees_breadcrumb_links_spec.rb b/spec/features/milestones/user_sees_breadcrumb_links_spec.rb index f58242759cc..92445735328 100644 --- a/spec/features/milestones/user_sees_breadcrumb_links_spec.rb +++ b/spec/features/milestones/user_sees_breadcrumb_links_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'New project milestone breadcrumb' do let(:project) { create(:project) } diff --git a/spec/features/milestones/user_views_milestone_spec.rb b/spec/features/milestones/user_views_milestone_spec.rb index aa0cdf66b75..71abb195ad1 100644 --- a/spec/features/milestones/user_views_milestone_spec.rb +++ b/spec/features/milestones/user_views_milestone_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require "rails_helper" +require 'spec_helper' describe "User views milestone" do set(:user) { create(:user) } diff --git a/spec/features/milestones/user_views_milestones_spec.rb b/spec/features/milestones/user_views_milestones_spec.rb index 6868791f584..0b51ca12997 100644 --- a/spec/features/milestones/user_views_milestones_spec.rb +++ b/spec/features/milestones/user_views_milestones_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require "rails_helper" +require 'spec_helper' describe "User views milestones" do set(:user) { create(:user) } diff --git a/spec/features/profiles/account_spec.rb b/spec/features/profiles/account_spec.rb index 741e41adbf1..c6db15065f2 100644 --- a/spec/features/profiles/account_spec.rb +++ b/spec/features/profiles/account_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Profile > Account', :js do let(:user) { create(:user, username: 'foo') } diff --git a/spec/features/profiles/active_sessions_spec.rb b/spec/features/profiles/active_sessions_spec.rb index 709cca7d178..a5c2d15f598 100644 --- a/spec/features/profiles/active_sessions_spec.rb +++ b/spec/features/profiles/active_sessions_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Profile > Active Sessions', :clean_gitlab_redis_shared_state do let(:user) do diff --git a/spec/features/profiles/chat_names_spec.rb b/spec/features/profiles/chat_names_spec.rb index 0219dacbc38..4c447faf77e 100644 --- a/spec/features/profiles/chat_names_spec.rb +++ b/spec/features/profiles/chat_names_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Profile > Chat' do let(:user) { create(:user) } diff --git a/spec/features/profiles/emails_spec.rb b/spec/features/profiles/emails_spec.rb index 40e2988730b..4d2cd0f8b56 100644 --- a/spec/features/profiles/emails_spec.rb +++ b/spec/features/profiles/emails_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Profile > Emails' do let(:user) { create(:user) } diff --git a/spec/features/profiles/gpg_keys_spec.rb b/spec/features/profiles/gpg_keys_spec.rb index 4237f037c27..07e87f36c65 100644 --- a/spec/features/profiles/gpg_keys_spec.rb +++ b/spec/features/profiles/gpg_keys_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Profile > GPG Keys' do let(:user) { create(:user, email: GpgHelpers::User2.emails.first) } diff --git a/spec/features/profiles/keys_spec.rb b/spec/features/profiles/keys_spec.rb index c1b142c4e12..3fc0fd76d2e 100644 --- a/spec/features/profiles/keys_spec.rb +++ b/spec/features/profiles/keys_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Profile > SSH Keys' do let(:user) { create(:user) } diff --git a/spec/features/projects/commit/mini_pipeline_graph_spec.rb b/spec/features/projects/commit/mini_pipeline_graph_spec.rb index 1199a3bd226..3d9fcfe0f62 100644 --- a/spec/features/projects/commit/mini_pipeline_graph_spec.rb +++ b/spec/features/projects/commit/mini_pipeline_graph_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Mini Pipeline Graph in Commit View', :js do let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/projects/labels/user_sees_breadcrumb_links_spec.rb b/spec/features/projects/labels/user_sees_breadcrumb_links_spec.rb index 35c84204910..68a924e4fad 100644 --- a/spec/features/projects/labels/user_sees_breadcrumb_links_spec.rb +++ b/spec/features/projects/labels/user_sees_breadcrumb_links_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'New project label breadcrumb' do let(:project) { create(:project) } diff --git a/spec/features/projects/settings/lfs_settings_spec.rb b/spec/features/projects/settings/lfs_settings_spec.rb index 56606df5a78..5fa3b9bba55 100644 --- a/spec/features/projects/settings/lfs_settings_spec.rb +++ b/spec/features/projects/settings/lfs_settings_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Projects > Settings > LFS settings' do let(:project) { create(:project) } diff --git a/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb b/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb index 9c77a08718e..3e9bfed1e47 100644 --- a/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb +++ b/spec/features/projects/settings/user_sees_revoke_deploy_token_modal_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Repository Settings > User sees revoke deploy token modal', :js do let(:project) { create(:project, :public, :repository) } diff --git a/spec/features/projects/show/developer_views_empty_project_instructions_spec.rb b/spec/features/projects/show/developer_views_empty_project_instructions_spec.rb index 6f176c260a2..70dc6c966ba 100644 --- a/spec/features/projects/show/developer_views_empty_project_instructions_spec.rb +++ b/spec/features/projects/show/developer_views_empty_project_instructions_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Projects > Show > Developer views empty project instructions' do let(:project) { create(:project, :empty_repo) } diff --git a/spec/features/projects/snippets/create_snippet_spec.rb b/spec/features/projects/snippets/create_snippet_spec.rb index 430883fdf29..891b780a100 100644 --- a/spec/features/projects/snippets/create_snippet_spec.rb +++ b/spec/features/projects/snippets/create_snippet_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Projects > Snippets > Create Snippet', :js do include DropzoneHelper diff --git a/spec/features/projects/tags/user_edits_tags_spec.rb b/spec/features/projects/tags/user_edits_tags_spec.rb index ebb2844d17f..63f97eeb4e0 100644 --- a/spec/features/projects/tags/user_edits_tags_spec.rb +++ b/spec/features/projects/tags/user_edits_tags_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Project > Tags', :js do include DropzoneHelper diff --git a/spec/features/read_only_spec.rb b/spec/features/read_only_spec.rb index 3af4b51b9b1..619d34ebed4 100644 --- a/spec/features/read_only_spec.rb +++ b/spec/features/read_only_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'read-only message' do set(:user) { create(:user) } diff --git a/spec/features/security/group/internal_access_spec.rb b/spec/features/security/group/internal_access_spec.rb index f4f3872aa09..d6575ec9de1 100644 --- a/spec/features/security/group/internal_access_spec.rb +++ b/spec/features/security/group/internal_access_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Internal Group access' do include AccessMatchers diff --git a/spec/features/security/group/private_access_spec.rb b/spec/features/security/group/private_access_spec.rb index 9cef8ef777c..2dc863a6e73 100644 --- a/spec/features/security/group/private_access_spec.rb +++ b/spec/features/security/group/private_access_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Private Group access' do include AccessMatchers diff --git a/spec/features/security/group/public_access_spec.rb b/spec/features/security/group/public_access_spec.rb index bbe74f0dab0..4066a19fce2 100644 --- a/spec/features/security/group/public_access_spec.rb +++ b/spec/features/security/group/public_access_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Public Group access' do include AccessMatchers diff --git a/spec/features/snippets/explore_spec.rb b/spec/features/snippets/explore_spec.rb index b48a5691e96..57e91fea709 100644 --- a/spec/features/snippets/explore_spec.rb +++ b/spec/features/snippets/explore_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Explore Snippets' do let!(:public_snippet) { create(:personal_snippet, :public) } diff --git a/spec/features/snippets/internal_snippet_spec.rb b/spec/features/snippets/internal_snippet_spec.rb index 8454a347382..4ef3b0e5e7a 100644 --- a/spec/features/snippets/internal_snippet_spec.rb +++ b/spec/features/snippets/internal_snippet_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Internal Snippets', :js do let(:internal_snippet) { create(:personal_snippet, :internal) } diff --git a/spec/features/snippets/public_snippets_spec.rb b/spec/features/snippets/public_snippets_spec.rb index e32a9292e22..a0db00cfc67 100644 --- a/spec/features/snippets/public_snippets_spec.rb +++ b/spec/features/snippets/public_snippets_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Public Snippets', :js do it 'Unauthenticated user should see public snippets' do diff --git a/spec/features/snippets/search_snippets_spec.rb b/spec/features/snippets/search_snippets_spec.rb index bbdf544bd0c..dce790e5708 100644 --- a/spec/features/snippets/search_snippets_spec.rb +++ b/spec/features/snippets/search_snippets_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Search Snippets' do it 'User searches for snippets by title' do diff --git a/spec/features/snippets/user_creates_snippet_spec.rb b/spec/features/snippets/user_creates_snippet_spec.rb index a4a5407d1f7..52ec5eddd5c 100644 --- a/spec/features/snippets/user_creates_snippet_spec.rb +++ b/spec/features/snippets/user_creates_snippet_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'User creates snippet', :js do include DropzoneHelper diff --git a/spec/features/snippets/user_deletes_snippet_spec.rb b/spec/features/snippets/user_deletes_snippet_spec.rb index 9773aca849a..217419a220a 100644 --- a/spec/features/snippets/user_deletes_snippet_spec.rb +++ b/spec/features/snippets/user_deletes_snippet_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'User deletes snippet' do let(:user) { create(:user) } diff --git a/spec/features/snippets/user_edits_snippet_spec.rb b/spec/features/snippets/user_edits_snippet_spec.rb index 5ff12c37aff..51d9baf44bc 100644 --- a/spec/features/snippets/user_edits_snippet_spec.rb +++ b/spec/features/snippets/user_edits_snippet_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'User edits snippet', :js do include DropzoneHelper diff --git a/spec/features/snippets/user_snippets_spec.rb b/spec/features/snippets/user_snippets_spec.rb index 4e9215db945..c6daa19d5e6 100644 --- a/spec/features/snippets/user_snippets_spec.rb +++ b/spec/features/snippets/user_snippets_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'User Snippets' do let(:author) { create(:user) } diff --git a/spec/features/uploads/user_uploads_avatar_to_group_spec.rb b/spec/features/uploads/user_uploads_avatar_to_group_spec.rb index 40d864e0002..d9d9d7e4b04 100644 --- a/spec/features/uploads/user_uploads_avatar_to_group_spec.rb +++ b/spec/features/uploads/user_uploads_avatar_to_group_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'User uploads avatar to group' do it 'they see the new avatar' do diff --git a/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb b/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb index 4c694365e3b..fc31d7aa3d1 100644 --- a/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb +++ b/spec/features/uploads/user_uploads_avatar_to_profile_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'User uploads avatar to profile' do let!(:user) { create(:user) } diff --git a/spec/features/uploads/user_uploads_file_to_note_spec.rb b/spec/features/uploads/user_uploads_file_to_note_spec.rb index 6bf8e8ea74f..30b5cf267ae 100644 --- a/spec/features/uploads/user_uploads_file_to_note_spec.rb +++ b/spec/features/uploads/user_uploads_file_to_note_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'User uploads file to note' do include DropzoneHelper diff --git a/spec/features/user_can_display_performance_bar_spec.rb b/spec/features/user_can_display_performance_bar_spec.rb index b2036108d42..154e948015f 100644 --- a/spec/features/user_can_display_performance_bar_spec.rb +++ b/spec/features/user_can_display_performance_bar_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'User can display performance bar', :js do shared_examples 'performance bar cannot be displayed' do diff --git a/spec/features/user_sees_revert_modal_spec.rb b/spec/features/user_sees_revert_modal_spec.rb index 35828b5f086..24b4f8dd4aa 100644 --- a/spec/features/user_sees_revert_modal_spec.rb +++ b/spec/features/user_sees_revert_modal_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'Merge request > User sees revert modal', :js do let(:project) { create(:project, :public, :repository) } diff --git a/spec/fixtures/api/schemas/pipeline.json b/spec/fixtures/api/schemas/pipeline.json index b6e30c40f13..d9ffad8fbab 100644 --- a/spec/fixtures/api/schemas/pipeline.json +++ b/spec/fixtures/api/schemas/pipeline.json @@ -97,6 +97,10 @@ "id": "/properties/details/properties/finished_at", "type": "string" }, + "name": { + "id": "/properties/details/properties/name", + "type": "string" + }, "manual_actions": { "id": "/properties/details/properties/manual_actions", "items": {}, @@ -323,6 +327,10 @@ "id": "/properties/web_url", "type": "string" }, + "merge_request_event_type": { + "id": "/properties/merge_request_event_type", + "type": "string" + }, "user": { "id": "/properties/user", "properties": { diff --git a/spec/fixtures/api/schemas/public_api/v4/release.json b/spec/fixtures/api/schemas/public_api/v4/release.json index ec3fa59cdb1..078b1c0b982 100644 --- a/spec/fixtures/api/schemas/public_api/v4/release.json +++ b/spec/fixtures/api/schemas/public_api/v4/release.json @@ -15,6 +15,7 @@ "author": { "oneOf": [{ "type": "null" }, { "$ref": "user/basic.json" }] }, + "milestone": { "type": "string" }, "assets": { "required": ["count", "links", "sources"], "properties": { diff --git a/spec/frontend/branches/divergence_graph_spec.js b/spec/frontend/branches/divergence_graph_spec.js index 8283bc966e4..adf39a2216a 100644 --- a/spec/frontend/branches/divergence_graph_spec.js +++ b/spec/frontend/branches/divergence_graph_spec.js @@ -25,13 +25,25 @@ describe('Divergence graph', () => { mock.restore(); }); - it('calls axos get with list of branch names', () => + it('calls axios get with list of branch names', () => init('/-/diverging_counts').then(() => { expect(axios.get).toHaveBeenCalledWith('/-/diverging_counts', { params: { names: ['master', 'test/hello-world'] }, }); })); + describe('no branches listed', () => { + beforeEach(() => { + document.body.innerHTML = `<div></div>`; + }); + + it('avoids requesting diverging commit counts', () => { + expect(axios.get).not.toHaveBeenCalledWith('/-/diverging_counts'); + + init('/-/diverging_counts'); + }); + }); + it('creates Vue components', () => init('/-/diverging_counts').then(() => { expect(document.querySelector('[data-name="master"]').innerHTML).not.toEqual(''); diff --git a/spec/frontend/jobs/store/utils_spec.js b/spec/frontend/jobs/store/utils_spec.js new file mode 100644 index 00000000000..9e81558f8c2 --- /dev/null +++ b/spec/frontend/jobs/store/utils_spec.js @@ -0,0 +1,60 @@ +import linesParser from '~/jobs/store/utils'; + +describe('linesParser', () => { + const mockData = [ + { + offset: 1001, + content: [{ text: ' on docker-auto-scale-com 8a6210b8' }], + }, + { + offset: 1002, + content: [ + { + text: + 'Using Docker executor with image dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.22-chrome-73.0-node-12.x-yarn-1.16-postgresql-9.6-graphicsmagick-1.3.33', + }, + ], + sections: ['prepare-executor'], + section_header: true, + }, + { + offset: 1003, + content: [{ text: 'Starting service postgres:9.6.14 ...' }], + sections: ['prepare-executor'], + }, + { + offset: 1004, + content: [{ text: 'Pulling docker image postgres:9.6.14 ...', style: 'term-fg-l-green' }], + sections: ['prepare-executor'], + }, + ]; + + let result; + + beforeEach(() => { + result = linesParser(mockData); + }); + + describe('regular line', () => { + it('adds a lineNumber property with correct index', () => { + expect(result[0].lineNumber).toEqual(0); + expect(result[1].line.lineNumber).toEqual(1); + }); + }); + + describe('collpasible section', () => { + it('adds a `isClosed` property', () => { + expect(result[1].isClosed).toEqual(true); + }); + + it('adds a `isHeader` property', () => { + expect(result[1].isHeader).toEqual(true); + }); + + it('creates a lines array property with the content of the collpasible section', () => { + expect(result[1].lines.length).toEqual(2); + expect(result[1].lines[0].content).toEqual(mockData[2].content); + expect(result[1].lines[1].content).toEqual(mockData[3].content); + }); + }); +}); diff --git a/spec/frontend/mocks/ce/lib/utils/axios_utils.js b/spec/frontend/mocks/ce/lib/utils/axios_utils.js index b4065626b09..a3783b91f95 100644 --- a/spec/frontend/mocks/ce/lib/utils/axios_utils.js +++ b/spec/frontend/mocks/ce/lib/utils/axios_utils.js @@ -6,9 +6,10 @@ axios.isMock = true; axios.defaults.adapter = config => { const message = `Unexpected unmocked request: ${JSON.stringify(config, null, 2)}\n` + - 'Consider using the `axios-mock-adapter` in tests.'; + 'Consider using the `axios-mock-adapter` module in tests.'; const error = new Error(message); error.config = config; + global.fail(error); throw error; }; diff --git a/spec/frontend/mocks/mocks_helper_spec.js b/spec/frontend/mocks/mocks_helper_spec.js index b8bb02c2f43..82e88b712c0 100644 --- a/spec/frontend/mocks/mocks_helper_spec.js +++ b/spec/frontend/mocks/mocks_helper_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable global-require, promise/catch-or-return */ +/* eslint-disable global-require */ import path from 'path'; @@ -126,9 +126,8 @@ describe('mocks_helper.js', () => { it('survives jest.isolateModules()', done => { jest.isolateModules(() => { const axios2 = require('~/lib/utils/axios_utils').default; - expect(axios2.get('http://gitlab.com')) - .rejects.toThrow('Unexpected unmocked request') - .then(done); + expect(axios2.isMock).toBe(true); + done(); }); }); diff --git a/spec/frontend/mocks/node/jquery.js b/spec/frontend/mocks/node/jquery.js index 34a25772f67..5c82f65406e 100644 --- a/spec/frontend/mocks/node/jquery.js +++ b/spec/frontend/mocks/node/jquery.js @@ -4,9 +4,11 @@ const $ = jest.requireActual('jquery'); // Fail tests for unmocked requests $.ajax = () => { - throw new Error( + const err = new Error( 'Unexpected unmocked jQuery.ajax() call! Make sure to mock jQuery.ajax() in tests.', ); + global.fail(err); + throw err; }; // jquery is not an ES6 module diff --git a/spec/frontend/mocks_spec.js b/spec/frontend/mocks_spec.js index 2d2324120fd..a4a1fdea396 100644 --- a/spec/frontend/mocks_spec.js +++ b/spec/frontend/mocks_spec.js @@ -3,11 +3,22 @@ import axios from '~/lib/utils/axios_utils'; describe('Mock auto-injection', () => { describe('mocks', () => { - it('~/lib/utils/axios_utils', () => - expect(axios.get('http://gitlab.com')).rejects.toThrow('Unexpected unmocked request')); + let failMock; + beforeEach(() => { + failMock = jest.spyOn(global, 'fail').mockImplementation(); + }); + + it('~/lib/utils/axios_utils', done => { + expect(axios.get('http://gitlab.com')).rejects.toThrow('Unexpected unmocked request'); + setImmediate(() => { + expect(failMock).toHaveBeenCalledTimes(1); + done(); + }); + }); it('jQuery.ajax()', () => { expect($.ajax).toThrow('Unexpected unmocked'); + expect(failMock).toHaveBeenCalledTimes(1); }); }); }); diff --git a/spec/helpers/avatars_helper_spec.rb b/spec/helpers/avatars_helper_spec.rb index 6fbb6147d84..9330e75af11 100644 --- a/spec/helpers/avatars_helper_spec.rb +++ b/spec/helpers/avatars_helper_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe AvatarsHelper do include UploadHelpers diff --git a/spec/helpers/commits_helper_spec.rb b/spec/helpers/commits_helper_spec.rb index 824b3ab4fc1..9e53bc05a48 100644 --- a/spec/helpers/commits_helper_spec.rb +++ b/spec/helpers/commits_helper_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe CommitsHelper do describe 'commit_author_link' do diff --git a/spec/helpers/form_helper_spec.rb b/spec/helpers/form_helper_spec.rb index 18cf0031d5f..a70d8333f30 100644 --- a/spec/helpers/form_helper_spec.rb +++ b/spec/helpers/form_helper_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe FormHelper do describe 'form_errors' do diff --git a/spec/helpers/import_helper_spec.rb b/spec/helpers/import_helper_spec.rb index 6e8c13db9fe..8a1b1e859b1 100644 --- a/spec/helpers/import_helper_spec.rb +++ b/spec/helpers/import_helper_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe ImportHelper do describe '#sanitize_project_name' do diff --git a/spec/helpers/markup_helper_spec.rb b/spec/helpers/markup_helper_spec.rb index 1757ec8fa4d..f6e1720e113 100644 --- a/spec/helpers/markup_helper_spec.rb +++ b/spec/helpers/markup_helper_spec.rb @@ -65,9 +65,6 @@ describe MarkupHelper do describe 'inside a group' do before do - # Ensure the generated reference links aren't redacted - group.add_maintainer(user) - helper.instance_variable_set(:@group, group) helper.instance_variable_set(:@project, nil) end @@ -81,9 +78,6 @@ describe MarkupHelper do let(:project_in_group) { create(:project, group: group) } before do - # Ensure the generated reference links aren't redacted - project_in_group.add_maintainer(user) - helper.instance_variable_set(:@group, group) helper.instance_variable_set(:@project, project_in_group) end diff --git a/spec/helpers/page_layout_helper_spec.rb b/spec/helpers/page_layout_helper_spec.rb index bf50763d06f..3b08fc511a3 100644 --- a/spec/helpers/page_layout_helper_spec.rb +++ b/spec/helpers/page_layout_helper_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe PageLayoutHelper do describe 'page_description' do diff --git a/spec/helpers/profiles_helper_spec.rb b/spec/helpers/profiles_helper_spec.rb index 8e336469c27..da2dc229c35 100644 --- a/spec/helpers/profiles_helper_spec.rb +++ b/spec/helpers/profiles_helper_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe ProfilesHelper do describe '#commit_email_select_options' do diff --git a/spec/helpers/users_helper_spec.rb b/spec/helpers/users_helper_spec.rb index a6623bc7941..9165e91ddcd 100644 --- a/spec/helpers/users_helper_spec.rb +++ b/spec/helpers/users_helper_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe UsersHelper do include TermsHelper diff --git a/spec/javascripts/boards/issue_spec.js b/spec/javascripts/boards/issue_spec.js index bb7abe52eae..05e6ea1394d 100644 --- a/spec/javascripts/boards/issue_spec.js +++ b/spec/javascripts/boards/issue_spec.js @@ -1,6 +1,6 @@ /* global ListIssue */ -import Vue from 'vue'; +import axios from '~/lib/utils/axios_utils'; import '~/boards/models/label'; import '~/boards/models/assignee'; import '~/boards/models/issue'; @@ -175,7 +175,7 @@ describe('Issue model', () => { describe('update', () => { it('passes assignee ids when there are assignees', done => { - spyOn(Vue.http, 'patch').and.callFake((url, data) => { + spyOn(axios, 'patch').and.callFake((url, data) => { expect(data.issue.assignee_ids).toEqual([1]); done(); return Promise.resolve(); @@ -185,7 +185,7 @@ describe('Issue model', () => { }); it('passes assignee ids of [0] when there are no assignees', done => { - spyOn(Vue.http, 'patch').and.callFake((url, data) => { + spyOn(axios, 'patch').and.callFake((url, data) => { expect(data.issue.assignee_ids).toEqual([0]); done(); return Promise.resolve(); diff --git a/spec/javascripts/flash_spec.js b/spec/javascripts/flash_spec.js index aecab331ead..bd8608b6bac 100644 --- a/spec/javascripts/flash_spec.js +++ b/spec/javascripts/flash_spec.js @@ -25,14 +25,6 @@ describe('Flash', () => { '<script>alert("a");</script>', ); }); - - it('adds container classes when inside content wrapper', () => { - el.innerHTML = createFlashEl('testing', 'alert', true); - - expect(el.querySelector('.flash-text').classList.contains('container-fluid')).toBeTruthy(); - - expect(el.querySelector('.flash-text').classList.contains('container-limited')).toBeTruthy(); - }); }); describe('hideFlash', () => { @@ -171,9 +163,7 @@ describe('Flash', () => { it('adds container classes when inside content-wrapper', () => { flash('test'); - expect(document.querySelector('.flash-text').className).toBe( - 'flash-text container-fluid container-limited limit-container-width', - ); + expect(document.querySelector('.flash-text').className).toBe('flash-text'); }); it('does not add container when outside of content-wrapper', () => { diff --git a/spec/javascripts/monitoring/charts/area_spec.js b/spec/javascripts/monitoring/charts/area_spec.js deleted file mode 100644 index 1e49a955815..00000000000 --- a/spec/javascripts/monitoring/charts/area_spec.js +++ /dev/null @@ -1,265 +0,0 @@ -import { shallowMount } from '@vue/test-utils'; -import { createStore } from '~/monitoring/stores'; -import { GlLink } from '@gitlab/ui'; -import { GlAreaChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts'; -import { shallowWrapperContainsSlotText } from 'spec/helpers/vue_test_utils_helper'; -import Area from '~/monitoring/components/charts/area.vue'; -import * as types from '~/monitoring/stores/mutation_types'; -import { TEST_HOST } from 'spec/test_constants'; -import MonitoringMock, { deploymentData } from '../mock_data'; - -describe('Area component', () => { - const mockSha = 'mockSha'; - const mockWidgets = 'mockWidgets'; - const mockSvgPathContent = 'mockSvgPathContent'; - const projectPath = `${TEST_HOST}/path/to/project`; - const commitUrl = `${projectPath}/commit/${mockSha}`; - let mockGraphData; - let areaChart; - let spriteSpy; - let store; - - beforeEach(() => { - store = createStore(); - store.commit(`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`, MonitoringMock.data); - store.commit(`monitoringDashboard/${types.RECEIVE_DEPLOYMENTS_DATA_SUCCESS}`, deploymentData); - - [mockGraphData] = store.state.monitoringDashboard.groups[0].metrics; - - areaChart = shallowMount(Area, { - propsData: { - graphData: mockGraphData, - containerWidth: 0, - deploymentData: store.state.monitoringDashboard.deploymentData, - projectPath, - }, - slots: { - default: mockWidgets, - }, - store, - }); - - spriteSpy = spyOnDependency(Area, 'getSvgIconPathContent').and.callFake( - () => new Promise(resolve => resolve(mockSvgPathContent)), - ); - }); - - afterEach(() => { - areaChart.destroy(); - }); - - it('renders chart title', () => { - expect(areaChart.find({ ref: 'graphTitle' }).text()).toBe(mockGraphData.title); - }); - - it('contains graph widgets from slot', () => { - expect(areaChart.find({ ref: 'graphWidgets' }).text()).toBe(mockWidgets); - }); - - describe('wrapped components', () => { - describe('GitLab UI area chart', () => { - let glAreaChart; - - beforeEach(() => { - glAreaChart = areaChart.find(GlAreaChart); - }); - - it('is a Vue instance', () => { - expect(glAreaChart.isVueInstance()).toBe(true); - }); - - it('receives data properties needed for proper chart render', () => { - const props = glAreaChart.props(); - - expect(props.data).toBe(areaChart.vm.chartData); - expect(props.option).toBe(areaChart.vm.chartOptions); - expect(props.formatTooltipText).toBe(areaChart.vm.formatTooltipText); - expect(props.thresholds).toBe(areaChart.vm.thresholds); - }); - - it('recieves a tooltip title', () => { - const mockTitle = 'mockTitle'; - areaChart.vm.tooltip.title = mockTitle; - - expect(shallowWrapperContainsSlotText(glAreaChart, 'tooltipTitle', mockTitle)).toBe(true); - }); - - describe('when tooltip is showing deployment data', () => { - beforeEach(() => { - areaChart.vm.tooltip.isDeployment = true; - }); - - it('uses deployment title', () => { - expect(shallowWrapperContainsSlotText(glAreaChart, 'tooltipTitle', 'Deployed')).toBe( - true, - ); - }); - - it('renders clickable commit sha in tooltip content', () => { - areaChart.vm.tooltip.sha = mockSha; - areaChart.vm.tooltip.commitUrl = commitUrl; - - const commitLink = areaChart.find(GlLink); - - expect(shallowWrapperContainsSlotText(commitLink, 'default', mockSha)).toBe(true); - expect(commitLink.attributes('href')).toEqual(commitUrl); - }); - }); - }); - }); - - describe('methods', () => { - describe('formatTooltipText', () => { - const mockDate = deploymentData[0].created_at; - const generateSeriesData = type => ({ - seriesData: [ - { - seriesName: areaChart.vm.chartData[0].name, - componentSubType: type, - value: [mockDate, 5.55555], - seriesIndex: 0, - }, - ], - value: mockDate, - }); - - describe('when series is of line type', () => { - beforeEach(() => { - areaChart.vm.formatTooltipText(generateSeriesData('line')); - }); - - it('formats tooltip title', () => { - expect(areaChart.vm.tooltip.title).toBe('31 May 2017, 9:23PM'); - }); - - it('formats tooltip content', () => { - const name = 'Core Usage'; - const value = '5.556'; - const seriesLabel = areaChart.find(GlChartSeriesLabel); - - expect(seriesLabel.vm.color).toBe(''); - expect(shallowWrapperContainsSlotText(seriesLabel, 'default', name)).toBe(true); - expect(areaChart.vm.tooltip.content).toEqual([{ name, value, color: undefined }]); - expect( - shallowWrapperContainsSlotText(areaChart.find(GlAreaChart), 'tooltipContent', value), - ).toBe(true); - }); - }); - - describe('when series is of scatter type', () => { - beforeEach(() => { - areaChart.vm.formatTooltipText(generateSeriesData('scatter')); - }); - - it('formats tooltip title', () => { - expect(areaChart.vm.tooltip.title).toBe('31 May 2017, 9:23PM'); - }); - - it('formats tooltip sha', () => { - expect(areaChart.vm.tooltip.sha).toBe('f5bcd1d9'); - }); - }); - }); - - describe('setSvg', () => { - const mockSvgName = 'mockSvgName'; - - beforeEach(() => { - areaChart.vm.setSvg(mockSvgName); - }); - - it('gets svg path content', () => { - expect(spriteSpy).toHaveBeenCalledWith(mockSvgName); - }); - - it('sets svg path content', done => { - areaChart.vm.$nextTick(() => { - expect(areaChart.vm.svgs[mockSvgName]).toBe(`path://${mockSvgPathContent}`); - done(); - }); - }); - }); - - describe('onResize', () => { - const mockWidth = 233; - - beforeEach(() => { - spyOn(Element.prototype, 'getBoundingClientRect').and.callFake(() => ({ - width: mockWidth, - })); - areaChart.vm.onResize(); - }); - - it('sets area chart width', () => { - expect(areaChart.vm.width).toBe(mockWidth); - }); - }); - }); - - describe('computed', () => { - describe('chartData', () => { - let chartData; - const seriesData = () => chartData[0]; - - beforeEach(() => { - ({ chartData } = areaChart.vm); - }); - - it('utilizes all data points', () => { - expect(chartData.length).toBe(1); - expect(seriesData().data.length).toBe(297); - }); - - it('creates valid data', () => { - const { data } = seriesData(); - - expect( - data.filter(([time, value]) => new Date(time).getTime() > 0 && typeof value === 'number') - .length, - ).toBe(data.length); - }); - - it('formats line width correctly', () => { - expect(chartData[0].lineStyle.width).toBe(2); - }); - }); - - describe('chartOptions', () => { - describe('dataZoom', () => { - it('contains an svg object within an array to properly render icon', () => { - const dataZoomObject = [{}]; - - expect(areaChart.vm.chartOptions.dataZoom).toEqual(dataZoomObject); - }); - }); - - describe('yAxis formatter', () => { - let format; - - beforeEach(() => { - format = areaChart.vm.chartOptions.yAxis.axisLabel.formatter; - }); - - it('rounds to 3 decimal places', () => { - expect(format(0.88888)).toBe('0.889'); - }); - }); - }); - - describe('scatterSeries', () => { - it('utilizes deployment data', () => { - expect(areaChart.vm.scatterSeries.data).toEqual([ - ['2017-05-31T21:23:37.881Z', 0], - ['2017-05-30T20:08:04.629Z', 0], - ['2017-05-30T17:42:38.409Z', 0], - ]); - }); - }); - - describe('yAxisLabel', () => { - it('constructs a label for the chart y-axis', () => { - expect(areaChart.vm.yAxisLabel).toBe('CPU'); - }); - }); - }); -}); diff --git a/spec/javascripts/monitoring/components/dashboard_spec.js b/spec/javascripts/monitoring/components/dashboard_spec.js index f3ec7520c6f..15e41e2fe93 100644 --- a/spec/javascripts/monitoring/components/dashboard_spec.js +++ b/spec/javascripts/monitoring/components/dashboard_spec.js @@ -378,7 +378,9 @@ describe('Dashboard', () => { }); }); - describe('link to chart', () => { + // https://gitlab.com/gitlab-org/gitlab-ce/issues/66922 + // eslint-disable-next-line jasmine/no-disabled-tests + xdescribe('link to chart', () => { let wrapper; const currentDashboard = 'TEST_DASHBOARD'; localVue.use(GlToast); diff --git a/spec/javascripts/sidebar/mock_data.js b/spec/javascripts/sidebar/mock_data.js index 7f20b0da991..3ee97b978fd 100644 --- a/spec/javascripts/sidebar/mock_data.js +++ b/spec/javascripts/sidebar/mock_data.js @@ -210,14 +210,4 @@ const mockData = { }, }; -mockData.sidebarMockInterceptor = function(request, next) { - const body = this.responseMap[request.method.toUpperCase()][request.url]; - - next( - request.respondWith(JSON.stringify(body), { - status: 200, - }), - ); -}.bind(mockData); - export default mockData; diff --git a/spec/javascripts/sidebar/sidebar_mediator_spec.js b/spec/javascripts/sidebar/sidebar_mediator_spec.js index 6c69c08e733..2e5845cd847 100644 --- a/spec/javascripts/sidebar/sidebar_mediator_spec.js +++ b/spec/javascripts/sidebar/sidebar_mediator_spec.js @@ -1,13 +1,16 @@ -import _ from 'underscore'; -import Vue from 'vue'; +import MockAdapter from 'axios-mock-adapter'; +import axios from '~/lib/utils/axios_utils'; import SidebarMediator from '~/sidebar/sidebar_mediator'; import SidebarStore from '~/sidebar/stores/sidebar_store'; import SidebarService from '~/sidebar/services/sidebar_service'; import Mock from './mock_data'; describe('Sidebar mediator', function() { + let mock; + beforeEach(() => { - Vue.http.interceptors.push(Mock.sidebarMockInterceptor); + mock = new MockAdapter(axios); + this.mediator = new SidebarMediator(Mock.mediator); }); @@ -15,7 +18,7 @@ describe('Sidebar mediator', function() { SidebarService.singleton = null; SidebarStore.singleton = null; SidebarMediator.singleton = null; - Vue.http.interceptors = _.without(Vue.http.interceptors, Mock.sidebarMockInterceptor); + mock.restore(); }); it('assigns yourself ', () => { @@ -26,6 +29,7 @@ describe('Sidebar mediator', function() { }); it('saves assignees', done => { + mock.onPut('/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar_extras').reply(200, {}); this.mediator .saveAssignees('issue[assignee_ids]') .then(resp => { @@ -38,6 +42,9 @@ describe('Sidebar mediator', function() { it('fetches the data', done => { const mockData = Mock.responseMap.GET['/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar_extras']; + mock + .onGet('/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar_extras') + .reply(200, mockData); spyOn(this.mediator, 'processFetchedData').and.callThrough(); this.mediator @@ -74,6 +81,7 @@ describe('Sidebar mediator', function() { it('fetches autocomplete projects', done => { const searchTerm = 'foo'; + mock.onGet('/autocomplete/projects?project_id=15').reply(200, {}); spyOn(this.mediator.service, 'getProjectsAutocomplete').and.callThrough(); spyOn(this.mediator.store, 'setAutocompleteProjects').and.callThrough(); @@ -88,7 +96,9 @@ describe('Sidebar mediator', function() { }); it('moves issue', done => { + const mockData = Mock.responseMap.POST['/gitlab-org/gitlab-shell/issues/5/move']; const moveToProjectId = 7; + mock.onPost('/gitlab-org/gitlab-shell/issues/5/move').reply(200, mockData); this.mediator.store.setMoveToProjectId(moveToProjectId); spyOn(this.mediator.service, 'moveIssue').and.callThrough(); const visitUrl = spyOnDependency(SidebarMediator, 'visitUrl'); @@ -105,6 +115,7 @@ describe('Sidebar mediator', function() { it('toggle subscription', done => { this.mediator.store.setSubscribedState(false); + mock.onPost('/gitlab-org/gitlab-shell/issues/5/toggle_subscription').reply(200, {}); spyOn(this.mediator.service, 'toggleSubscription').and.callThrough(); this.mediator diff --git a/spec/javascripts/sidebar/sidebar_move_issue_spec.js b/spec/javascripts/sidebar/sidebar_move_issue_spec.js index 230e0a933a9..ec712450f2e 100644 --- a/spec/javascripts/sidebar/sidebar_move_issue_spec.js +++ b/spec/javascripts/sidebar/sidebar_move_issue_spec.js @@ -1,6 +1,6 @@ import $ from 'jquery'; -import _ from 'underscore'; -import Vue from 'vue'; +import MockAdapter from 'axios-mock-adapter'; +import axios from '~/lib/utils/axios_utils'; import SidebarMediator from '~/sidebar/sidebar_mediator'; import SidebarStore from '~/sidebar/stores/sidebar_store'; import SidebarService from '~/sidebar/services/sidebar_service'; @@ -8,8 +8,12 @@ import SidebarMoveIssue from '~/sidebar/lib/sidebar_move_issue'; import Mock from './mock_data'; describe('SidebarMoveIssue', function() { + let mock; + beforeEach(() => { - Vue.http.interceptors.push(Mock.sidebarMockInterceptor); + mock = new MockAdapter(axios); + const mockData = Mock.responseMap.GET['/autocomplete/projects?project_id=15']; + mock.onGet('/autocomplete/projects?project_id=15').reply(200, mockData); this.mediator = new SidebarMediator(Mock.mediator); this.$content = $(` <div class="dropdown"> @@ -37,8 +41,7 @@ describe('SidebarMoveIssue', function() { SidebarMediator.singleton = null; this.sidebarMoveIssue.destroy(); - - Vue.http.interceptors = _.without(Vue.http.interceptors, Mock.sidebarMockInterceptor); + mock.restore(); }); describe('init', () => { diff --git a/spec/lib/banzai/filter/blockquote_fence_filter_spec.rb b/spec/lib/banzai/filter/blockquote_fence_filter_spec.rb index 807f1b8bbd3..8e955ec3b6b 100644 --- a/spec/lib/banzai/filter/blockquote_fence_filter_spec.rb +++ b/spec/lib/banzai/filter/blockquote_fence_filter_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Banzai::Filter::BlockquoteFenceFilter do include FilterSpecHelper diff --git a/spec/lib/banzai/filter/front_matter_filter_spec.rb b/spec/lib/banzai/filter/front_matter_filter_spec.rb index 90b383dbcff..1b5b1770615 100644 --- a/spec/lib/banzai/filter/front_matter_filter_spec.rb +++ b/spec/lib/banzai/filter/front_matter_filter_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Banzai::Filter::FrontMatterFilter do include FilterSpecHelper diff --git a/spec/lib/banzai/filter/relative_link_filter_spec.rb b/spec/lib/banzai/filter/relative_link_filter_spec.rb index 789530fbc56..f8b3748c663 100644 --- a/spec/lib/banzai/filter/relative_link_filter_spec.rb +++ b/spec/lib/banzai/filter/relative_link_filter_spec.rb @@ -289,121 +289,72 @@ describe Banzai::Filter::RelativeLinkFilter do let(:relative_path) { "/#{project.full_path}#{upload_path}" } context 'to a project upload' do - context 'without project repository access' do - let(:project) { create(:project, :repository, repository_access_level: ProjectFeature::PRIVATE) } - - it 'does not rebuild relative URL for a link' do - doc = filter(link(upload_path)) - expect(doc.at_css('a')['href']).to eq(upload_path) - - doc = filter(nested(link(upload_path))) - expect(doc.at_css('a')['href']).to eq(upload_path) - end - - it 'does not rebuild relative URL for an image' do - doc = filter(image(upload_path)) - expect(doc.at_css('img')['src']).to eq(upload_path) - - doc = filter(nested(image(upload_path))) - expect(doc.at_css('img')['src']).to eq(upload_path) - end - + shared_examples 'rewrite project uploads' do context 'with an absolute URL' do let(:absolute_path) { Gitlab.config.gitlab.url + relative_path } let(:only_path) { false } - it 'does not rewrite the link' do + it 'rewrites the link correctly' do doc = filter(link(upload_path)) - expect(doc.at_css('a')['href']).to eq(upload_path) + expect(doc.at_css('a')['href']).to eq(absolute_path) end end - end - context 'with an absolute URL' do - let(:absolute_path) { Gitlab.config.gitlab.url + relative_path } - let(:only_path) { false } - - it 'rewrites the link correctly' do + it 'rebuilds relative URL for a link' do doc = filter(link(upload_path)) + expect(doc.at_css('a')['href']).to eq(relative_path) - expect(doc.at_css('a')['href']).to eq(absolute_path) + doc = filter(nested(link(upload_path))) + expect(doc.at_css('a')['href']).to eq(relative_path) end - end - it 'rebuilds relative URL for a link' do - doc = filter(link(upload_path)) - expect(doc.at_css('a')['href']).to eq(relative_path) + it 'rebuilds relative URL for an image' do + doc = filter(image(upload_path)) + expect(doc.at_css('img')['src']).to eq(relative_path) - doc = filter(nested(link(upload_path))) - expect(doc.at_css('a')['href']).to eq(relative_path) - end + doc = filter(nested(image(upload_path))) + expect(doc.at_css('img')['src']).to eq(relative_path) + end - it 'rebuilds relative URL for an image' do - doc = filter(image(upload_path)) - expect(doc.at_css('img')['src']).to eq(relative_path) + it 'does not modify absolute URL' do + doc = filter(link('http://example.com')) + expect(doc.at_css('a')['href']).to eq 'http://example.com' + end - doc = filter(nested(image(upload_path))) - expect(doc.at_css('img')['src']).to eq(relative_path) - end + it 'supports unescaped Unicode filenames' do + path = '/uploads/한글.png' + doc = filter(link(path)) - it 'does not modify absolute URL' do - doc = filter(link('http://example.com')) - expect(doc.at_css('a')['href']).to eq 'http://example.com' - end + expect(doc.at_css('a')['href']).to eq("/#{project.full_path}/uploads/%ED%95%9C%EA%B8%80.png") + end - it 'supports unescaped Unicode filenames' do - path = '/uploads/한글.png' - doc = filter(link(path)) + it 'supports escaped Unicode filenames' do + path = '/uploads/한글.png' + escaped = Addressable::URI.escape(path) + doc = filter(image(escaped)) - expect(doc.at_css('a')['href']).to eq("/#{project.full_path}/uploads/%ED%95%9C%EA%B8%80.png") + expect(doc.at_css('img')['src']).to eq("/#{project.full_path}/uploads/%ED%95%9C%EA%B8%80.png") + end end - it 'supports escaped Unicode filenames' do - path = '/uploads/한글.png' - escaped = Addressable::URI.escape(path) - doc = filter(image(escaped)) + context 'without project repository access' do + let(:project) { create(:project, :repository, repository_access_level: ProjectFeature::PRIVATE) } + + it_behaves_like 'rewrite project uploads' + end - expect(doc.at_css('img')['src']).to eq("/#{project.full_path}/uploads/%ED%95%9C%EA%B8%80.png") + context 'with project repository access' do + it_behaves_like 'rewrite project uploads' end end context 'to a group upload' do - let(:upload_path) { '/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg' } - let(:upload_link) { link(upload_path) } + let(:upload_link) { link('/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg') } let(:group) { create(:group) } let(:project) { nil } let(:relative_path) { "/groups/#{group.full_path}/-/uploads/e90decf88d8f96fe9e1389afc2e4a91f/test.jpg" } - context 'without group read access' do - let(:group) { create(:group, :private) } - - it 'does not rewrite the link' do - doc = filter(upload_link) - - expect(doc.at_css('a')['href']).to eq(upload_path) - end - - it 'does not rewrite the link for subgroup' do - group.update!(parent: create(:group)) - - doc = filter(upload_link) - - expect(doc.at_css('a')['href']).to eq(upload_path) - end - - context 'with an absolute URL' do - let(:absolute_path) { Gitlab.config.gitlab.url + relative_path } - let(:only_path) { false } - - it 'does not rewrite the link' do - doc = filter(upload_link) - - expect(doc.at_css('a')['href']).to eq(upload_path) - end - end - end - context 'with an absolute URL' do let(:absolute_path) { Gitlab.config.gitlab.url + relative_path } let(:only_path) { false } diff --git a/spec/lib/banzai/pipeline/description_pipeline_spec.rb b/spec/lib/banzai/pipeline/description_pipeline_spec.rb index d032ec71e45..5ecd3df5151 100644 --- a/spec/lib/banzai/pipeline/description_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/description_pipeline_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Banzai::Pipeline::DescriptionPipeline do def parse(html) diff --git a/spec/lib/banzai/pipeline/email_pipeline_spec.rb b/spec/lib/banzai/pipeline/email_pipeline_spec.rb index eea25320f3d..77186861225 100644 --- a/spec/lib/banzai/pipeline/email_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/email_pipeline_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Banzai::Pipeline::EmailPipeline do describe '.filters' do diff --git a/spec/lib/banzai/pipeline/full_pipeline_spec.rb b/spec/lib/banzai/pipeline/full_pipeline_spec.rb index 2b4d1b58676..f63b86d1451 100644 --- a/spec/lib/banzai/pipeline/full_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/full_pipeline_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Banzai::Pipeline::FullPipeline do describe 'References' do diff --git a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb index 3a9ecd2fb81..7eb63fea413 100644 --- a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Banzai::Pipeline::GfmPipeline do describe 'integration between parsing regular and external issue references' do diff --git a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb index 015af20f220..4a485fbc2bd 100644 --- a/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/wiki_pipeline_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Banzai::Pipeline::WikiPipeline do describe 'TableOfContents' do diff --git a/spec/lib/gitlab/anonymous_session_spec.rb b/spec/lib/gitlab/anonymous_session_spec.rb index 628aae81ada..94daa0f2470 100644 --- a/spec/lib/gitlab/anonymous_session_spec.rb +++ b/spec/lib/gitlab/anonymous_session_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::AnonymousSession, :clean_gitlab_redis_shared_state do let(:default_session_id) { '6919a6f1bb119dd7396fadc38fd18d0d' } diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index 098c33f9cb1..0365d63ea9c 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -587,7 +587,8 @@ describe Gitlab::Auth do :read_project, :build_download_code, :build_read_container_image, - :build_create_container_image + :build_create_container_image, + :build_destroy_container_image ] end diff --git a/spec/lib/gitlab/background_migration/populate_merge_request_assignees_table_spec.rb b/spec/lib/gitlab/background_migration/populate_merge_request_assignees_table_spec.rb index ad4fa4fe03a..c1f6871a568 100644 --- a/spec/lib/gitlab/background_migration/populate_merge_request_assignees_table_spec.rb +++ b/spec/lib/gitlab/background_migration/populate_merge_request_assignees_table_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::BackgroundMigration::PopulateMergeRequestAssigneesTable, :migration, schema: 20190315191339 do let(:namespaces) { table(:namespaces) } diff --git a/spec/lib/gitlab/background_migration/reset_merge_status_spec.rb b/spec/lib/gitlab/background_migration/reset_merge_status_spec.rb index 740781f1aa5..fd35ddc49a2 100644 --- a/spec/lib/gitlab/background_migration/reset_merge_status_spec.rb +++ b/spec/lib/gitlab/background_migration/reset_merge_status_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::BackgroundMigration::ResetMergeStatus, :migration, schema: 20190528180441 do let(:namespaces) { table(:namespaces) } diff --git a/spec/lib/gitlab/checks/project_created_spec.rb b/spec/lib/gitlab/checks/project_created_spec.rb index 14cb5e6ec66..373fef2a240 100644 --- a/spec/lib/gitlab/checks/project_created_spec.rb +++ b/spec/lib/gitlab/checks/project_created_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::Checks::ProjectCreated, :clean_gitlab_redis_shared_state do let(:user) { create(:user) } diff --git a/spec/lib/gitlab/checks/project_moved_spec.rb b/spec/lib/gitlab/checks/project_moved_spec.rb index 3ca977aa48d..3de397760b4 100644 --- a/spec/lib/gitlab/checks/project_moved_spec.rb +++ b/spec/lib/gitlab/checks/project_moved_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::Checks::ProjectMoved, :clean_gitlab_redis_shared_state do let(:user) { create(:user) } diff --git a/spec/lib/gitlab/database_importers/common_metrics/importer_spec.rb b/spec/lib/gitlab/database_importers/common_metrics/importer_spec.rb index eed2a1b7b48..e6321d48e11 100644 --- a/spec/lib/gitlab/database_importers/common_metrics/importer_spec.rb +++ b/spec/lib/gitlab/database_importers/common_metrics/importer_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::DatabaseImporters::CommonMetrics::Importer do subject { described_class.new } diff --git a/spec/lib/gitlab/database_importers/common_metrics/prometheus_metric_spec.rb b/spec/lib/gitlab/database_importers/common_metrics/prometheus_metric_spec.rb index 94f544e59b3..e4e8a85e7bc 100644 --- a/spec/lib/gitlab/database_importers/common_metrics/prometheus_metric_spec.rb +++ b/spec/lib/gitlab/database_importers/common_metrics/prometheus_metric_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::DatabaseImporters::CommonMetrics::PrometheusMetric do it 'group enum equals ::PrometheusMetric' do diff --git a/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb b/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb index b3dedfe1f77..aab6fbcbbd1 100644 --- a/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb +++ b/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb @@ -176,14 +176,28 @@ describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService do end context 'with non default prometheus address' do + let(:listen_address) { 'https://localhost:9090' } + let(:prometheus_settings) do { enable: true, - listen_address: 'https://localhost:9090' + listen_address: listen_address } end it_behaves_like 'has prometheus service', 'https://localhost:9090' + + context 'with :9090 symbol' do + let(:listen_address) { :':9090' } + + it_behaves_like 'has prometheus service', 'http://localhost:9090' + end + + context 'with 0.0.0.0:9090' do + let(:listen_address) { '0.0.0.0:9090' } + + it_behaves_like 'has prometheus service', 'http://localhost:9090' + end end context 'when prometheus setting is not present in gitlab.yml' do diff --git a/spec/lib/gitlab/dependency_linker/cartfile_linker_spec.rb b/spec/lib/gitlab/dependency_linker/cartfile_linker_spec.rb index 3eb5db51224..6d61edaa870 100644 --- a/spec/lib/gitlab/dependency_linker/cartfile_linker_spec.rb +++ b/spec/lib/gitlab/dependency_linker/cartfile_linker_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::DependencyLinker::CartfileLinker do describe '.support?' do diff --git a/spec/lib/gitlab/dependency_linker/composer_json_linker_spec.rb b/spec/lib/gitlab/dependency_linker/composer_json_linker_spec.rb index 6bef6f57e64..cc1f09628ef 100644 --- a/spec/lib/gitlab/dependency_linker/composer_json_linker_spec.rb +++ b/spec/lib/gitlab/dependency_linker/composer_json_linker_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::DependencyLinker::ComposerJsonLinker do describe '.support?' do diff --git a/spec/lib/gitlab/dependency_linker/gemfile_linker_spec.rb b/spec/lib/gitlab/dependency_linker/gemfile_linker_spec.rb index 6ecdb0d1247..c6b6dfa77cb 100644 --- a/spec/lib/gitlab/dependency_linker/gemfile_linker_spec.rb +++ b/spec/lib/gitlab/dependency_linker/gemfile_linker_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::DependencyLinker::GemfileLinker do describe '.support?' do diff --git a/spec/lib/gitlab/dependency_linker/gemspec_linker_spec.rb b/spec/lib/gitlab/dependency_linker/gemspec_linker_spec.rb index 256fe58925c..c1cbfa31684 100644 --- a/spec/lib/gitlab/dependency_linker/gemspec_linker_spec.rb +++ b/spec/lib/gitlab/dependency_linker/gemspec_linker_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::DependencyLinker::GemspecLinker do describe '.support?' do diff --git a/spec/lib/gitlab/dependency_linker/godeps_json_linker_spec.rb b/spec/lib/gitlab/dependency_linker/godeps_json_linker_spec.rb index f620d1b590c..9f8542a76c9 100644 --- a/spec/lib/gitlab/dependency_linker/godeps_json_linker_spec.rb +++ b/spec/lib/gitlab/dependency_linker/godeps_json_linker_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::DependencyLinker::GodepsJsonLinker do describe '.support?' do diff --git a/spec/lib/gitlab/dependency_linker/package_json_linker_spec.rb b/spec/lib/gitlab/dependency_linker/package_json_linker_spec.rb index 71e9381eaad..eb0c5e0675a 100644 --- a/spec/lib/gitlab/dependency_linker/package_json_linker_spec.rb +++ b/spec/lib/gitlab/dependency_linker/package_json_linker_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::DependencyLinker::PackageJsonLinker do describe '.support?' do diff --git a/spec/lib/gitlab/dependency_linker/parser/gemfile_spec.rb b/spec/lib/gitlab/dependency_linker/parser/gemfile_spec.rb index 9bfb1b13a2b..5b69ef5af24 100644 --- a/spec/lib/gitlab/dependency_linker/parser/gemfile_spec.rb +++ b/spec/lib/gitlab/dependency_linker/parser/gemfile_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::DependencyLinker::Parser::Gemfile do describe '#parse' do diff --git a/spec/lib/gitlab/dependency_linker/podfile_linker_spec.rb b/spec/lib/gitlab/dependency_linker/podfile_linker_spec.rb index eb81bc07760..77326e73505 100644 --- a/spec/lib/gitlab/dependency_linker/podfile_linker_spec.rb +++ b/spec/lib/gitlab/dependency_linker/podfile_linker_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::DependencyLinker::PodfileLinker do describe '.support?' do diff --git a/spec/lib/gitlab/dependency_linker/podspec_json_linker_spec.rb b/spec/lib/gitlab/dependency_linker/podspec_json_linker_spec.rb index 938726dd434..d522a08cdd9 100644 --- a/spec/lib/gitlab/dependency_linker/podspec_json_linker_spec.rb +++ b/spec/lib/gitlab/dependency_linker/podspec_json_linker_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::DependencyLinker::PodspecJsonLinker do describe '.support?' do diff --git a/spec/lib/gitlab/dependency_linker/podspec_linker_spec.rb b/spec/lib/gitlab/dependency_linker/podspec_linker_spec.rb index 540eb2fadfe..baabd0c0460 100644 --- a/spec/lib/gitlab/dependency_linker/podspec_linker_spec.rb +++ b/spec/lib/gitlab/dependency_linker/podspec_linker_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::DependencyLinker::PodspecLinker do describe '.support?' do diff --git a/spec/lib/gitlab/dependency_linker/requirements_txt_linker_spec.rb b/spec/lib/gitlab/dependency_linker/requirements_txt_linker_spec.rb index 957a87985a2..04ac5f10479 100644 --- a/spec/lib/gitlab/dependency_linker/requirements_txt_linker_spec.rb +++ b/spec/lib/gitlab/dependency_linker/requirements_txt_linker_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::DependencyLinker::RequirementsTxtLinker do describe '.support?' do diff --git a/spec/lib/gitlab/dependency_linker_spec.rb b/spec/lib/gitlab/dependency_linker_spec.rb index 98e46d62ca0..3ea3334caf0 100644 --- a/spec/lib/gitlab/dependency_linker_spec.rb +++ b/spec/lib/gitlab/dependency_linker_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::DependencyLinker do describe '.link' do diff --git a/spec/lib/gitlab/favicon_spec.rb b/spec/lib/gitlab/favicon_spec.rb index dce56bbd2c4..63c26e29d73 100644 --- a/spec/lib/gitlab/favicon_spec.rb +++ b/spec/lib/gitlab/favicon_spec.rb @@ -1,14 +1,16 @@ -require 'rails_helper' +require 'spec_helper' RSpec.describe Gitlab::Favicon, :request_store do + include RailsHelpers + describe '.main' do it 'defaults to favicon.png' do - allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('production')) + stub_rails_env('production') expect(described_class.main).to match_asset_path '/assets/favicon.png' end it 'has blue favicon for development', unless: Gitlab.ee? do - allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('development')) + stub_rails_env('development') expect(described_class.main).to match_asset_path '/assets/favicon-blue.png' end @@ -24,7 +26,7 @@ RSpec.describe Gitlab::Favicon, :request_store do context 'asset host' do before do - allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('production')) + stub_rails_env('production') end it 'returns a relative url when the asset host is not configured' do diff --git a/spec/lib/gitlab/file_markdown_link_builder_spec.rb b/spec/lib/gitlab/file_markdown_link_builder_spec.rb index feb2776c5d0..d9e2e162ae8 100644 --- a/spec/lib/gitlab/file_markdown_link_builder_spec.rb +++ b/spec/lib/gitlab/file_markdown_link_builder_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::FileMarkdownLinkBuilder do let(:custom_class) do diff --git a/spec/lib/gitlab/file_type_detection_spec.rb b/spec/lib/gitlab/file_type_detection_spec.rb index 5e9b8988cc8..22ec7d414e8 100644 --- a/spec/lib/gitlab/file_type_detection_spec.rb +++ b/spec/lib/gitlab/file_type_detection_spec.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::FileTypeDetection do def upload_fixture(filename) diff --git a/spec/lib/gitlab/gpg/commit_spec.rb b/spec/lib/gitlab/gpg/commit_spec.rb index 47e6f5d4220..a3d7e42733d 100644 --- a/spec/lib/gitlab/gpg/commit_spec.rb +++ b/spec/lib/gitlab/gpg/commit_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe Gitlab::Gpg::Commit do describe '#signature' do diff --git a/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb b/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb index 1a2c6ef25c4..1dfca0b056c 100644 --- a/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb +++ b/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do describe '#run' do diff --git a/spec/lib/gitlab/gpg_spec.rb b/spec/lib/gitlab/gpg_spec.rb index 48bbd7f854c..77d318c9b23 100644 --- a/spec/lib/gitlab/gpg_spec.rb +++ b/spec/lib/gitlab/gpg_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe Gitlab::Gpg do describe '.fingerprints_from_key' do diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index ec4a6ef05b9..c6aa4a2482c 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -62,6 +62,8 @@ milestone: - participants - events - boards +- milestone_release +- release snippets: - author - project @@ -72,6 +74,8 @@ releases: - author - project - links +- milestone_release +- milestone links: - release project_members: @@ -484,3 +488,6 @@ lists: - board - label - list_user_preferences +milestone_releases: +- milestone +- release diff --git a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb index 7395b095454..f7f510f01db 100644 --- a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb +++ b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe Gitlab::Kubernetes::Helm::InstallCommand do let(:files) { { 'ca.pem': 'some file content' } } diff --git a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb index fce2aded786..64cadcc011c 100644 --- a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb +++ b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe Gitlab::Kubernetes::Helm::Pod do describe '#generate' do diff --git a/spec/lib/gitlab/prometheus/metric_group_spec.rb b/spec/lib/gitlab/prometheus/metric_group_spec.rb index a45dd0af91e..787f14daf47 100644 --- a/spec/lib/gitlab/prometheus/metric_group_spec.rb +++ b/spec/lib/gitlab/prometheus/metric_group_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::Prometheus::MetricGroup do describe '.common_metrics' do diff --git a/spec/lib/gitlab/sidekiq_config_spec.rb b/spec/lib/gitlab/sidekiq_config_spec.rb index 1e8ccb447b1..49efbac160a 100644 --- a/spec/lib/gitlab/sidekiq_config_spec.rb +++ b/spec/lib/gitlab/sidekiq_config_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Gitlab::SidekiqConfig do describe '.workers' do diff --git a/spec/lib/gitlab/tracing_spec.rb b/spec/lib/gitlab/tracing_spec.rb index db75ce2a998..e913bb600ec 100644 --- a/spec/lib/gitlab/tracing_spec.rb +++ b/spec/lib/gitlab/tracing_spec.rb @@ -59,7 +59,7 @@ describe Gitlab::Tracing do it 'returns the correct state for .tracing_url' do expect(described_class).to receive(:tracing_url_enabled?).and_return(tracing_url_enabled?) allow(described_class).to receive(:tracing_url_template).and_return(tracing_url_template) - allow(Gitlab::CorrelationId).to receive(:current_id).and_return(correlation_id) + allow(Labkit::Correlation::CorrelationId).to receive(:current_id).and_return(correlation_id) allow(Gitlab).to receive(:process_name).and_return(process_name) expect(described_class.tracing_url).to eq(tracing_url) diff --git a/spec/lib/gitlab_spec.rb b/spec/lib/gitlab_spec.rb index 1fc363460ae..74d4b12a070 100644 --- a/spec/lib/gitlab_spec.rb +++ b/spec/lib/gitlab_spec.rb @@ -1,10 +1,10 @@ # frozen_string_literal: true -require 'fast_spec_helper' - -require_dependency 'gitlab' +require 'spec_helper' describe Gitlab do + include RailsHelpers + describe '.root' do it 'returns the root path of the app' do expect(described_class.root).to eq(Pathname.new(File.expand_path('../..', __dir__))) @@ -113,7 +113,7 @@ describe Gitlab do it 'is true when dev env' do allow(described_class).to receive_messages(com?: false, org?: false) - allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('development')) + stub_rails_env('development') expect(described_class.dev_env_org_or_com?).to eq true end diff --git a/spec/mailers/abuse_report_mailer_spec.rb b/spec/mailers/abuse_report_mailer_spec.rb index f96870cc112..86153071cd3 100644 --- a/spec/mailers/abuse_report_mailer_spec.rb +++ b/spec/mailers/abuse_report_mailer_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe AbuseReportMailer do include EmailSpec::Matchers diff --git a/spec/mailers/email_rejection_mailer_spec.rb b/spec/mailers/email_rejection_mailer_spec.rb index bbe0a50ae8e..2ce2e3e1410 100644 --- a/spec/mailers/email_rejection_mailer_spec.rb +++ b/spec/mailers/email_rejection_mailer_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe EmailRejectionMailer do include EmailSpec::Matchers diff --git a/spec/mailers/repository_check_mailer_spec.rb b/spec/mailers/repository_check_mailer_spec.rb index 3dce89f5be2..757d3dfa797 100644 --- a/spec/mailers/repository_check_mailer_spec.rb +++ b/spec/mailers/repository_check_mailer_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe RepositoryCheckMailer do include EmailSpec::Matchers diff --git a/spec/models/abuse_report_spec.rb b/spec/models/abuse_report_spec.rb index a5f8e999d5d..814df472389 100644 --- a/spec/models/abuse_report_spec.rb +++ b/spec/models/abuse_report_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe AbuseReport do set(:report) { create(:abuse_report) } diff --git a/spec/models/active_session_spec.rb b/spec/models/active_session_spec.rb index 2a689754ee0..b1f93dc7189 100644 --- a/spec/models/active_session_spec.rb +++ b/spec/models/active_session_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do let(:user) do diff --git a/spec/models/appearance_spec.rb b/spec/models/appearance_spec.rb index 209d138f956..2c32028c3e5 100644 --- a/spec/models/appearance_spec.rb +++ b/spec/models/appearance_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Appearance do subject { build(:appearance) } diff --git a/spec/models/blob_spec.rb b/spec/models/blob_spec.rb index 8364293b908..62a75bde63b 100644 --- a/spec/models/blob_spec.rb +++ b/spec/models/blob_spec.rb @@ -1,7 +1,7 @@ # encoding: utf-8 # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Blob do include FakeBlobHelpers diff --git a/spec/models/board_spec.rb b/spec/models/board_spec.rb index 54452faa0e1..f6eee67e539 100644 --- a/spec/models/board_spec.rb +++ b/spec/models/board_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Board do describe 'relationships' do diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 7d84d094bdf..63ca383ac4b 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -323,6 +323,25 @@ describe Ci::Pipeline, :mailer do end end + describe '#merge_train_pipeline?' do + subject { pipeline.merge_train_pipeline? } + + let!(:pipeline) do + create(:ci_pipeline, source: :merge_request_event, merge_request: merge_request, ref: ref, target_sha: 'xxx') + end + + let(:merge_request) { create(:merge_request) } + let(:ref) { 'refs/merge-requests/1/train' } + + it { is_expected.to be_truthy } + + context 'when ref is merge ref' do + let(:ref) { 'refs/merge-requests/1/merge' } + + it { is_expected.to be_falsy } + end + end + describe '#merge_request_ref?' do subject { pipeline.merge_request_ref? } @@ -333,6 +352,48 @@ describe Ci::Pipeline, :mailer do end end + describe '#merge_train_ref?' do + subject { pipeline.merge_train_ref? } + + it 'calls Mergetrain#merge_train_ref?' do + expect(MergeRequest).to receive(:merge_train_ref?).with(pipeline.ref) + + subject + end + end + + describe '#merge_request_event_type' do + subject { pipeline.merge_request_event_type } + + before do + allow(pipeline).to receive(:merge_request_event?) { true } + end + + context 'when pipeline is merge train pipeline' do + before do + allow(pipeline).to receive(:merge_train_pipeline?) { true } + end + + it { is_expected.to eq(:merge_train) } + end + + context 'when pipeline is merge request pipeline' do + before do + allow(pipeline).to receive(:merge_request_pipeline?) { true } + end + + it { is_expected.to eq(:merged_result) } + end + + context 'when pipeline is detached merge request pipeline' do + before do + allow(pipeline).to receive(:detached_merge_request_pipeline?) { true } + end + + it { is_expected.to eq(:detached) } + end + end + describe '#legacy_detached_merge_request_pipeline?' do subject { pipeline.legacy_detached_merge_request_pipeline? } @@ -782,7 +843,8 @@ describe Ci::Pipeline, :mailer do 'CI_MERGE_REQUEST_TITLE' => merge_request.title, 'CI_MERGE_REQUEST_ASSIGNEES' => merge_request.assignee_username_list, 'CI_MERGE_REQUEST_MILESTONE' => milestone.title, - 'CI_MERGE_REQUEST_LABELS' => labels.map(&:title).join(',')) + 'CI_MERGE_REQUEST_LABELS' => labels.map(&:title).join(','), + 'CI_MERGE_REQUEST_EVENT_TYPE' => pipeline.merge_request_event_type.to_s) end context 'when source project does not exist' do diff --git a/spec/models/clusters/applications/cert_manager_spec.rb b/spec/models/clusters/applications/cert_manager_spec.rb index f6d5d05e4a0..bddc09decc3 100644 --- a/spec/models/clusters/applications/cert_manager_spec.rb +++ b/spec/models/clusters/applications/cert_manager_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Clusters::Applications::CertManager do let(:cert_manager) { create(:clusters_applications_cert_manager) } diff --git a/spec/models/clusters/applications/helm_spec.rb b/spec/models/clusters/applications/helm_spec.rb index 00b5c72a3d3..9672129bb1e 100644 --- a/spec/models/clusters/applications/helm_spec.rb +++ b/spec/models/clusters/applications/helm_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Clusters::Applications::Helm do include_examples 'cluster application core specs', :clusters_applications_helm diff --git a/spec/models/clusters/applications/ingress_spec.rb b/spec/models/clusters/applications/ingress_spec.rb index 057517d3820..f984f6ba0ce 100644 --- a/spec/models/clusters/applications/ingress_spec.rb +++ b/spec/models/clusters/applications/ingress_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Clusters::Applications::Ingress do let(:ingress) { create(:clusters_applications_ingress) } diff --git a/spec/models/clusters/applications/jupyter_spec.rb b/spec/models/clusters/applications/jupyter_spec.rb index 3ff66a074e4..1b39328752d 100644 --- a/spec/models/clusters/applications/jupyter_spec.rb +++ b/spec/models/clusters/applications/jupyter_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Clusters::Applications::Jupyter do include_examples 'cluster application core specs', :clusters_applications_jupyter diff --git a/spec/models/clusters/applications/knative_spec.rb b/spec/models/clusters/applications/knative_spec.rb index 334f10526cb..3825994b733 100644 --- a/spec/models/clusters/applications/knative_spec.rb +++ b/spec/models/clusters/applications/knative_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Clusters::Applications::Knative do let(:knative) { create(:clusters_applications_knative) } diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb index eb6ccba5584..8fc3b7e4c40 100644 --- a/spec/models/clusters/applications/prometheus_spec.rb +++ b/spec/models/clusters/applications/prometheus_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Clusters::Applications::Prometheus do include KubernetesHelpers diff --git a/spec/models/clusters/applications/runner_spec.rb b/spec/models/clusters/applications/runner_spec.rb index 4abe45a2152..b420a180524 100644 --- a/spec/models/clusters/applications/runner_spec.rb +++ b/spec/models/clusters/applications/runner_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Clusters::Applications::Runner do let(:ci_runner) { create(:ci_runner) } diff --git a/spec/models/concerns/blocks_json_serialization_spec.rb b/spec/models/concerns/blocks_json_serialization_spec.rb index e8657c45a93..0ef5be3cb61 100644 --- a/spec/models/concerns/blocks_json_serialization_spec.rb +++ b/spec/models/concerns/blocks_json_serialization_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe BlocksJsonSerialization do DummyModel = Class.new do diff --git a/spec/models/concerns/deployable_spec.rb b/spec/models/concerns/deployable_spec.rb index bb73dd8ade0..ad2c0770a2c 100644 --- a/spec/models/concerns/deployable_spec.rb +++ b/spec/models/concerns/deployable_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Deployable do describe '#create_deployment' do diff --git a/spec/models/concerns/deployment_platform_spec.rb b/spec/models/concerns/deployment_platform_spec.rb index 27f535487c8..220f244ad71 100644 --- a/spec/models/concerns/deployment_platform_spec.rb +++ b/spec/models/concerns/deployment_platform_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe DeploymentPlatform do let(:project) { create(:project) } diff --git a/spec/models/concerns/routable_spec.rb b/spec/models/concerns/routable_spec.rb index cff86afe768..cad705ee594 100644 --- a/spec/models/concerns/routable_spec.rb +++ b/spec/models/concerns/routable_spec.rb @@ -66,6 +66,13 @@ describe Group, 'Routable' do it { expect(described_class.find_by_full_path(group.to_param.upcase)).to eq(group) } it { expect(described_class.find_by_full_path(nested_group.to_param)).to eq(nested_group) } it { expect(described_class.find_by_full_path('unknown')).to eq(nil) } + + it 'includes route information when loading a record' do + path = group.to_param + control_count = ActiveRecord::QueryRecorder.new { described_class.find_by_full_path(path) }.count + + expect { described_class.find_by_full_path(path).route }.not_to exceed_all_query_limit(control_count) + end end context 'with redirect routes' do diff --git a/spec/models/concerns/triggerable_hooks_spec.rb b/spec/models/concerns/triggerable_hooks_spec.rb index f28e5f56411..ac1bc51d950 100644 --- a/spec/models/concerns/triggerable_hooks_spec.rb +++ b/spec/models/concerns/triggerable_hooks_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' RSpec.describe TriggerableHooks do before do diff --git a/spec/models/conversational_development_index/metric_spec.rb b/spec/models/conversational_development_index/metric_spec.rb index 60b1a860dfd..55ba466e614 100644 --- a/spec/models/conversational_development_index/metric_spec.rb +++ b/spec/models/conversational_development_index/metric_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe ConversationalDevelopmentIndex::Metric do let(:conv_dev_index) { create(:conversational_development_index_metric) } diff --git a/spec/models/gpg_key_spec.rb b/spec/models/gpg_key_spec.rb index 479b39cd139..b9c914e2506 100644 --- a/spec/models/gpg_key_spec.rb +++ b/spec/models/gpg_key_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe GpgKey do describe "associations" do diff --git a/spec/models/gpg_key_subkey_spec.rb b/spec/models/gpg_key_subkey_spec.rb index 51d2f9cb9ac..5f80cc02924 100644 --- a/spec/models/gpg_key_subkey_spec.rb +++ b/spec/models/gpg_key_subkey_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe GpgKeySubkey do subject { build(:gpg_key_subkey) } diff --git a/spec/models/gpg_signature_spec.rb b/spec/models/gpg_signature_spec.rb index 47c343edf0e..4911375c962 100644 --- a/spec/models/gpg_signature_spec.rb +++ b/spec/models/gpg_signature_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' RSpec.describe GpgSignature do let(:commit_sha) { '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33' } diff --git a/spec/models/hooks/system_hook_spec.rb b/spec/models/hooks/system_hook_spec.rb index e0d4d2e4858..a4d202dc4f8 100644 --- a/spec/models/hooks/system_hook_spec.rb +++ b/spec/models/hooks/system_hook_spec.rb @@ -64,7 +64,7 @@ describe SystemHook do ).once end - it "project_create hook" do + it "project member create hook" do project.add_maintainer(user) expect(WebMock).to have_requested(:post, system_hook.url).with( @@ -73,7 +73,7 @@ describe SystemHook do ).once end - it "project_destroy hook" do + it "project member destroy hook" do project.add_maintainer(user) project.project_members.destroy_all # rubocop: disable DestroyAll @@ -83,6 +83,15 @@ describe SystemHook do ).once end + it "project member update hook" do + project.add_guest(user) + + expect(WebMock).to have_requested(:post, system_hook.url).with( + body: /user_update_for_team/, + headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'System Hook' } + ).once + end + it 'group create hook' do create(:group) @@ -119,6 +128,16 @@ describe SystemHook do headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'System Hook' } ).once end + + it 'group member update hook' do + group.add_guest(user) + group.add_maintainer(user) + + expect(WebMock).to have_requested(:post, system_hook.url).with( + body: /user_update_for_group/, + headers: { 'Content-Type' => 'application/json', 'X-Gitlab-Event' => 'System Hook' } + ).once + end end describe '.repository_update_hooks' do diff --git a/spec/models/hooks/web_hook_log_spec.rb b/spec/models/hooks/web_hook_log_spec.rb index f812149c9be..85934b81086 100644 --- a/spec/models/hooks/web_hook_log_spec.rb +++ b/spec/models/hooks/web_hook_log_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe WebHookLog do it { is_expected.to belong_to(:web_hook) } diff --git a/spec/models/lfs_download_object_spec.rb b/spec/models/lfs_download_object_spec.rb index 8b53effe98f..d7522fbb969 100644 --- a/spec/models/lfs_download_object_spec.rb +++ b/spec/models/lfs_download_object_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe LfsDownloadObject do let(:oid) { 'cd293be6cea034bd45a0352775a219ef5dc7825ce55d1f7dae9762d80ce64411' } diff --git a/spec/models/lfs_file_lock_spec.rb b/spec/models/lfs_file_lock_spec.rb index aa64d66944b..a42346c341d 100644 --- a/spec/models/lfs_file_lock_spec.rb +++ b/spec/models/lfs_file_lock_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe LfsFileLock do set(:lfs_file_lock) { create(:lfs_file_lock) } diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb index 2429cd408a6..dc28204d7aa 100644 --- a/spec/models/list_spec.rb +++ b/spec/models/list_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe List do it_behaves_like 'having unique enum values' diff --git a/spec/models/merge_request_diff_commit_spec.rb b/spec/models/merge_request_diff_commit_spec.rb index ab2aadf7d88..c0a09dab0b0 100644 --- a/spec/models/merge_request_diff_commit_spec.rb +++ b/spec/models/merge_request_diff_commit_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe MergeRequestDiffCommit do let(:merge_request) { create(:merge_request) } diff --git a/spec/models/merge_request_diff_file_spec.rb b/spec/models/merge_request_diff_file_spec.rb index 66957c24fdc..97b30bb8607 100644 --- a/spec/models/merge_request_diff_file_spec.rb +++ b/spec/models/merge_request_diff_file_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe MergeRequestDiffFile do describe '#diff' do diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index d344a6d0f0d..11234982dd4 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -3195,6 +3195,40 @@ describe MergeRequest do end end + describe '.merge_train_ref?' do + subject { described_class.merge_train_ref?(ref) } + + context 'when ref is ref name of a branch' do + let(:ref) { 'feature' } + + it { is_expected.to be_falsey } + end + + context 'when ref is HEAD ref path of a branch' do + let(:ref) { 'refs/heads/feature' } + + it { is_expected.to be_falsey } + end + + context 'when ref is HEAD ref path of a merge request' do + let(:ref) { 'refs/merge-requests/1/head' } + + it { is_expected.to be_falsey } + end + + context 'when ref is merge ref path of a merge request' do + let(:ref) { 'refs/merge-requests/1/merge' } + + it { is_expected.to be_falsey } + end + + context 'when ref is train ref path of a merge request' do + let(:ref) { 'refs/merge-requests/1/train' } + + it { is_expected.to be_truthy } + end + end + describe '#cleanup_refs' do subject { merge_request.cleanup_refs(only: only) } diff --git a/spec/models/milestone_release_spec.rb b/spec/models/milestone_release_spec.rb new file mode 100644 index 00000000000..d6f73275977 --- /dev/null +++ b/spec/models/milestone_release_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe MilestoneRelease do + let(:project) { create(:project) } + let(:release) { create(:release, project: project) } + let(:milestone) { create(:milestone, project: project) } + + subject { build(:milestone_release, release: release, milestone: milestone) } + + describe 'associations' do + it { is_expected.to belong_to(:milestone) } + it { is_expected.to belong_to(:release) } + end + + describe 'validations' do + it { is_expected.to validate_uniqueness_of(:milestone_id).scoped_to(:release_id) } + + context 'when milestone and release do not have the same project' do + it 'is not valid' do + other_project = create(:project) + release = build(:release, project: other_project) + milestone_release = described_class.new(milestone: milestone, release: release) + expect(milestone_release).not_to be_valid + end + end + + context 'when milestone and release have the same project' do + it 'is valid' do + milestone_release = described_class.new(milestone: milestone, release: release) + expect(milestone_release).to be_valid + end + end + end +end diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb index 3704a2d468d..64030f5b92a 100644 --- a/spec/models/milestone_spec.rb +++ b/spec/models/milestone_spec.rb @@ -54,11 +54,31 @@ describe Milestone do expect(milestone.errors[:due_date]).to include("date must not be after 9999-12-31") end end + + describe 'milestone_release' do + let(:milestone) { build(:milestone, project: project) } + + context 'when it is tied to a release for another project' do + it 'creates a validation error' do + other_project = create(:project) + milestone.release = build(:release, project: other_project) + expect(milestone).not_to be_valid + end + end + + context 'when it is tied to a release for the same project' do + it 'is valid' do + milestone.release = build(:release, project: project) + expect(milestone).to be_valid + end + end + end end describe "Associations" do it { is_expected.to belong_to(:project) } it { is_expected.to have_many(:issues) } + it { is_expected.to have_one(:release) } end let(:project) { create(:project, :public) } diff --git a/spec/models/note_diff_file_spec.rb b/spec/models/note_diff_file_spec.rb index b15bedd257e..11108016b8e 100644 --- a/spec/models/note_diff_file_spec.rb +++ b/spec/models/note_diff_file_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe NoteDiffFile do describe 'associations' do diff --git a/spec/models/notification_setting_spec.rb b/spec/models/notification_setting_spec.rb index 85128456918..820d233dbdc 100644 --- a/spec/models/notification_setting_spec.rb +++ b/spec/models/notification_setting_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' RSpec.describe NotificationSetting do it_behaves_like 'having unique enum values' diff --git a/spec/models/project_deploy_token_spec.rb b/spec/models/project_deploy_token_spec.rb index 2a5fefc1ab0..8c8924762bd 100644 --- a/spec/models/project_deploy_token_spec.rb +++ b/spec/models/project_deploy_token_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' RSpec.describe ProjectDeployToken, type: :model do let(:project) { create(:project) } diff --git a/spec/models/project_import_state_spec.rb b/spec/models/project_import_state_spec.rb index 472bf8f9713..8a847bbe24e 100644 --- a/spec/models/project_import_state_spec.rb +++ b/spec/models/project_import_state_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe ProjectImportState, type: :model do subject { create(:import_state) } diff --git a/spec/models/project_statistics_spec.rb b/spec/models/project_statistics_spec.rb index a164ed9bbea..4bc6130387a 100644 --- a/spec/models/project_statistics_spec.rb +++ b/spec/models/project_statistics_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe ProjectStatistics do let(:project) { create :project } diff --git a/spec/models/redirect_route_spec.rb b/spec/models/redirect_route_spec.rb index 6ecb5c31c7e..b9b2873f8f2 100644 --- a/spec/models/redirect_route_spec.rb +++ b/spec/models/redirect_route_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe RedirectRoute do let(:group) { create(:group) } diff --git a/spec/models/release_spec.rb b/spec/models/release_spec.rb index e9d846e7291..c690390e24d 100644 --- a/spec/models/release_spec.rb +++ b/spec/models/release_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' RSpec.describe Release do let(:user) { create(:user) } @@ -13,6 +13,7 @@ RSpec.describe Release do it { is_expected.to belong_to(:project) } it { is_expected.to belong_to(:author).class_name('User') } it { is_expected.to have_many(:links).class_name('Releases::Link') } + it { is_expected.to have_one(:milestone) } end describe 'validation' do @@ -34,6 +35,20 @@ RSpec.describe Release do expect(existing_release_without_name.name).to be_nil end end + + context 'when a release is tied to a milestone for another project' do + it 'creates a validation error' do + release.milestone = build(:milestone, project: create(:project)) + expect(release).not_to be_valid + end + end + + context 'when a release is tied to a milestone linked to the same project' do + it 'is valid' do + release.milestone = build(:milestone, project: project) + expect(release).to be_valid + end + end end describe '#assets_count' do diff --git a/spec/models/remote_mirror_spec.rb b/spec/models/remote_mirror_spec.rb index f8d6e500e10..63d0bf3f314 100644 --- a/spec/models/remote_mirror_spec.rb +++ b/spec/models/remote_mirror_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe RemoteMirror, :mailer do include GitHelpers diff --git a/spec/models/resource_label_event_spec.rb b/spec/models/resource_label_event_spec.rb index cb52f154299..f4023dcb95a 100644 --- a/spec/models/resource_label_event_spec.rb +++ b/spec/models/resource_label_event_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' RSpec.describe ResourceLabelEvent, type: :model do subject { build(:resource_label_event, issue: issue) } diff --git a/spec/models/timelog_spec.rb b/spec/models/timelog_spec.rb index 9d69a0ab148..28fc82f2a32 100644 --- a/spec/models/timelog_spec.rb +++ b/spec/models/timelog_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' RSpec.describe Timelog do subject { build(:timelog) } diff --git a/spec/models/upload_spec.rb b/spec/models/upload_spec.rb index 02702cb2497..d97bb8cfb90 100644 --- a/spec/models/upload_spec.rb +++ b/spec/models/upload_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Upload do describe 'assocations' do diff --git a/spec/models/user_agent_detail_spec.rb b/spec/models/user_agent_detail_spec.rb index f191d245045..5c28511b446 100644 --- a/spec/models/user_agent_detail_spec.rb +++ b/spec/models/user_agent_detail_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe UserAgentDetail do describe '.submittable?' do diff --git a/spec/models/user_callout_spec.rb b/spec/models/user_callout_spec.rb index b87f6f03d6f..de6534b480a 100644 --- a/spec/models/user_callout_spec.rb +++ b/spec/models/user_callout_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe UserCallout do let!(:callout) { create(:user_callout) } diff --git a/spec/presenters/blob_presenter_spec.rb b/spec/presenters/blob_presenter_spec.rb index eacf383be7d..8680e8b9b45 100644 --- a/spec/presenters/blob_presenter_spec.rb +++ b/spec/presenters/blob_presenter_spec.rb @@ -39,6 +39,20 @@ describe BlobPresenter, :seed_helper do subject.highlight(plain: true) end + context '"to" param is present' do + before do + allow(git_blob) + .to receive(:data) + .and_return("line one\nline two\nline 3") + end + + it 'returns limited highlighted content' do + expect(Gitlab::Highlight).to receive(:highlight).with('files/ruby/regex.rb', "line one\n", plain: nil, language: nil) + + subject.highlight(to: 1) + end + end + context 'gitlab-language contains a match' do before do allow(blob).to receive(:language_from_gitattributes).and_return('ruby') diff --git a/spec/presenters/ci/pipeline_presenter_spec.rb b/spec/presenters/ci/pipeline_presenter_spec.rb index cda07a0ae09..7e8bbedcf6d 100644 --- a/spec/presenters/ci/pipeline_presenter_spec.rb +++ b/spec/presenters/ci/pipeline_presenter_spec.rb @@ -77,6 +77,40 @@ describe Ci::PipelinePresenter do end end + describe '#name' do + subject { presenter.name } + + context 'when pipeline is detached merge request pipeline' do + let(:merge_request) { create(:merge_request, :with_detached_merge_request_pipeline) } + let(:pipeline) { merge_request.all_pipelines.last } + + it { is_expected.to eq('Detached merge request pipeline') } + end + + context 'when pipeline is merge request pipeline' do + let(:merge_request) { create(:merge_request, :with_merge_request_pipeline) } + let(:pipeline) { merge_request.all_pipelines.last } + + it { is_expected.to eq('Merged result pipeline') } + end + + context 'when pipeline is merge train pipeline' do + let(:pipeline) { create(:ci_pipeline, project: project) } + + before do + allow(pipeline).to receive(:merge_request_event_type) { :merge_train } + end + + it { is_expected.to eq('Merge train pipeline') } + end + + context 'when pipeline is branch pipeline' do + let(:pipeline) { create(:ci_pipeline, project: project) } + + it { is_expected.to eq('Pipeline') } + end + end + describe '#ref_text' do subject { presenter.ref_text } diff --git a/spec/presenters/clusterable_presenter_spec.rb b/spec/presenters/clusterable_presenter_spec.rb index 05afe5347d1..47ccc59ae45 100644 --- a/spec/presenters/clusterable_presenter_spec.rb +++ b/spec/presenters/clusterable_presenter_spec.rb @@ -78,4 +78,13 @@ describe ClusterablePresenter do it_behaves_like 'appropriate member permissions' end end + + describe '#environments_cluster_path' do + subject { described_class.new(clusterable).environments_cluster_path(cluster) } + + let(:clusterable) { create(:group) } + let(:cluster) { create(:cluster_for_group, groups: [clusterable]) } + + it { is_expected.to be_nil } + end end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb deleted file mode 100644 index 671fd6c8666..00000000000 --- a/spec/rails_helper.rb +++ /dev/null @@ -1 +0,0 @@ -require "spec_helper" diff --git a/spec/requests/api/pages_domains_spec.rb b/spec/requests/api/pages_domains_spec.rb index 449032b95b7..326b724666d 100644 --- a/spec/requests/api/pages_domains_spec.rb +++ b/spec/requests/api/pages_domains_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe API::PagesDomains do set(:project) { create(:project, path: 'my.project', pages_https_only: false) } diff --git a/spec/requests/api/project_snippets_spec.rb b/spec/requests/api/project_snippets_spec.rb index 58a28e636f1..2e6e13aa927 100644 --- a/spec/requests/api/project_snippets_spec.rb +++ b/spec/requests/api/project_snippets_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe API::ProjectSnippets do set(:project) { create(:project, :public) } diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 5465fe0c366..550c7d135a6 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -5,6 +5,8 @@ shared_examples 'languages and percentages JSON response' do let(:expected_languages) { project.repository.languages.map { |language| language.values_at(:label, :value)}.to_h } before do + allow(DetectRepositoryLanguagesWorker).to receive(:perform_async).and_call_original + allow(project.repository).to receive(:languages).and_return( [{ value: 66.69, label: "Ruby", color: "#701516", highlight: "#701516" }, { value: 22.98, label: "JavaScript", color: "#f1e05a", highlight: "#f1e05a" }, diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb index cc05b8d5b45..515912cb305 100644 --- a/spec/requests/api/snippets_spec.rb +++ b/spec/requests/api/snippets_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe API::Snippets do let!(:user) { create(:user) } diff --git a/spec/serializers/entity_date_helper_spec.rb b/spec/serializers/entity_date_helper_spec.rb index ae0f917415c..73506954965 100644 --- a/spec/serializers/entity_date_helper_spec.rb +++ b/spec/serializers/entity_date_helper_spec.rb @@ -57,6 +57,28 @@ describe EntityDateHelper do end end + context 'when milestone due date is today' do + let(:milestone_remaining) { date_helper_class.remaining_days_in_words(Date.today) } + + it 'returns today' do + expect(milestone_remaining).to eq("<strong>Today</strong>") + end + end + + context 'when milestone due date is tomorrow' do + let(:milestone_remaining) { date_helper_class.remaining_days_in_words(Date.tomorrow) } + + it 'returns 1 day remaining' do + expect(milestone_remaining).to eq("<strong>1</strong> day remaining") + end + + it 'returns 1 day remaining when queried mid-day' do + Timecop.freeze(Time.utc(2017, 3, 17, 13, 10)) do + expect(milestone_remaining).to eq("<strong>1</strong> day remaining") + end + end + end + context 'when less than 1 year and more than 30 days remaining' do let(:milestone_remaining) { date_helper_class.remaining_days_in_words(2.months.from_now.utc.to_date) } diff --git a/spec/serializers/pipeline_entity_spec.rb b/spec/serializers/pipeline_entity_spec.rb index 6be612ec226..eb9972d3e4d 100644 --- a/spec/serializers/pipeline_entity_spec.rb +++ b/spec/serializers/pipeline_entity_spec.rb @@ -41,7 +41,7 @@ describe PipelineEntity do it 'contains details' do expect(subject).to include :details expect(subject[:details]) - .to include :duration, :finished_at + .to include :duration, :finished_at, :name expect(subject[:details][:status]).to include :icon, :favicon, :text, :label, :tooltip end @@ -211,6 +211,10 @@ describe PipelineEntity do expect(subject[:source_sha]).to be_present expect(subject[:target_sha]).to be_present end + + it 'exposes merge request event type' do + expect(subject[:merge_request_event_type]).to be_present + end end end end diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb index 3ca389ba25b..2807b8c8c85 100644 --- a/spec/services/auth/container_registry_authentication_service_spec.rb +++ b/spec/services/auth/container_registry_authentication_service_spec.rb @@ -476,7 +476,7 @@ describe Auth::ContainerRegistryAuthenticationService do let(:current_user) { create(:user) } let(:authentication_abilities) do - [:build_read_container_image, :build_create_container_image] + [:build_read_container_image, :build_create_container_image, :build_destroy_container_image] end before do @@ -507,19 +507,19 @@ describe Auth::ContainerRegistryAuthenticationService do end end - context 'disallow to delete images' do + context 'allow to delete images since registry 2.7' do let(:current_params) do - { scopes: ["repository:#{current_project.full_path}:*"] } + { scopes: ["repository:#{current_project.full_path}:delete"] } end - it_behaves_like 'an inaccessible' do + it_behaves_like 'a deletable since registry 2.7' do let(:project) { current_project } end end - context 'disallow to delete images since registry 2.7' do + context 'disallow to delete images' do let(:current_params) do - { scopes: ["repository:#{current_project.full_path}:delete"] } + { scopes: ["repository:#{current_project.full_path}:*"] } end it_behaves_like 'an inaccessible' do diff --git a/spec/services/groups/transfer_service_spec.rb b/spec/services/groups/transfer_service_spec.rb index f3af8cf5f3b..0cbb3122bb0 100644 --- a/spec/services/groups/transfer_service_spec.rb +++ b/spec/services/groups/transfer_service_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Groups::TransferService do let(:user) { create(:user) } diff --git a/spec/services/metrics/dashboard/project_dashboard_service_spec.rb b/spec/services/metrics/dashboard/project_dashboard_service_spec.rb index 1357914be2a..e76db868425 100644 --- a/spec/services/metrics/dashboard/project_dashboard_service_spec.rb +++ b/spec/services/metrics/dashboard/project_dashboard_service_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe Metrics::Dashboard::ProjectDashboardService, :use_clean_rails_memory_store_caching do include MetricsDashboardHelpers diff --git a/spec/services/milestones/destroy_service_spec.rb b/spec/services/milestones/destroy_service_spec.rb index 3a22e4d4f92..ff1e1256166 100644 --- a/spec/services/milestones/destroy_service_spec.rb +++ b/spec/services/milestones/destroy_service_spec.rb @@ -65,5 +65,19 @@ describe Milestones::DestroyService do expect { service.execute(group_milestone) }.not_to change { Event.count } end end + + context 'when a release is tied to a milestone' do + it 'destroys the milestone but not the associated release' do + release = create( + :release, + tag: 'v1.0', + project: project, + milestone: milestone + ) + + expect { service.execute(milestone) }.not_to change { Release.count } + expect(release.reload).to be_persisted + end + end end end diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index ab0e01e27d7..bd6734634cb 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -278,6 +278,7 @@ describe NotificationService, :mailer do notification.new_note(note) should_email(note.author) + expect(find_email_for(note.author)).to have_header('X-GitLab-NotificationReason', 'own_activity') end it_behaves_like 'project emails are disabled' do @@ -335,6 +336,9 @@ describe NotificationService, :mailer do should_not_email(@u_participating) should_not_email(@u_disabled) should_not_email(@u_lazy_participant) + + expect(find_email_for(@u_mentioned)).to have_header('X-GitLab-NotificationReason', 'mentioned') + expect(find_email_for(@u_custom_global)).to have_header('X-GitLab-NotificationReason', '') end end diff --git a/spec/services/releases/create_service_spec.rb b/spec/services/releases/create_service_spec.rb index e26676cdd55..5c9d6537df1 100644 --- a/spec/services/releases/create_service_spec.rb +++ b/spec/services/releases/create_service_spec.rb @@ -72,6 +72,15 @@ describe Releases::CreateService do expect(project.releases.find_by(tag: tag_name).description).to eq(description) end end + + context 'when a passed-in milestone does not exist for this project' do + it 'raises an error saying the milestone is inexistent' do + service = described_class.new(project, user, params.merge!({ milestone: 'v111.0' })) + result = service.execute + expect(result[:status]).to eq(:error) + expect(result[:message]).to eq('Milestone does not exist') + end + end end describe '#find_or_build_release' do @@ -80,5 +89,58 @@ describe Releases::CreateService do expect(project.releases.count).to eq(0) end + + context 'when existing milestone is passed in' do + let(:title) { 'v1.0' } + let(:milestone) { create(:milestone, :active, project: project, title: title) } + let(:params_with_milestone) { params.merge!({ milestone: title }) } + + it 'creates a release and ties this milestone to it' do + service = described_class.new(milestone.project, user, params_with_milestone) + result = service.execute + + expect(project.releases.count).to eq(1) + expect(result[:status]).to eq(:success) + + release = project.releases.last + + expect(release.milestone).to eq(milestone) + end + + context 'when another release was previously created with that same milestone linked' do + it 'also creates another release tied to that same milestone' do + other_release = create(:release, milestone: milestone, project: project, tag: 'v1.0') + service = described_class.new(milestone.project, user, params_with_milestone) + service.execute + release = project.releases.last + + expect(release.milestone).to eq(milestone) + expect(other_release.milestone).to eq(milestone) + expect(release.id).not_to eq(other_release.id) + end + end + end + + context 'when no milestone is passed in' do + it 'creates a release without a milestone tied to it' do + expect(params.key? :milestone).to be_falsey + service.execute + release = project.releases.last + expect(release.milestone).to be_nil + end + + it 'does not create any new MilestoneRelease object' do + expect { service.execute }.not_to change { MilestoneRelease.count } + end + end + + context 'when an empty value is passed as a milestone' do + it 'creates a release without a milestone tied to it' do + service = described_class.new(project, user, params.merge!({ milestone: '' })) + service.execute + release = project.releases.last + expect(release.milestone).to be_nil + end + end end end diff --git a/spec/services/releases/destroy_service_spec.rb b/spec/services/releases/destroy_service_spec.rb index f4c901e6585..c3172e5edbc 100644 --- a/spec/services/releases/destroy_service_spec.rb +++ b/spec/services/releases/destroy_service_spec.rb @@ -57,5 +57,15 @@ describe Releases::DestroyService do http_status: 403) end end + + context 'when a milestone is tied to the release' do + let!(:milestone) { create(:milestone, :active, project: project, title: 'v1.0') } + let!(:release) { create(:release, milestone: milestone, project: project, tag: tag) } + + it 'destroys the release but leave the milestone intact' do + expect { subject }.not_to change { Milestone.count } + expect(milestone.reload).to be_persisted + end + end end end diff --git a/spec/services/releases/update_service_spec.rb b/spec/services/releases/update_service_spec.rb index 14e6a5f13c8..944f3d8c9ad 100644 --- a/spec/services/releases/update_service_spec.rb +++ b/spec/services/releases/update_service_spec.rb @@ -48,5 +48,42 @@ describe Releases::UpdateService do it_behaves_like 'a failed update' end + + context 'when a milestone is passed in' do + let(:old_title) { 'v1.0' } + let(:new_title) { 'v2.0' } + let(:milestone) { create(:milestone, project: project, title: old_title) } + let(:new_milestone) { create(:milestone, project: project, title: new_title) } + let(:params_with_milestone) { params.merge!({ milestone: new_title }) } + + before do + release.milestone = milestone + release.save! + + described_class.new(new_milestone.project, user, params_with_milestone).execute + release.reload + end + + it 'updates the related milestone accordingly' do + expect(release.milestone.title).to eq(new_title) + end + end + + context "when an 'empty' milestone is passed in" do + let(:milestone) { create(:milestone, project: project, title: 'v1.0') } + let(:params_with_empty_milestone) { params.merge!({ milestone: '' }) } + + before do + release.milestone = milestone + release.save! + + described_class.new(milestone.project, user, params_with_empty_milestone).execute + release.reload + end + + it 'removes the old milestone and does not associate any new milestone' do + expect(release.milestone).to be_nil + end + end end end diff --git a/spec/services/system_hooks_service_spec.rb b/spec/services/system_hooks_service_spec.rb index f5c6e972953..d72e5cc2b16 100644 --- a/spec/services/system_hooks_service_spec.rb +++ b/spec/services/system_hooks_service_spec.rb @@ -19,6 +19,7 @@ describe SystemHooksService do it { expect(event_data(project, :destroy)).to include(:event_name, :name, :created_at, :updated_at, :path, :project_id, :owner_name, :owner_email, :project_visibility) } it { expect(event_data(project_member, :create)).to include(:event_name, :created_at, :updated_at, :project_name, :project_path, :project_path_with_namespace, :project_id, :user_name, :user_username, :user_email, :user_id, :access_level, :project_visibility) } it { expect(event_data(project_member, :destroy)).to include(:event_name, :created_at, :updated_at, :project_name, :project_path, :project_path_with_namespace, :project_id, :user_name, :user_username, :user_email, :user_id, :access_level, :project_visibility) } + it { expect(event_data(project_member, :update)).to include(:event_name, :created_at, :updated_at, :project_name, :project_path, :project_path_with_namespace, :project_id, :user_name, :user_username, :user_email, :user_id, :access_level, :project_visibility) } it { expect(event_data(key, :create)).to include(:username, :key, :id) } it { expect(event_data(key, :destroy)).to include(:username, :key, :id) } it { expect(event_data(deploy_key, :create)).to include(:key, :id) } @@ -70,6 +71,13 @@ describe SystemHooksService do ) end + it do + expect(event_data(group_member, :update)).to include( + :event_name, :created_at, :updated_at, :group_name, :group_path, + :group_id, :user_id, :user_username, :user_name, :user_email, :group_access + ) + end + it 'includes the correct project visibility level' do data = event_data(project, :create) @@ -145,6 +153,7 @@ describe SystemHooksService do it { expect(event_name(project, :update)).to eq "project_update" } it { expect(event_name(project_member, :create)).to eq "user_add_to_team" } it { expect(event_name(project_member, :destroy)).to eq "user_remove_from_team" } + it { expect(event_name(project_member, :update)).to eq "user_update_for_team" } it { expect(event_name(key, :create)).to eq 'key_create' } it { expect(event_name(key, :destroy)).to eq 'key_destroy' } it { expect(event_name(group, :create)).to eq 'group_create' } @@ -152,6 +161,7 @@ describe SystemHooksService do it { expect(event_name(group, :rename)).to eq 'group_rename' } it { expect(event_name(group_member, :create)).to eq 'user_add_to_group' } it { expect(event_name(group_member, :destroy)).to eq 'user_remove_from_group' } + it { expect(event_name(group_member, :update)).to eq 'user_update_for_group' } end def event_data(*args) diff --git a/spec/services/update_merge_request_metrics_service_spec.rb b/spec/services/update_merge_request_metrics_service_spec.rb index 12a2b287c72..bb07dfa1a0e 100644 --- a/spec/services/update_merge_request_metrics_service_spec.rb +++ b/spec/services/update_merge_request_metrics_service_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe MergeRequestMetricsService do let(:metrics) { create(:merge_request).metrics } diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index bd504f1553b..6ce76af556f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -148,6 +148,12 @@ RSpec.configure do |config| .with(:force_autodevops_on_by_default, anything) .and_return(false) + # Stub this call due to being an expensive operation + # It can be reenabled for specific tests via: + # + # allow(DetectRepositoryLanguagesWorker).to receive(:perform_async).and_call_original + allow(DetectRepositoryLanguagesWorker).to receive(:perform_async).and_return(true) + Gitlab::ThreadMemoryCache.cache_backend.clear end diff --git a/spec/support/helpers/project_forks_helper.rb b/spec/support/helpers/project_forks_helper.rb index b2d22853e4c..90d0d1845fc 100644 --- a/spec/support/helpers/project_forks_helper.rb +++ b/spec/support/helpers/project_forks_helper.rb @@ -45,7 +45,7 @@ module ProjectForksHelper # not reset the @exists variable of this forked_project.repository # so we have to explicitly call this method to clear the @exists variable. # of the instance we're returning here. - forked_project.repository.after_import + forked_project.repository.expire_content_cache end forked_project diff --git a/spec/support/helpers/rails_helpers.rb b/spec/support/helpers/rails_helpers.rb new file mode 100644 index 00000000000..e1875b2fb15 --- /dev/null +++ b/spec/support/helpers/rails_helpers.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module RailsHelpers + def stub_rails_env(env_name) + allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new(env_name)) + end +end diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb index a4acf76e1a3..8ca362ce2df 100644 --- a/spec/support/helpers/test_env.rb +++ b/spec/support/helpers/test_env.rb @@ -244,7 +244,6 @@ module TestEnv FileUtils.mkdir_p(target_repo_path) FileUtils.cp_r("#{File.expand_path(bare_repo)}/.", target_repo_path) FileUtils.chmod_R 0755, target_repo_path - set_repo_refs(target_repo_path, refs) end def create_bare_repository(path) diff --git a/spec/uploaders/gitlab_uploader_spec.rb b/spec/uploaders/gitlab_uploader_spec.rb index 44718ed1212..3bee4875348 100644 --- a/spec/uploaders/gitlab_uploader_spec.rb +++ b/spec/uploaders/gitlab_uploader_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' require 'carrierwave/storage/fog' describe GitlabUploader do diff --git a/spec/uploaders/object_storage_spec.rb b/spec/uploaders/object_storage_spec.rb index 6bad5d49b1c..0cf486c7087 100644 --- a/spec/uploaders/object_storage_spec.rb +++ b/spec/uploaders/object_storage_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' require 'carrierwave/storage/fog' class Implementation < GitlabUploader diff --git a/spec/uploaders/records_uploads_spec.rb b/spec/uploaders/records_uploads_spec.rb index 6134137d2b7..046ad3406d9 100644 --- a/spec/uploaders/records_uploads_spec.rb +++ b/spec/uploaders/records_uploads_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe RecordsUploads do let!(:uploader) do diff --git a/spec/uploaders/uploader_helper_spec.rb b/spec/uploaders/uploader_helper_spec.rb index fd6712d4645..7c9ec8ff59c 100644 --- a/spec/uploaders/uploader_helper_spec.rb +++ b/spec/uploaders/uploader_helper_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe UploaderHelper do let(:uploader) do diff --git a/spec/views/devise/shared/_signin_box.html.haml_spec.rb b/spec/views/devise/shared/_signin_box.html.haml_spec.rb index 5d521d18c70..0563984a03c 100644 --- a/spec/views/devise/shared/_signin_box.html.haml_spec.rb +++ b/spec/views/devise/shared/_signin_box.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe 'devise/shared/_signin_box' do describe 'Crowd form' do diff --git a/spec/views/help/index.html.haml_spec.rb b/spec/views/help/index.html.haml_spec.rb index 257991549a9..f25e05dca7f 100644 --- a/spec/views/help/index.html.haml_spec.rb +++ b/spec/views/help/index.html.haml_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe 'help/index' do include StubVersion diff --git a/spec/views/help/instance_configuration.html.haml_spec.rb b/spec/views/help/instance_configuration.html.haml_spec.rb index ceb7e34a540..18628ddebf7 100644 --- a/spec/views/help/instance_configuration.html.haml_spec.rb +++ b/spec/views/help/instance_configuration.html.haml_spec.rb @@ -1,4 +1,4 @@ -require 'rails_helper' +require 'spec_helper' describe 'help/instance_configuration' do describe 'General Sections:' do diff --git a/spec/views/projects/settings/operations/show.html.haml_spec.rb b/spec/views/projects/settings/operations/show.html.haml_spec.rb index 6762fe3759b..ece9c16650f 100644 --- a/spec/views/projects/settings/operations/show.html.haml_spec.rb +++ b/spec/views/projects/settings/operations/show.html.haml_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'spec_helper' -require 'rails_helper' describe 'projects/settings/operations/show' do let(:project) { create(:project) } diff --git a/spec/workers/repository_remove_remote_worker_spec.rb b/spec/workers/repository_remove_remote_worker_spec.rb index 6eba5c50960..afac9212fab 100644 --- a/spec/workers/repository_remove_remote_worker_spec.rb +++ b/spec/workers/repository_remove_remote_worker_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe RepositoryRemoveRemoteWorker do include ExclusiveLeaseHelpers diff --git a/spec/workers/repository_update_remote_mirror_worker_spec.rb b/spec/workers/repository_update_remote_mirror_worker_spec.rb index 66d517332ba..7bc499d480d 100644 --- a/spec/workers/repository_update_remote_mirror_worker_spec.rb +++ b/spec/workers/repository_update_remote_mirror_worker_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe RepositoryUpdateRemoteMirrorWorker, :clean_gitlab_redis_shared_state do subject { described_class.new } diff --git a/spec/workers/upload_checksum_worker_spec.rb b/spec/workers/upload_checksum_worker_spec.rb index 7202c8001b4..ad054f0ff72 100644 --- a/spec/workers/upload_checksum_worker_spec.rb +++ b/spec/workers/upload_checksum_worker_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require 'rails_helper' +require 'spec_helper' describe UploadChecksumWorker do describe '#perform' do |