diff options
330 files changed, 2428 insertions, 1215 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index cc27ac3677b..488d2f261e7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -327,7 +327,7 @@ review-docs-cleanup: cloud-native-image: image: ruby:2.4-alpine before_script: [] - stage: build + stage: test allow_failure: true variables: GIT_DEPTH: "1" diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 54e3b8217d8..d8c4e965190 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -808,20 +808,6 @@ Style/UnlessElse: Style/UnneededInterpolation: Enabled: false -# Offense count: 11 -# Cop supports --auto-correct. -Style/ZeroLengthPredicate: - Exclude: - - 'app/models/deploy_key.rb' - - 'app/models/network/commit.rb' - - 'app/models/network/graph.rb' - - 'app/models/project_services/asana_service.rb' - - 'app/services/boards/create_service.rb' - - 'app/services/merge_requests/conflicts/list_service.rb' - - 'lib/declarative_policy/dsl.rb' - - 'lib/extracts_path.rb' - - 'lib/gitlab/git/repository.rb' - # Offense count: 22840 # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https diff --git a/app/assets/javascripts/behaviors/index.js b/app/assets/javascripts/behaviors/index.js index 84fef4d8b4f..8c4eccc34a3 100644 --- a/app/assets/javascripts/behaviors/index.js +++ b/app/assets/javascripts/behaviors/index.js @@ -1,15 +1,19 @@ import './autosize'; import './bind_in_out'; import './markdown/render_gfm'; +import initGFMInput from './markdown/gfm_auto_complete'; import initCopyAsGFM from './markdown/copy_as_gfm'; import initCopyToClipboard from './copy_to_clipboard'; import './details_behavior'; import installGlEmojiElement from './gl_emoji'; import './quick_submit'; import './requires_input'; +import initPageShortcuts from './shortcuts'; import './toggler_behavior'; -import '../preview_markdown'; +import './preview_markdown'; installGlEmojiElement(); +initGFMInput(); initCopyAsGFM(); initCopyToClipboard(); +initPageShortcuts(); diff --git a/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js b/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js new file mode 100644 index 00000000000..a303e504cc7 --- /dev/null +++ b/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js @@ -0,0 +1,19 @@ +import $ from 'jquery'; +import { convertPermissionToBoolean } from '~/lib/utils/common_utils'; +import GfmAutoComplete from '~/gfm_auto_complete'; + +export default function initGFMInput() { + $('.js-gfm-input:not(.js-vue-textarea)').each((i, el) => { + const gfm = new GfmAutoComplete(gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources); + const enableGFM = convertPermissionToBoolean(el.dataset.supportsAutocomplete); + + gfm.setup($(el), { + emojis: true, + members: enableGFM, + issues: enableGFM, + milestones: enableGFM, + mergeRequests: enableGFM, + labels: enableGFM, + }); + }); +} diff --git a/app/assets/javascripts/preview_markdown.js b/app/assets/javascripts/behaviors/preview_markdown.js index 0964baf8954..0964baf8954 100644 --- a/app/assets/javascripts/preview_markdown.js +++ b/app/assets/javascripts/behaviors/preview_markdown.js diff --git a/app/assets/javascripts/behaviors/shortcuts.js b/app/assets/javascripts/behaviors/shortcuts.js new file mode 100644 index 00000000000..7987a533ae5 --- /dev/null +++ b/app/assets/javascripts/behaviors/shortcuts.js @@ -0,0 +1,35 @@ +import Shortcuts from './shortcuts/shortcuts'; + +export default function initPageShortcuts() { + const { page } = document.body.dataset; + const pagesWithCustomShortcuts = [ + 'projects:activity', + 'projects:artifacts:browse', + 'projects:artifacts:file', + 'projects:blame:show', + 'projects:blob:show', + 'projects:commit:show', + 'projects:commits:show', + 'projects:find_file:show', + 'projects:issues:edit', + 'projects:issues:index', + 'projects:issues:new', + 'projects:issues:show', + 'projects:merge_requests:creations:diffs', + 'projects:merge_requests:creations:new', + 'projects:merge_requests:edit', + 'projects:merge_requests:index', + 'projects:merge_requests:show', + 'projects:network:show', + 'projects:show', + 'projects:tree:show', + 'groups:show', + ]; + + // the pages above have their own shortcuts sub-classes instantiated elsewhere + // TODO: replace this whitelist with something more automated/maintainable + if (page && !pagesWithCustomShortcuts.includes(page)) { + return new Shortcuts(); + } + return false; +} diff --git a/app/assets/javascripts/shortcuts.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js index 99c71d6524a..6719bfd6d22 100644 --- a/app/assets/javascripts/shortcuts.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js @@ -1,9 +1,9 @@ import $ from 'jquery'; import Cookies from 'js-cookie'; import Mousetrap from 'mousetrap'; -import axios from './lib/utils/axios_utils'; -import { refreshCurrentPage, visitUrl } from './lib/utils/url_utility'; -import findAndFollowLink from './shortcuts_dashboard_navigation'; +import axios from '../../lib/utils/axios_utils'; +import { refreshCurrentPage, visitUrl } from '../../lib/utils/url_utility'; +import findAndFollowLink from '../../lib/utils/navigation_utility'; const defaultStopCallback = Mousetrap.stopCallback; Mousetrap.stopCallback = (e, element, combo) => { diff --git a/app/assets/javascripts/shortcuts_blob.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_blob.js index 908b9cab93d..052e33b4a2b 100644 --- a/app/assets/javascripts/shortcuts_blob.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_blob.js @@ -1,5 +1,5 @@ import Mousetrap from 'mousetrap'; -import { getLocationHash, visitUrl } from './lib/utils/url_utility'; +import { getLocationHash, visitUrl } from '../../lib/utils/url_utility'; import Shortcuts from './shortcuts'; const defaults = { diff --git a/app/assets/javascripts/shortcuts_find_file.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_find_file.js index 8658081c6c2..8658081c6c2 100644 --- a/app/assets/javascripts/shortcuts_find_file.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_find_file.js diff --git a/app/assets/javascripts/shortcuts_issuable.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js index e9451be31fd..5e48bf5a35c 100644 --- a/app/assets/javascripts/shortcuts_issuable.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js @@ -1,9 +1,9 @@ import $ from 'jquery'; import Mousetrap from 'mousetrap'; import _ from 'underscore'; -import Sidebar from './right_sidebar'; +import Sidebar from '../../right_sidebar'; import Shortcuts from './shortcuts'; -import { CopyAsGFM } from './behaviors/markdown/copy_as_gfm'; +import { CopyAsGFM } from '../markdown/copy_as_gfm'; export default class ShortcutsIssuable extends Shortcuts { constructor(isMergeRequest) { diff --git a/app/assets/javascripts/shortcuts_navigation.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_navigation.js index 6b595764bc5..fa9b2c9f755 100644 --- a/app/assets/javascripts/shortcuts_navigation.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_navigation.js @@ -1,5 +1,5 @@ import Mousetrap from 'mousetrap'; -import findAndFollowLink from './shortcuts_dashboard_navigation'; +import findAndFollowLink from '../../lib/utils/navigation_utility'; import Shortcuts from './shortcuts'; export default class ShortcutsNavigation extends Shortcuts { diff --git a/app/assets/javascripts/shortcuts_network.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_network.js index a88c280fa3b..a88c280fa3b 100644 --- a/app/assets/javascripts/shortcuts_network.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_network.js diff --git a/app/assets/javascripts/shortcuts_wiki.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js index 41865dcf4ba..8b7e6a56d25 100644 --- a/app/assets/javascripts/shortcuts_wiki.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js @@ -1,6 +1,6 @@ import Mousetrap from 'mousetrap'; import ShortcutsNavigation from './shortcuts_navigation'; -import findAndFollowLink from './shortcuts_dashboard_navigation'; +import findAndFollowLink from '../../lib/utils/navigation_utility'; export default class ShortcutsWiki extends ShortcutsNavigation { constructor() { diff --git a/app/assets/javascripts/boards/components/board_blank_state.vue b/app/assets/javascripts/boards/components/board_blank_state.vue index 286529b4d13..cde22725a89 100644 --- a/app/assets/javascripts/boards/components/board_blank_state.vue +++ b/app/assets/javascripts/boards/components/board_blank_state.vue @@ -83,7 +83,7 @@ export default { right on the way to making the most of your board. </p> <button - class="btn btn-create btn-inverted btn-block" + class="btn btn-success btn-inverted btn-block" type="button" @click.stop="addDefaultLists"> Add default lists diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js index bc263cbbfea..8be99566f09 100644 --- a/app/assets/javascripts/boards/index.js +++ b/app/assets/javascripts/boards/index.js @@ -229,7 +229,7 @@ export default () => { template: ` <div class="board-extra-actions"> <button - class="btn btn-create prepend-left-10" + class="btn btn-success prepend-left-10" type="button" data-placement="bottom" ref="addIssuesButton" diff --git a/app/assets/javascripts/commons/polyfills.js b/app/assets/javascripts/commons/polyfills.js index 742cf490ad2..539d0d29e0d 100644 --- a/app/assets/javascripts/commons/polyfills.js +++ b/app/assets/javascripts/commons/polyfills.js @@ -14,10 +14,10 @@ import 'core-js/es6/map'; import 'core-js/es6/weak-map'; // Browser polyfills -import 'classlist-polyfill'; import 'formdata-polyfill'; import './polyfills/custom_event'; import './polyfills/element'; import './polyfills/event'; import './polyfills/nodelist'; import './polyfills/request_idle_callback'; +import './polyfills/svg'; diff --git a/app/assets/javascripts/commons/polyfills/element.js b/app/assets/javascripts/commons/polyfills/element.js index b593bde6aa2..dde5e8f54f9 100644 --- a/app/assets/javascripts/commons/polyfills/element.js +++ b/app/assets/javascripts/commons/polyfills/element.js @@ -1,12 +1,17 @@ -Element.prototype.closest = Element.prototype.closest || +// polyfill Element.classList and DOMTokenList with classList.js +import 'classlist-polyfill'; + +Element.prototype.closest = + Element.prototype.closest || function closest(selector, selectedElement = this) { if (!selectedElement) return null; - return selectedElement.matches(selector) ? - selectedElement : - Element.prototype.closest(selector, selectedElement.parentElement); + return selectedElement.matches(selector) + ? selectedElement + : Element.prototype.closest(selector, selectedElement.parentElement); }; -Element.prototype.matches = Element.prototype.matches || +Element.prototype.matches = + Element.prototype.matches || Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || @@ -15,13 +20,15 @@ Element.prototype.matches = Element.prototype.matches || function matches(selector) { const elms = (this.document || this.ownerDocument).querySelectorAll(selector); let i = elms.length - 1; - while (i >= 0 && elms.item(i) !== this) { i -= 1; } + while (i >= 0 && elms.item(i) !== this) { + i -= 1; + } return i > -1; }; // From the polyfill on MDN, https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove#Polyfill -((arr) => { - arr.forEach((item) => { +(arr => { + arr.forEach(item => { if (Object.prototype.hasOwnProperty.call(item, 'remove')) { return; } diff --git a/app/assets/javascripts/commons/polyfills/svg.js b/app/assets/javascripts/commons/polyfills/svg.js new file mode 100644 index 00000000000..8648a568f6f --- /dev/null +++ b/app/assets/javascripts/commons/polyfills/svg.js @@ -0,0 +1,5 @@ +import svg4everybody from 'svg4everybody'; + +// polyfill support for external SVG file references via <use xlink:href> +// @see https://css-tricks.com/svg-use-external-source/ +svg4everybody(); diff --git a/app/assets/javascripts/diffs/components/diff_line_note_form.vue b/app/assets/javascripts/diffs/components/diff_line_note_form.vue index a0dc381ccc7..0fa14615532 100644 --- a/app/assets/javascripts/diffs/components/diff_line_note_form.vue +++ b/app/assets/javascripts/diffs/components/diff_line_note_form.vue @@ -22,7 +22,7 @@ export default { type: Object, required: true, }, - position: { + linePosition: { type: String, required: false, default: '', @@ -81,7 +81,7 @@ export default { noteTargetLine: this.noteTargetLine, diffViewType: this.diffViewType, diffFile: selectedDiffFile, - linePosition: this.position, + linePosition: this.linePosition, }); this.saveNote(postData) diff --git a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue index 0e306f39a9f..62fa34e835a 100644 --- a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue +++ b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue @@ -1,5 +1,5 @@ <script> -import { mapGetters } from 'vuex'; +import { mapGetters, mapActions } from 'vuex'; import DiffTableCell from './diff_table_cell.vue'; import { NEW_LINE_TYPE, @@ -63,7 +63,11 @@ export default { this.linePositionLeft = LINE_POSITION_LEFT; this.linePositionRight = LINE_POSITION_RIGHT; }, + mounted() { + this.scrollToLineIfNeededInline(this.line); + }, methods: { + ...mapActions('diffs', ['scrollToLineIfNeededInline']), handleMouseMove(e) { // To show the comment icon on the gutter we need to know if we hover the line. // Current table structure doesn't allow us to do this with CSS in both of the diff view types diff --git a/app/assets/javascripts/diffs/components/no_changes.vue b/app/assets/javascripts/diffs/components/no_changes.vue index d817157fbcd..6905630ad8c 100644 --- a/app/assets/javascripts/diffs/components/no_changes.vue +++ b/app/assets/javascripts/diffs/components/no_changes.vue @@ -38,7 +38,7 @@ export default { <div class="text-center"> <a :href="newBlobPath" - class="btn btn-save" + class="btn btn-success" > {{ __('Create commit') }} </a> diff --git a/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue b/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue index 26417c350cb..3339c56cbb6 100644 --- a/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue +++ b/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue @@ -92,7 +92,7 @@ export default { :diff-file-hash="diffFileHash" :line="line.left" :note-target-line="line.left" - position="left" + line-position="left" /> </td> <td class="notes_line new"></td> @@ -111,7 +111,7 @@ export default { :diff-file-hash="diffFileHash" :line="line.right" :note-target-line="line.right" - position="right" + line-position="right" /> </td> </tr> diff --git a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue index fb68d191091..fcc3b3e9117 100644 --- a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue +++ b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue @@ -1,4 +1,5 @@ <script> +import { mapActions } from 'vuex'; import $ from 'jquery'; import DiffTableCell from './diff_table_cell.vue'; import { @@ -64,7 +65,11 @@ export default { this.oldLineType = OLD_LINE_TYPE; this.parallelDiffViewType = PARALLEL_DIFF_VIEW_TYPE; }, + mounted() { + this.scrollToLineIfNeededParallel(this.line); + }, methods: { + ...mapActions('diffs', ['scrollToLineIfNeededParallel']), handleMouseMove(e) { const isHover = e.type === 'mouseover'; const hoveringCell = e.target.closest('td'); diff --git a/app/assets/javascripts/diffs/constants.js b/app/assets/javascripts/diffs/constants.js index f68afa44837..2795dddfc48 100644 --- a/app/assets/javascripts/diffs/constants.js +++ b/app/assets/javascripts/diffs/constants.js @@ -7,6 +7,7 @@ export const CONTEXT_LINE_TYPE = 'context'; export const EMPTY_CELL_TYPE = 'empty-cell'; export const COMMENT_FORM_TYPE = 'commentForm'; export const DIFF_NOTE_TYPE = 'DiffNote'; +export const LEGACY_DIFF_NOTE_TYPE = 'LegacyDiffNote'; export const NOTE_TYPE = 'Note'; export const NEW_LINE_TYPE = 'new'; export const OLD_LINE_TYPE = 'old'; diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js index 027df2ec841..e60bb9dd7e3 100644 --- a/app/assets/javascripts/diffs/store/actions.js +++ b/app/assets/javascripts/diffs/store/actions.js @@ -2,7 +2,7 @@ import Vue from 'vue'; import axios from '~/lib/utils/axios_utils'; import Cookies from 'js-cookie'; import { handleLocationHash, historyPushState } from '~/lib/utils/common_utils'; -import { mergeUrlParams } from '~/lib/utils/url_utility'; +import { mergeUrlParams, getLocationHash } from '~/lib/utils/url_utility'; import { getDiffPositionByLineCode } from './utils'; import * as types from './mutation_types'; import { @@ -120,6 +120,25 @@ export const loadMoreLines = ({ commit }, options) => { }); }; +export const scrollToLineIfNeededInline = (_, line) => { + const hash = getLocationHash(); + + if (hash && line.lineCode === hash) { + handleLocationHash(); + } +}; + +export const scrollToLineIfNeededParallel = (_, line) => { + const hash = getLocationHash(); + + if ( + hash && + ((line.left && line.left.lineCode === hash) || (line.right && line.right.lineCode === hash)) + ) { + handleLocationHash(); + } +}; + export const loadCollapsedDiff = ({ commit }, file) => axios.get(file.loadCollapsedDiffUrl).then(res => { commit(types.ADD_COLLAPSED_DIFFS, { diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js index 6dc5bf16c65..59a2c09e54f 100644 --- a/app/assets/javascripts/diffs/store/mutations.js +++ b/app/assets/javascripts/diffs/store/mutations.js @@ -90,16 +90,18 @@ export default { const firstDiscussion = discussions[0]; const isDiffDiscussion = firstDiscussion.diff_discussion; const hasLineCode = firstDiscussion.line_code; - const isResolvable = firstDiscussion.resolvable; const diffPosition = diffPositionByLineCode[firstDiscussion.line_code]; if ( selectedFile && isDiffDiscussion && hasLineCode && - isResolvable && diffPosition && - isDiscussionApplicableToLine(firstDiscussion, diffPosition) + isDiscussionApplicableToLine({ + discussion: firstDiscussion, + diffPosition, + latestDiff: state.latestDiff, + }) ) { const targetLine = selectedFile.parallelDiffLines.find( line => diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js index b7e52a8f37f..834a94ea42a 100644 --- a/app/assets/javascripts/diffs/store/utils.js +++ b/app/assets/javascripts/diffs/store/utils.js @@ -4,6 +4,7 @@ import { LINE_POSITION_LEFT, LINE_POSITION_RIGHT, TEXT_DIFF_POSITION_TYPE, + LEGACY_DIFF_NOTE_TYPE, DIFF_NOTE_TYPE, NEW_LINE_TYPE, OLD_LINE_TYPE, @@ -60,7 +61,10 @@ export function getNoteFormData(params) { noteable_type: noteableType, noteable_id: noteableData.id, commit_id: '', - type: DIFF_NOTE_TYPE, + type: + diffFile.diffRefs.startSha && diffFile.diffRefs.headSha + ? DIFF_NOTE_TYPE + : LEGACY_DIFF_NOTE_TYPE, line_code: noteTargetLine.lineCode, }, }; @@ -230,7 +234,16 @@ export function getDiffPositionByLineCode(diffFiles) { const { lineCode, oldLine, newLine } = line; if (lineCode) { - acc[lineCode] = { baseSha, headSha, startSha, newPath, oldPath, oldLine, newLine }; + acc[lineCode] = { + baseSha, + headSha, + startSha, + newPath, + oldPath, + oldLine, + newLine, + lineCode, + }; } }); } @@ -241,9 +254,15 @@ export function getDiffPositionByLineCode(diffFiles) { // This method will check whether the discussion is still applicable // to the diff line in question regarding different versions of the MR -export function isDiscussionApplicableToLine(discussion, diffPosition) { - const originalRefs = convertObjectPropsToCamelCase(discussion.original_position.formatter); - const refs = convertObjectPropsToCamelCase(discussion.position.formatter); +export function isDiscussionApplicableToLine({ discussion, diffPosition, latestDiff }) { + const { lineCode, ...diffPositionCopy } = diffPosition; - return _.isEqual(refs, diffPosition) || _.isEqual(originalRefs, diffPosition); + if (discussion.original_position && discussion.position) { + const originalRefs = convertObjectPropsToCamelCase(discussion.original_position.formatter); + const refs = convertObjectPropsToCamelCase(discussion.position.formatter); + + return _.isEqual(refs, diffPositionCopy) || _.isEqual(originalRefs, diffPositionCopy); + } + + return latestDiff && discussion.active && lineCode === discussion.line_code; } diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js deleted file mode 100644 index a5af37e80b6..00000000000 --- a/app/assets/javascripts/dispatcher.js +++ /dev/null @@ -1,89 +0,0 @@ -/* eslint-disable consistent-return, no-new */ - -import $ from 'jquery'; -import GfmAutoComplete from './gfm_auto_complete'; -import { convertPermissionToBoolean } from './lib/utils/common_utils'; -import GlFieldErrors from './gl_field_errors'; -import Shortcuts from './shortcuts'; -import SearchAutocomplete from './search_autocomplete'; -import performanceBar from './performance_bar'; - -function initSearch() { - // Only when search form is present - if ($('.search').length) { - return new SearchAutocomplete(); - } -} - -function initFieldErrors() { - $('.gl-show-field-errors').each((i, form) => { - new GlFieldErrors(form); - }); -} - -function initPageShortcuts(page) { - const pagesWithCustomShortcuts = [ - 'projects:activity', - 'projects:artifacts:browse', - 'projects:artifacts:file', - 'projects:blame:show', - 'projects:blob:show', - 'projects:commit:show', - 'projects:commits:show', - 'projects:find_file:show', - 'projects:issues:edit', - 'projects:issues:index', - 'projects:issues:new', - 'projects:issues:show', - 'projects:merge_requests:creations:diffs', - 'projects:merge_requests:creations:new', - 'projects:merge_requests:edit', - 'projects:merge_requests:index', - 'projects:merge_requests:show', - 'projects:network:show', - 'projects:show', - 'projects:tree:show', - 'groups:show', - ]; - - if (pagesWithCustomShortcuts.indexOf(page) === -1) { - new Shortcuts(); - } -} - -function initGFMInput() { - $('.js-gfm-input:not(.js-vue-textarea)').each((i, el) => { - const gfm = new GfmAutoComplete( - gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources, - ); - const enableGFM = convertPermissionToBoolean( - el.dataset.supportsAutocomplete, - ); - gfm.setup($(el), { - emojis: true, - members: enableGFM, - issues: enableGFM, - milestones: enableGFM, - mergeRequests: enableGFM, - labels: enableGFM, - }); - }); -} - -function initPerformanceBar() { - if (document.querySelector('#js-peek')) { - performanceBar({ container: '#js-peek' }); - } -} - -export default () => { - initSearch(); - initFieldErrors(); - - const page = $('body').attr('data-page'); - if (page) { - initPageShortcuts(page); - initGFMInput(); - initPerformanceBar(); - } -}; diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js index ff969bb94a4..d2778bcdf1c 100644 --- a/app/assets/javascripts/dropzone_input.js +++ b/app/assets/javascripts/dropzone_input.js @@ -1,7 +1,7 @@ import $ from 'jquery'; import Dropzone from 'dropzone'; import _ from 'underscore'; -import './preview_markdown'; +import './behaviors/preview_markdown'; import csrf from './lib/utils/csrf'; import axios from './lib/utils/axios_utils'; diff --git a/app/assets/javascripts/environments/components/empty_state.vue b/app/assets/javascripts/environments/components/empty_state.vue index 00e63c3467a..cf78f89981e 100644 --- a/app/assets/javascripts/environments/components/empty_state.vue +++ b/app/assets/javascripts/environments/components/empty_state.vue @@ -35,7 +35,7 @@ code gets deployed, such as staging or production.`) }} <a v-if="canCreateEnvironment" :href="newPath" - class="btn btn-create js-new-environment-button" + class="btn btn-success js-new-environment-button" > {{ s__("Environments|New environment") }} </a> diff --git a/app/assets/javascripts/environments/components/environments_app.vue b/app/assets/javascripts/environments/components/environments_app.vue index 8efdfb8abe0..e2ecf426e64 100644 --- a/app/assets/javascripts/environments/components/environments_app.vue +++ b/app/assets/javascripts/environments/components/environments_app.vue @@ -107,7 +107,7 @@ > <a :href="newEnvironmentPath" - class="btn btn-create" + class="btn btn-success" > {{ s__("Environments|New environment") }} </a> diff --git a/app/assets/javascripts/issue_show/components/edit_actions.vue b/app/assets/javascripts/issue_show/components/edit_actions.vue index 597c6d69a81..7fd3ea61aa7 100644 --- a/app/assets/javascripts/issue_show/components/edit_actions.vue +++ b/app/assets/javascripts/issue_show/components/edit_actions.vue @@ -53,7 +53,7 @@ <button :class="{ disabled: formState.updateLoading || !isSubmitEnabled }" :disabled="formState.updateLoading || !isSubmitEnabled" - class="btn btn-save float-left" + class="btn btn-success float-left" type="submit" @click.prevent="updateIssuable"> Save changes diff --git a/app/assets/javascripts/jobs/components/header.vue b/app/assets/javascripts/jobs/components/header.vue index 3e49b04e44e..63324e68d68 100644 --- a/app/assets/javascripts/jobs/components/header.vue +++ b/app/assets/javascripts/jobs/components/header.vue @@ -57,7 +57,7 @@ export default { actions.push({ label: 'New issue', path: this.job.new_issue_path, - cssClass: 'js-new-issue btn btn-new btn-inverted d-none d-md-block d-lg-block d-xl-block', + cssClass: 'js-new-issue btn btn-success btn-inverted d-none d-md-block d-lg-block d-xl-block', type: 'link', }); } diff --git a/app/assets/javascripts/jobs/components/sidebar_details_block.vue b/app/assets/javascripts/jobs/components/sidebar_details_block.vue index 1210ccd038a..80c2a5fb48b 100644 --- a/app/assets/javascripts/jobs/components/sidebar_details_block.vue +++ b/app/assets/javascripts/jobs/components/sidebar_details_block.vue @@ -130,7 +130,7 @@ export default { <a v-if="job.new_issue_path" :href="job.new_issue_path" - class="js-new-issue btn btn-new btn-inverted" + class="js-new-issue btn btn-success btn-inverted" > {{ __('New issue') }} </a> diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js index 0849d97bc1a..30925940807 100644 --- a/app/assets/javascripts/lib/utils/common_utils.js +++ b/app/assets/javascripts/lib/utils/common_utils.js @@ -56,7 +56,8 @@ export const rstrip = val => { return val; }; -export const updateTooltipTitle = ($tooltipEl, newTitle) => $tooltipEl.attr('title', newTitle).tooltip('_fixTitle'); +export const updateTooltipTitle = ($tooltipEl, newTitle) => + $tooltipEl.attr('title', newTitle).tooltip('_fixTitle'); export const disableButtonIfEmptyField = (fieldSelector, buttonSelector, eventName = 'input') => { const field = $(fieldSelector); @@ -86,6 +87,7 @@ export const handleLocationHash = () => { const fixedTabs = document.querySelector('.js-tabs-affix'); const fixedDiffStats = document.querySelector('.js-diff-files-changed'); const fixedNav = document.querySelector('.navbar-gitlab'); + const performanceBar = document.querySelector('#js-peek'); let adjustment = 0; if (fixedNav) adjustment -= fixedNav.offsetHeight; @@ -102,6 +104,10 @@ export const handleLocationHash = () => { adjustment -= fixedDiffStats.offsetHeight; } + if (performanceBar) { + adjustment -= performanceBar.offsetHeight; + } + window.scrollBy(0, adjustment); }; @@ -131,21 +137,20 @@ export const parseUrlPathname = url => { return parsedUrl.pathname.charAt(0) === '/' ? parsedUrl.pathname : `/${parsedUrl.pathname}`; }; -const splitPath = (path = '') => path - .replace(/^\?/, '') - .split('&'); +const splitPath = (path = '') => path.replace(/^\?/, '').split('&'); -export const urlParamsToArray = (path = '') => splitPath(path) - .filter(param => param.length > 0) - .map(param => { - const split = param.split('='); - return [decodeURI(split[0]), split[1]].join('='); - }); +export const urlParamsToArray = (path = '') => + splitPath(path) + .filter(param => param.length > 0) + .map(param => { + const split = param.split('='); + return [decodeURI(split[0]), split[1]].join('='); + }); export const getUrlParamsArray = () => urlParamsToArray(window.location.search); -export const urlParamsToObject = (path = '') => splitPath(path) - .reduce((dataParam, filterParam) => { +export const urlParamsToObject = (path = '') => + splitPath(path).reduce((dataParam, filterParam) => { if (filterParam === '') { return dataParam; } @@ -216,7 +221,7 @@ export const getParameterByName = (name, urlToParse) => { return decodeURIComponent(results[2].replace(/\+/g, ' ')); }; -const handleSelectedRange = (range) => { +const handleSelectedRange = range => { const container = range.commonAncestorContainer; // add context to fragment if needed if (container.tagName === 'OL') { @@ -453,7 +458,7 @@ export const backOff = (fn, timeout = 60000) => { export const createOverlayIcon = (iconPath, overlayPath) => { const faviconImage = document.createElement('img'); - return new Promise((resolve) => { + return new Promise(resolve => { faviconImage.onload = () => { const size = 32; @@ -464,13 +469,29 @@ export const createOverlayIcon = (iconPath, overlayPath) => { const context = canvas.getContext('2d'); context.clearRect(0, 0, size, size); context.drawImage( - faviconImage, 0, 0, faviconImage.width, faviconImage.height, 0, 0, size, size, + faviconImage, + 0, + 0, + faviconImage.width, + faviconImage.height, + 0, + 0, + size, + size, ); const overlayImage = document.createElement('img'); overlayImage.onload = () => { context.drawImage( - overlayImage, 0, 0, overlayImage.width, overlayImage.height, 0, 0, size, size, + overlayImage, + 0, + 0, + overlayImage.width, + overlayImage.height, + 0, + 0, + size, + size, ); const faviconWithOverlayUrl = canvas.toDataURL(); @@ -483,17 +504,21 @@ export const createOverlayIcon = (iconPath, overlayPath) => { }); }; -export const setFaviconOverlay = (overlayPath) => { +export const setFaviconOverlay = overlayPath => { const faviconEl = document.getElementById('favicon'); - if (!faviconEl) { return null; } + if (!faviconEl) { + return null; + } const iconPath = faviconEl.getAttribute('data-original-href'); - return createOverlayIcon(iconPath, overlayPath).then(faviconWithOverlayUrl => faviconEl.setAttribute('href', faviconWithOverlayUrl)); + return createOverlayIcon(iconPath, overlayPath).then(faviconWithOverlayUrl => + faviconEl.setAttribute('href', faviconWithOverlayUrl), + ); }; -export const setFavicon = (faviconPath) => { +export const setFavicon = faviconPath => { const faviconEl = document.getElementById('favicon'); if (faviconEl && faviconPath) { faviconEl.setAttribute('href', faviconPath); @@ -518,7 +543,7 @@ export const setCiStatusFavicon = pageUrl => } return resetFavicon(); }) - .catch((error) => { + .catch(error => { resetFavicon(); throw error; }); diff --git a/app/assets/javascripts/shortcuts_dashboard_navigation.js b/app/assets/javascripts/lib/utils/navigation_utility.js index 9f69f110d06..1579b225e44 100644 --- a/app/assets/javascripts/shortcuts_dashboard_navigation.js +++ b/app/assets/javascripts/lib/utils/navigation_utility.js @@ -1,4 +1,4 @@ -import { visitUrl } from './lib/utils/url_utility'; +import { visitUrl } from './url_utility'; /** * Helper function that finds the href of the fiven selector and updates the location. diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index c5a5f64abac..e8aac51a299 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -2,7 +2,6 @@ import jQuery from 'jquery'; import Cookies from 'js-cookie'; -import svg4everybody from 'svg4everybody'; // bootstrap webpack, common libs, polyfills, and behaviors import './webpack'; @@ -25,11 +24,12 @@ import initLayoutNav from './layout_nav'; import './feature_highlight/feature_highlight_options'; import LazyLoader from './lazy_loader'; import initLogoAnimation from './logo'; -import './milestone_select'; import './frequent_items'; import initBreadcrumbs from './breadcrumb'; -import initDispatcher from './dispatcher'; import initUsagePingConsent from './usage_ping_consent'; +import initPerformanceBar from './performance_bar'; +import initSearchAutocomplete from './search_autocomplete'; +import GlFieldErrors from './gl_field_errors'; // expose jQuery as global (TODO: remove these) window.jQuery = jQuery; @@ -41,8 +41,6 @@ if (process.env.NODE_ENV !== 'production' && gon && gon.test_env) { import(/* webpackMode: "eager" */ './test_utils/'); } -svg4everybody(); - document.addEventListener('beforeunload', () => { // Unbind scroll events $(document).off('scroll'); @@ -81,6 +79,9 @@ document.addEventListener('DOMContentLoaded', () => { initLogoAnimation(); initUsagePingConsent(); + if (document.querySelector('.search')) initSearchAutocomplete(); + if (document.querySelector('#js-peek')) initPerformanceBar({ container: '#js-peek' }); + // Set the default path for all cookies to GitLab's root directory Cookies.defaults.path = gon.relative_url_root || '/'; @@ -270,5 +271,6 @@ document.addEventListener('DOMContentLoaded', () => { }); } - initDispatcher(); + // initialize field errors + $('.gl-show-field-errors').each((i, form) => new GlFieldErrors(form)); }); diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue index 6612bc44e0b..7735133c470 100644 --- a/app/assets/javascripts/notes/components/comment_form.vue +++ b/app/assets/javascripts/notes/components/comment_form.vue @@ -374,7 +374,7 @@ js-gfm-input js-autosize markdown-area js-vue-textarea" append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"> <button :disabled="isSubmitButtonDisabled" - class="btn btn-create comment-btn js-comment-button js-comment-submit-button" + class="btn btn-success comment-btn js-comment-button js-comment-submit-button" type="submit" @click.prevent="handleSave()"> {{ __(commentButtonTitle) }} diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue index c41ed070383..29595a2ba73 100644 --- a/app/assets/javascripts/notes/components/note_form.vue +++ b/app/assets/javascripts/notes/components/note_form.vue @@ -188,7 +188,7 @@ js-autosize markdown-area js-vue-issue-note-form js-vue-textarea" <button :disabled="isDisabled" type="button" - class="js-vue-issue-save btn btn-save js-comment-button " + class="js-vue-issue-save btn btn-success js-comment-button " @click="handleUpdate()"> {{ saveButtonTitle }} </button> diff --git a/app/assets/javascripts/notes/stores/mutations.js b/app/assets/javascripts/notes/stores/mutations.js index 16bb54be126..f1242a0d8be 100644 --- a/app/assets/javascripts/notes/stores/mutations.js +++ b/app/assets/javascripts/notes/stores/mutations.js @@ -100,7 +100,10 @@ export default { discussionsData.forEach(discussion => { if (discussion.diff_file) { - Object.assign(discussion, { fileHash: discussion.diff_file.file_hash }); + Object.assign(discussion, { + fileHash: discussion.diff_file.file_hash, + truncated_diff_lines: discussion.truncated_diff_lines || [], + }); } // To support legacy notes, should be very rare case. diff --git a/app/assets/javascripts/notes/stores/utils.js b/app/assets/javascripts/notes/stores/utils.js index 8ccbdb4c130..0e41ff03d67 100644 --- a/app/assets/javascripts/notes/stores/utils.js +++ b/app/assets/javascripts/notes/stores/utils.js @@ -27,7 +27,7 @@ export const getQuickActionText = note => { export const reduceDiscussionsToLineCodes = selectedDiscussions => selectedDiscussions.reduce((acc, note) => { - if (note.diff_discussion && note.line_code && note.resolvable) { + if (note.diff_discussion && note.line_code) { // For context about line notes: there might be multiple notes with the same line code const items = acc[note.line_code] || []; items.push(note); diff --git a/app/assets/javascripts/pages/admin/application_settings/index.js b/app/assets/javascripts/pages/admin/application_settings/index.js index 069f8ce55d0..47bd70537f1 100644 --- a/app/assets/javascripts/pages/admin/application_settings/index.js +++ b/app/assets/javascripts/pages/admin/application_settings/index.js @@ -1,13 +1,8 @@ import initSettingsPanels from '~/settings_panels'; import projectSelect from '~/project_select'; -import UsagePingPayload from './usage_ping_payload'; document.addEventListener('DOMContentLoaded', () => { // Initialize expandable settings panels initSettingsPanels(); projectSelect(); - new UsagePingPayload( - document.querySelector('.js-usage-ping-payload-trigger'), - document.querySelector('.js-usage-ping-payload'), - ).init(); }); diff --git a/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/index.js b/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/index.js new file mode 100644 index 00000000000..c40503603be --- /dev/null +++ b/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/index.js @@ -0,0 +1,8 @@ +import UsagePingPayload from './../usage_ping_payload'; + +document.addEventListener('DOMContentLoaded', () => { + new UsagePingPayload( + document.querySelector('.js-usage-ping-payload-trigger'), + document.querySelector('.js-usage-ping-payload'), + ).init(); +}); diff --git a/app/assets/javascripts/pages/groups/boards/index.js b/app/assets/javascripts/pages/groups/boards/index.js index 5cfe8723204..79c3be771d0 100644 --- a/app/assets/javascripts/pages/groups/boards/index.js +++ b/app/assets/javascripts/pages/groups/boards/index.js @@ -1,5 +1,5 @@ import UsersSelect from '~/users_select'; -import ShortcutsNavigation from '~/shortcuts_navigation'; +import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import initBoards from '~/boards'; document.addEventListener('DOMContentLoaded', () => { diff --git a/app/assets/javascripts/pages/groups/show/index.js b/app/assets/javascripts/pages/groups/show/index.js index 5b8c2ae7e81..3a45fd70d02 100644 --- a/app/assets/javascripts/pages/groups/show/index.js +++ b/app/assets/javascripts/pages/groups/show/index.js @@ -6,7 +6,7 @@ import NewGroupChild from '~/groups/new_group_child'; import notificationsDropdown from '~/notifications_dropdown'; import NotificationsForm from '~/notifications_form'; import ProjectsList from '~/projects_list'; -import ShortcutsNavigation from '~/shortcuts_navigation'; +import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import GroupTabs from './group_tabs'; document.addEventListener('DOMContentLoaded', () => { diff --git a/app/assets/javascripts/pages/projects/activity/index.js b/app/assets/javascripts/pages/projects/activity/index.js index 5543ad82428..d39ea3d10bf 100644 --- a/app/assets/javascripts/pages/projects/activity/index.js +++ b/app/assets/javascripts/pages/projects/activity/index.js @@ -1,5 +1,5 @@ import Activities from '~/activities'; -import ShortcutsNavigation from '~/shortcuts_navigation'; +import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; document.addEventListener('DOMContentLoaded', () => { new Activities(); // eslint-disable-line no-new diff --git a/app/assets/javascripts/pages/projects/artifacts/browse/index.js b/app/assets/javascripts/pages/projects/artifacts/browse/index.js index ea7458fe9b8..26dc90a56d7 100644 --- a/app/assets/javascripts/pages/projects/artifacts/browse/index.js +++ b/app/assets/javascripts/pages/projects/artifacts/browse/index.js @@ -1,5 +1,5 @@ import BuildArtifacts from '~/build_artifacts'; -import ShortcutsNavigation from '~/shortcuts_navigation'; +import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; document.addEventListener('DOMContentLoaded', () => { new ShortcutsNavigation(); // eslint-disable-line no-new diff --git a/app/assets/javascripts/pages/projects/artifacts/file/index.js b/app/assets/javascripts/pages/projects/artifacts/file/index.js index 8484e5e9848..249900d6cb7 100644 --- a/app/assets/javascripts/pages/projects/artifacts/file/index.js +++ b/app/assets/javascripts/pages/projects/artifacts/file/index.js @@ -1,5 +1,5 @@ import BlobViewer from '~/blob/viewer/index'; -import ShortcutsNavigation from '~/shortcuts_navigation'; +import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; document.addEventListener('DOMContentLoaded', () => { new ShortcutsNavigation(); // eslint-disable-line no-new diff --git a/app/assets/javascripts/pages/projects/boards/index.js b/app/assets/javascripts/pages/projects/boards/index.js index 5cfe8723204..79c3be771d0 100644 --- a/app/assets/javascripts/pages/projects/boards/index.js +++ b/app/assets/javascripts/pages/projects/boards/index.js @@ -1,5 +1,5 @@ import UsersSelect from '~/users_select'; -import ShortcutsNavigation from '~/shortcuts_navigation'; +import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import initBoards from '~/boards'; document.addEventListener('DOMContentLoaded', () => { diff --git a/app/assets/javascripts/pages/projects/commit/show/index.js b/app/assets/javascripts/pages/projects/commit/show/index.js index 2e23cce11ce..f477424811d 100644 --- a/app/assets/javascripts/pages/projects/commit/show/index.js +++ b/app/assets/javascripts/pages/projects/commit/show/index.js @@ -3,7 +3,7 @@ import $ from 'jquery'; import Diff from '~/diff'; import ZenMode from '~/zen_mode'; -import ShortcutsNavigation from '~/shortcuts_navigation'; +import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown'; import initNotes from '~/init_notes'; import initChangesDropdown from '~/init_changes_dropdown'; diff --git a/app/assets/javascripts/pages/projects/commits/show/index.js b/app/assets/javascripts/pages/projects/commits/show/index.js index 3682020579b..ad671ce9351 100644 --- a/app/assets/javascripts/pages/projects/commits/show/index.js +++ b/app/assets/javascripts/pages/projects/commits/show/index.js @@ -1,6 +1,6 @@ import CommitsList from '~/commits'; import GpgBadges from '~/gpg_badges'; -import ShortcutsNavigation from '~/shortcuts_navigation'; +import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; document.addEventListener('DOMContentLoaded', () => { new CommitsList(document.querySelector('.js-project-commits-show').dataset.commitsLimit); // eslint-disable-line no-new diff --git a/app/assets/javascripts/pages/projects/find_file/show/index.js b/app/assets/javascripts/pages/projects/find_file/show/index.js index 24630c2aa05..388d7d7bdda 100644 --- a/app/assets/javascripts/pages/projects/find_file/show/index.js +++ b/app/assets/javascripts/pages/projects/find_file/show/index.js @@ -1,6 +1,6 @@ import $ from 'jquery'; import ProjectFindFile from '~/project_find_file'; -import ShortcutsFindFile from '~/shortcuts_find_file'; +import ShortcutsFindFile from '~/behaviors/shortcuts/shortcuts_find_file'; document.addEventListener('DOMContentLoaded', () => { const findElement = document.querySelector('.js-file-finder'); diff --git a/app/assets/javascripts/pages/projects/index.js b/app/assets/javascripts/pages/projects/index.js index 9c074b74c3b..5659e13981a 100644 --- a/app/assets/javascripts/pages/projects/index.js +++ b/app/assets/javascripts/pages/projects/index.js @@ -1,7 +1,7 @@ import initDismissableCallout from '~/dismissable_callout'; import initGkeDropdowns from '~/projects/gke_cluster_dropdowns'; import Project from './project'; -import ShortcutsNavigation from '../../shortcuts_navigation'; +import ShortcutsNavigation from '../../behaviors/shortcuts/shortcuts_navigation'; document.addEventListener('DOMContentLoaded', () => { const { page } = document.body.dataset; diff --git a/app/assets/javascripts/pages/projects/init_blob.js b/app/assets/javascripts/pages/projects/init_blob.js index 56ab3fcdfcb..bc08ccf3584 100644 --- a/app/assets/javascripts/pages/projects/init_blob.js +++ b/app/assets/javascripts/pages/projects/init_blob.js @@ -1,7 +1,7 @@ import LineHighlighter from '~/line_highlighter'; import BlobLinePermalinkUpdater from '~/blob/blob_line_permalink_updater'; -import ShortcutsNavigation from '~/shortcuts_navigation'; -import ShortcutsBlob from '~/shortcuts_blob'; +import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; +import ShortcutsBlob from '~/behaviors/shortcuts/shortcuts_blob'; import BlobForkSuggestion from '~/blob/blob_fork_suggestion'; import initBlobBundle from '~/blob_edit/blob_bundle'; diff --git a/app/assets/javascripts/pages/projects/issues/form.js b/app/assets/javascripts/pages/projects/issues/form.js index b2b8e5d2300..197bfa8a394 100644 --- a/app/assets/javascripts/pages/projects/issues/form.js +++ b/app/assets/javascripts/pages/projects/issues/form.js @@ -5,7 +5,7 @@ import GLForm from '~/gl_form'; import IssuableForm from '~/issuable_form'; import LabelsSelect from '~/labels_select'; import MilestoneSelect from '~/milestone_select'; -import ShortcutsNavigation from '~/shortcuts_navigation'; +import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import IssuableTemplateSelectors from '~/templates/issuable_template_selectors'; export default () => { diff --git a/app/assets/javascripts/pages/projects/issues/index/index.js b/app/assets/javascripts/pages/projects/issues/index/index.js index 23edbdc5cad..a56c0bb6be8 100644 --- a/app/assets/javascripts/pages/projects/issues/index/index.js +++ b/app/assets/javascripts/pages/projects/issues/index/index.js @@ -1,7 +1,7 @@ /* eslint-disable no-new */ import IssuableIndex from '~/issuable_index'; -import ShortcutsNavigation from '~/shortcuts_navigation'; +import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import UsersSelect from '~/users_select'; import initFilteredSearch from '~/pages/search/init_filtered_search'; import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys'; diff --git a/app/assets/javascripts/pages/projects/issues/show.js b/app/assets/javascripts/pages/projects/issues/show.js index 500fbd27340..74b3a515e84 100644 --- a/app/assets/javascripts/pages/projects/issues/show.js +++ b/app/assets/javascripts/pages/projects/issues/show.js @@ -1,6 +1,6 @@ import initIssuableSidebar from '~/init_issuable_sidebar'; import Issue from '~/issue'; -import ShortcutsIssuable from '~/shortcuts_issuable'; +import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable'; import ZenMode from '~/zen_mode'; import '~/notes/index'; import '~/issue_show/index'; diff --git a/app/assets/javascripts/pages/projects/merge_requests/index/index.js b/app/assets/javascripts/pages/projects/merge_requests/index/index.js index 1fad0fb7297..3647048a872 100644 --- a/app/assets/javascripts/pages/projects/merge_requests/index/index.js +++ b/app/assets/javascripts/pages/projects/merge_requests/index/index.js @@ -1,5 +1,5 @@ import IssuableIndex from '~/issuable_index'; -import ShortcutsNavigation from '~/shortcuts_navigation'; +import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import UsersSelect from '~/users_select'; import initFilteredSearch from '~/pages/search/init_filtered_search'; import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys'; diff --git a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js index 3a3c21f2202..e3971618da5 100644 --- a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js +++ b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js @@ -2,7 +2,7 @@ import $ from 'jquery'; import Diff from '~/diff'; -import ShortcutsNavigation from '~/shortcuts_navigation'; +import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import GLForm from '~/gl_form'; import IssuableForm from '~/issuable_form'; import LabelsSelect from '~/labels_select'; diff --git a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js index 26ead75cec4..7bfb83a2204 100644 --- a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js +++ b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js @@ -1,6 +1,6 @@ import ZenMode from '~/zen_mode'; import initIssuableSidebar from '~/init_issuable_sidebar'; -import ShortcutsIssuable from '~/shortcuts_issuable'; +import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable'; import { handleLocationHash } from '~/lib/utils/common_utils'; import howToMerge from '~/how_to_merge'; import initPipelines from '~/commit/pipelines/pipelines_bundle'; diff --git a/app/assets/javascripts/pages/projects/network/show/index.js b/app/assets/javascripts/pages/projects/network/show/index.js index a0b14fed10f..9f05f63b742 100644 --- a/app/assets/javascripts/pages/projects/network/show/index.js +++ b/app/assets/javascripts/pages/projects/network/show/index.js @@ -1,5 +1,5 @@ import $ from 'jquery'; -import ShortcutsNetwork from '../../../../shortcuts_network'; +import ShortcutsNetwork from '~/behaviors/shortcuts/shortcuts_network'; import Network from '../network'; document.addEventListener('DOMContentLoaded', () => { diff --git a/app/assets/javascripts/pages/projects/show/index.js b/app/assets/javascripts/pages/projects/show/index.js index 0507f67843f..7302c1ab202 100644 --- a/app/assets/javascripts/pages/projects/show/index.js +++ b/app/assets/javascripts/pages/projects/show/index.js @@ -1,6 +1,6 @@ import $ from 'jquery'; import initBlob from '~/blob_edit/blob_bundle'; -import ShortcutsNavigation from '~/shortcuts_navigation'; +import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import NotificationsForm from '~/notifications_form'; import UserCallout from '~/user_callout'; import TreeView from '~/tree'; diff --git a/app/assets/javascripts/pages/projects/tree/show/index.js b/app/assets/javascripts/pages/projects/tree/show/index.js index 33d69d891d8..400aed35e32 100644 --- a/app/assets/javascripts/pages/projects/tree/show/index.js +++ b/app/assets/javascripts/pages/projects/tree/show/index.js @@ -4,7 +4,7 @@ import initBlob from '~/blob_edit/blob_bundle'; import commitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue'; import GpgBadges from '~/gpg_badges'; import TreeView from '../../../../tree'; -import ShortcutsNavigation from '../../../../shortcuts_navigation'; +import ShortcutsNavigation from '../../../../behaviors/shortcuts/shortcuts_navigation'; import BlobViewer from '../../../../blob/viewer'; import NewCommitForm from '../../../../new_commit_form'; import { ajaxGet } from '../../../../lib/utils/common_utils'; diff --git a/app/assets/javascripts/pages/projects/wikis/index.js b/app/assets/javascripts/pages/projects/wikis/index.js index b0a323a71cd..c2629090f01 100644 --- a/app/assets/javascripts/pages/projects/wikis/index.js +++ b/app/assets/javascripts/pages/projects/wikis/index.js @@ -2,8 +2,8 @@ import $ from 'jquery'; import Vue from 'vue'; import Translate from '~/vue_shared/translate'; import csrf from '~/lib/utils/csrf'; +import ShortcutsWiki from '~/behaviors/shortcuts/shortcuts_wiki'; import Wikis from './wikis'; -import ShortcutsWiki from '../../../shortcuts_wiki'; import ZenMode from '../../../zen_mode'; import GLForm from '../../../gl_form'; import deleteWikiModal from './components/delete_wiki_modal.vue'; diff --git a/app/assets/javascripts/pipelines/components/nav_controls.vue b/app/assets/javascripts/pipelines/components/nav_controls.vue index 9501afb7493..efb80d3a3c0 100644 --- a/app/assets/javascripts/pipelines/components/nav_controls.vue +++ b/app/assets/javascripts/pipelines/components/nav_controls.vue @@ -43,7 +43,7 @@ export default { <a v-if="newPipelinePath" :href="newPipelinePath" - class="btn btn-create js-run-pipeline" + class="btn btn-success js-run-pipeline" > {{ s__('Pipelines|Run Pipeline') }} </a> diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js index aec09b8bc0a..50dd3c12382 100644 --- a/app/assets/javascripts/search_autocomplete.js +++ b/app/assets/javascripts/search_autocomplete.js @@ -68,7 +68,7 @@ function setSearchOptions() { } } -export default class SearchAutocomplete { +export class SearchAutocomplete { constructor({ wrap, optsEl, autocompletePath, projectId, projectRef } = {}) { setSearchOptions(); this.bindEventContext(); @@ -499,3 +499,7 @@ export default class SearchAutocomplete { this.dropdownMenu.toggleClass('fade-out', !this.isScrolledUp()); } } + +export default function initSearchAutocomplete(opts) { + return new SearchAutocomplete(opts); +} diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue index 086dbabe77e..e73b7e410d5 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue @@ -37,7 +37,7 @@ export default { <a v-if="mr.newBlobPath" :href="mr.newBlobPath" - class="btn btn-inverted btn-save"> + class="btn btn-inverted btn-success"> Create file </a> </div> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue index a5ca7b719a1..23c3284cd21 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue @@ -255,7 +255,7 @@ export default { data-toggle="dropdown" aria-label="Select merge moment"> <i - class="fa fa-chevron-down" + class="fa fa-chevron-down qa-merge-moment-dropdown" aria-hidden="true" ></i> </button> @@ -265,7 +265,7 @@ export default { role="menu"> <li> <a - class="merge_when_pipeline_succeeds" + class="merge_when_pipeline_succeeds qa-merge-when-pipeline-succeeds-option" href="#" @click.prevent="handleMergeButtonClick(true)"> <span class="media"> @@ -279,7 +279,7 @@ export default { </li> <li> <a - class="accept-merge-request" + class="accept-merge-request qa-merge-immediately-option" href="#" @click.prevent="handleMergeButtonClick(false, true)"> <span class="media"> diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index ab62ca07573..686ce0c63a4 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -147,18 +147,12 @@ } &.btn-success, - &.btn-new, - &.btn-create, - &.btn-save, &.btn-register { @include btn-green; } &.btn-inverted { - &.btn-success, - &.btn-new, - &.btn-create, - &.btn-save { + &.btn-success { @include btn-outline($white-light, $green-600, $green-500, $green-500, $white-light, $green-600, $green-600, $green-700); } diff --git a/app/assets/stylesheets/framework/responsive_tables.scss b/app/assets/stylesheets/framework/responsive_tables.scss index 764bebd82c6..fc185ccfaad 100644 --- a/app/assets/stylesheets/framework/responsive_tables.scss +++ b/app/assets/stylesheets/framework/responsive_tables.scss @@ -39,7 +39,7 @@ .table-section { white-space: nowrap; - $section-widths: 10 15 20 25 30 40 50 100; + $section-widths: 5 10 15 20 25 30 40 50 100; @each $width in $section-widths { &.section-#{$width} { flex: 0 0 #{$width + '%'}; diff --git a/app/assets/stylesheets/framework/snippets.scss b/app/assets/stylesheets/framework/snippets.scss index 7152ef9bcfd..36ab38f1c9d 100644 --- a/app/assets/stylesheets/framework/snippets.scss +++ b/app/assets/stylesheets/framework/snippets.scss @@ -45,7 +45,7 @@ } } -.snippet-scope-menu .btn-new { +.snippet-scope-menu .btn-success { margin-top: 15px; } diff --git a/app/assets/stylesheets/pages/xterm.scss b/app/assets/stylesheets/page_bundles/xterm.scss index 7d40c61da26..7f040ac9b96 100644 --- a/app/assets/stylesheets/pages/xterm.scss +++ b/app/assets/stylesheets/page_bundles/xterm.scss @@ -1,3 +1,5 @@ +@import 'framework/variables'; + .build-page { // color codes are based on http://en.wikipedia.org/wiki/File:Xterm_256color_chart.svg // see also: https://gist.github.com/jasonm23/2868981 diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss index 394c99268be..fe792a53b44 100644 --- a/app/assets/stylesheets/pages/groups.scss +++ b/app/assets/stylesheets/pages/groups.scss @@ -106,7 +106,7 @@ &, .dropdown, .dropdown .dropdown-toggle, - .btn-new { + .btn-success { display: block; } @@ -118,7 +118,7 @@ .group-filter-form, .dropdown .dropdown-toggle, - .btn-new { + .btn-success { width: 100%; } diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss index 5fdb2b4a90a..99609a96976 100644 --- a/app/assets/stylesheets/pages/members.scss +++ b/app/assets/stylesheets/pages/members.scss @@ -4,7 +4,7 @@ } .users-project-form { - .btn-create { + .btn-success { margin-right: 10px; } } diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss index ac7b701c2e2..4268e194ed7 100644 --- a/app/assets/stylesheets/pages/note_form.scss +++ b/app/assets/stylesheets/pages/note_form.scss @@ -2,7 +2,7 @@ * Note Form */ .comment-btn { - @extend .btn-create; + @extend .btn-success; } .diff-file .diff-content { diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index 77119aea9e2..04151b1cd59 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -218,7 +218,7 @@ input[type='checkbox']:hover { } .btn-search, - .btn-new { + .btn-success { width: 100%; margin-top: 5px; diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index faee2880c67..875e46969fe 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -1,11 +1,39 @@ # frozen_string_literal: true class Admin::ApplicationSettingsController < Admin::ApplicationController + include InternalRedirect before_action :set_application_setting def show end + def integrations + end + + def repository + end + + def templates + end + + def ci_cd + end + + def reporting + end + + def metrics_and_profiling + end + + def network + end + + def geo + end + + def preferences + end + def update successful = ApplicationSettings::UpdateService .new(@application_setting, current_user, application_setting_params) @@ -15,10 +43,12 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController session[:ask_for_usage_stats_consent] = current_user.requires_usage_stats_consent? end + redirect_path = referer_path(request) || admin_application_settings_path + respond_to do |format| if successful format.json { head :ok } - format.html { redirect_to admin_application_settings_path, notice: 'Application settings saved successfully' } + format.html { redirect_to redirect_path, notice: 'Application settings saved successfully' } else format.json { head :bad_request } format.html { render :show } diff --git a/app/controllers/concerns/internal_redirect.rb b/app/controllers/concerns/internal_redirect.rb index 4d3b5681757..6785e6972d0 100644 --- a/app/controllers/concerns/internal_redirect.rb +++ b/app/controllers/concerns/internal_redirect.rb @@ -38,4 +38,10 @@ module InternalRedirect path_with_query = [uri.path, uri.query].compact.join('?') [path_with_query, uri.fragment].compact.join("#") end + + def referer_path(request) + return unless request.referer.presence + + URI(request.referer).path + end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index ef4560023af..32fc8e5e9ce 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -7,7 +7,15 @@ module ApplicationHelper # See https://docs.gitlab.com/ee/development/ee_features.html#code-in-app-views # rubocop: disable CodeReuse/ActiveRecord def render_if_exists(partial, locals = {}) - render(partial, locals) if lookup_context.exists?(partial, [], true) + render(partial, locals) if partial_exists?(partial) + end + + def partial_exists?(partial) + lookup_context.exists?(partial, [], true) + end + + def template_exists?(template) + lookup_context.exists?(template, [], false) end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 3ebf0162cb6..dc393968786 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -264,4 +264,8 @@ module ApplicationSettingsHelper :web_ide_clientside_preview_enabled ] end + + def expanded_by_default? + Rails.env.test? + end end diff --git a/app/helpers/services_helper.rb b/app/helpers/services_helper.rb index 8b554e1aaa9..d4b50b7ecfb 100644 --- a/app/helpers/services_helper.rb +++ b/app/helpers/services_helper.rb @@ -32,7 +32,7 @@ module ServicesHelper end def service_save_button(service) - button_tag(class: 'btn btn-save', type: 'submit', disabled: service.deprecated?) do + button_tag(class: 'btn btn-success', type: 'submit', disabled: service.deprecated?) do icon('spinner spin', class: 'hidden js-btn-spinner') + content_tag(:span, 'Save changes', class: 'js-btn-label') end diff --git a/app/models/container_repository.rb b/app/models/container_repository.rb index 93ca3a5daf4..2c08a8e1acf 100644 --- a/app/models/container_repository.rb +++ b/app/models/container_repository.rb @@ -8,8 +8,6 @@ class ContainerRepository < ActiveRecord::Base delegate :client, to: :registry - before_destroy :delete_tags! - # rubocop: disable CodeReuse/ServiceClass def registry @registry ||= begin diff --git a/app/models/deploy_key.rb b/app/models/deploy_key.rb index fd5d7726fb6..db501b4b506 100644 --- a/app/models/deploy_key.rb +++ b/app/models/deploy_key.rb @@ -18,7 +18,7 @@ class DeployKey < Key end def orphaned? - self.deploy_keys_projects.length == 0 + self.deploy_keys_projects.empty? end def almost_orphaned? diff --git a/app/models/diff_note.rb b/app/models/diff_note.rb index 716cf6574d3..047d353b4b5 100644 --- a/app/models/diff_note.rb +++ b/app/models/diff_note.rb @@ -131,7 +131,7 @@ class DiffNote < Note # As an extra benefit, the returned `diff_file` already # has `highlighted_diff_lines` data set from Redis on # `Diff::FileCollection::MergeRequestDiff`. - noteable.diffs(paths: original_position.paths, expanded: true).diff_files.first + noteable.diffs(original_position.diff_options).diff_files.first else original_position.diff_file(self.project.repository) end diff --git a/app/models/network/commit.rb b/app/models/network/commit.rb index 6c5a4c56377..1b2369aab18 100644 --- a/app/models/network/commit.rb +++ b/app/models/network/commit.rb @@ -18,7 +18,7 @@ module Network end def space - if @spaces.size > 0 + if @spaces.present? @spaces.first else 0 diff --git a/app/models/network/graph.rb b/app/models/network/graph.rb index 1431dfefc55..6da3bb7bfb7 100644 --- a/app/models/network/graph.rb +++ b/app/models/network/graph.rb @@ -81,7 +81,7 @@ module Network skip = 0 while offset == -1 tmp_commits = find_commits(skip) - if tmp_commits.size > 0 + if tmp_commits.present? index = tmp_commits.index do |c| c.id == @commit.id end @@ -218,7 +218,7 @@ module Network def get_space_base(leaves) space_base = 1 parents = leaves.last.parents(@map) - if parents.size > 0 + if parents.present? if parents.first.space > 0 space_base = parents.first.space end diff --git a/app/models/project_services/asana_service.rb b/app/models/project_services/asana_service.rb index 568f870c2db..cc5f1207653 100644 --- a/app/models/project_services/asana_service.rb +++ b/app/models/project_services/asana_service.rb @@ -65,7 +65,7 @@ http://app.asana.com/-/account_api' # check the branch restriction is poplulated and branch is not included branch = Gitlab::Git.ref_name(data[:ref]) branch_restriction = restrict_to_branch.to_s - if branch_restriction.length > 0 && branch_restriction.index(branch).nil? + if branch_restriction.present? && branch_restriction.index(branch).nil? return end diff --git a/app/services/boards/create_service.rb b/app/services/boards/create_service.rb index 4caf5ffa3cb..1b796cef3e2 100644 --- a/app/services/boards/create_service.rb +++ b/app/services/boards/create_service.rb @@ -9,7 +9,7 @@ module Boards private def can_create_board? - parent.boards.size == 0 + parent.boards.empty? end def create_board! diff --git a/app/services/merge_requests/reload_diffs_service.rb b/app/services/merge_requests/reload_diffs_service.rb index c350b14d12b..b4d48fe92ad 100644 --- a/app/services/merge_requests/reload_diffs_service.rb +++ b/app/services/merge_requests/reload_diffs_service.rb @@ -31,7 +31,7 @@ module MergeRequests def clear_cache(new_diff) # Executing the iteration we cache highlighted diffs for each diff file of # MergeRequestDiff. - new_diff.diffs_collection.write_cache + cacheable_collection(new_diff).write_cache # Remove cache for all diffs on this MR. Do not use the association on the # model, as that will interfere with other actions happening when @@ -39,9 +39,15 @@ module MergeRequests MergeRequestDiff.where(merge_request: merge_request).each do |merge_request_diff| next if merge_request_diff == new_diff - merge_request_diff.diffs_collection.clear_cache + cacheable_collection(merge_request_diff).clear_cache end end # rubocop: enable CodeReuse/ActiveRecord + + def cacheable_collection(diff) + # There are scenarios where we don't need to request Diff Stats. + # Mainly when clearing / writing diff caches. + diff.diffs(include_stats: false) + end end end diff --git a/app/services/projects/container_repository/destroy_service.rb b/app/services/projects/container_repository/destroy_service.rb index a8e7eab6068..1f5af7970d6 100644 --- a/app/services/projects/container_repository/destroy_service.rb +++ b/app/services/projects/container_repository/destroy_service.rb @@ -6,6 +6,8 @@ module Projects def execute(container_repository) return false unless can?(current_user, :update_container_image, project) + # Delete tags outside of the transaction to avoid hitting an idle-in-transaction timeout + container_repository.delete_tags! container_repository.destroy end end diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb index 5090ebf8f51..210571b6b4e 100644 --- a/app/services/projects/destroy_service.rb +++ b/app/services/projects/destroy_service.rb @@ -133,11 +133,11 @@ module Projects end def attempt_destroy_transaction(project) - Project.transaction do - unless remove_legacy_registry_tags - raise_error('Failed to remove some tags in project container registry. Please try again or contact administrator.') - end + unless remove_registry_tags + raise_error('Failed to remove some tags in project container registry. Please try again or contact administrator.') + end + Project.transaction do log_destroy_event trash_repositories! @@ -156,6 +156,17 @@ module Projects log_info("Attempting to destroy #{project.full_path} (#{project.id})") end + def remove_registry_tags + return false unless remove_legacy_registry_tags + + project.container_repositories.find_each do |container_repository| + service = Projects::ContainerRepository::DestroyService.new(project, current_user) + service.execute(container_repository) + end + + true + end + ## # This method makes sure that we correctly remove registry tags # for legacy image repository (when repository path equals project path). diff --git a/app/views/abuse_reports/new.html.haml b/app/views/abuse_reports/new.html.haml index 278ad210543..391115a67b5 100644 --- a/app/views/abuse_reports/new.html.haml +++ b/app/views/abuse_reports/new.html.haml @@ -19,4 +19,4 @@ Explain the problem with this user. If appropriate, provide a link to the relevant issue or comment. .form-actions - = f.submit "Send report", class: "btn btn-create" + = f.submit "Send report", class: "btn btn-success" diff --git a/app/views/admin/appearances/_form.html.haml b/app/views/admin/appearances/_form.html.haml index a0861870ba4..d71dac2574c 100644 --- a/app/views/admin/appearances/_form.html.haml +++ b/app/views/admin/appearances/_form.html.haml @@ -75,7 +75,7 @@ Guidelines parsed with #{link_to "GitLab Flavored Markdown", help_page_path('user/markdown'), target: '_blank'}. .form-actions - = f.submit 'Save', class: 'btn btn-save append-right-10' + = f.submit 'Save', class: 'btn btn-success append-right-10' - if @appearance.persisted? Preview last save: = link_to 'Sign-in page', preview_sign_in_admin_appearances_path, class: 'btn', target: '_blank', rel: 'noopener noreferrer' diff --git a/app/views/admin/appearances/preview_sign_in.html.haml b/app/views/admin/appearances/preview_sign_in.html.haml index 1af7dd5bb67..2cd95071c73 100644 --- a/app/views/admin/appearances/preview_sign_in.html.haml +++ b/app/views/admin/appearances/preview_sign_in.html.haml @@ -8,5 +8,5 @@ = label_tag :password = password_field_tag :password, nil, class: "form-control bottom", title: 'This field is required.' .form-group - = button_tag "Sign in", class: "btn-create btn" + = button_tag "Sign in", class: "btn-success btn" diff --git a/app/views/admin/application_settings/ci_cd.html.haml b/app/views/admin/application_settings/ci_cd.html.haml new file mode 100644 index 00000000000..db24c9982f7 --- /dev/null +++ b/app/views/admin/application_settings/ci_cd.html.haml @@ -0,0 +1,26 @@ +- breadcrumb_title _("CI/CD") +- page_title _("CI/CD") +- @content_class = "limit-container-width" unless fluid_layout + +%section.settings.as-ci-cd.no-animate#js-ci-cd-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Continuous Integration and Deployment') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Auto DevOps, runners and job artifacts') + .settings-content + = render 'ci_cd' + +- if Gitlab.config.registry.enabled + %section.settings.as-registry.no-animate#js-registry-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Container Registry') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Various container registry settings.') + .settings-content + = render 'registry' diff --git a/app/views/admin/application_settings/integrations.html.haml b/app/views/admin/application_settings/integrations.html.haml new file mode 100644 index 00000000000..310e86b1377 --- /dev/null +++ b/app/views/admin/application_settings/integrations.html.haml @@ -0,0 +1,31 @@ +- breadcrumb_title _("Integrations") +- page_title _("Integrations") +- @content_class = "limit-container-width" unless fluid_layout + += render_if_exists 'admin/application_settings/elasticsearch_form', expanded: expanded_by_default? + +%section.settings.as-plantuml.no-animate#js-plantuml-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('PlantUML') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Allow rendering of PlantUML diagrams in Asciidoc documents.') + .settings-content + = render 'plantuml' + += render_if_exists 'admin/application_settings/slack', expanded: expanded_by_default? + +%section.settings.as-third-party-offers.no-animate#js-third-party-offers-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Third party offers') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Control the display of third party offers.') + .settings-content + = render 'third_party_offers', application_setting: @application_setting + += render_if_exists 'admin/application_settings/snowplow', expanded: expanded_by_default? diff --git a/app/views/admin/application_settings/metrics_and_profiling.html.haml b/app/views/admin/application_settings/metrics_and_profiling.html.haml new file mode 100644 index 00000000000..f50aca32bdf --- /dev/null +++ b/app/views/admin/application_settings/metrics_and_profiling.html.haml @@ -0,0 +1,50 @@ +- breadcrumb_title _("Metrics and profiling") +- page_title _("Metrics and profiling") +- @content_class = "limit-container-width" unless fluid_layout + +%section.settings.as-influx.no-animate#js-influx-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Metrics - Influx') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Enable and configure InfluxDB metrics.') + .settings-content + = render 'influx' + +%section.settings.as-prometheus.no-animate#js-prometheus-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Metrics - Prometheus') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Enable and configure Prometheus metrics.') + .settings-content + = render 'prometheus' + +%section.settings.as-performance-bar.no-animate#js-performance-bar-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Profiling - Performance bar') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Enable the Performance Bar for a given group.') + = link_to icon('question-circle'), help_page_path('administration/monitoring/performance/performance_bar') + .settings-content + = render 'performance_bar' + +%section.settings.as-usage.no-animate#js-usage-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header#usage-statistics + %h4 + = _('Usage statistics') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Enable or disable version check and usage ping.') + .settings-content + = render 'usage' + += render_if_exists 'admin/application_settings/pseudonymizer_settings', expanded: expanded_by_default? diff --git a/app/views/admin/application_settings/network.html.haml b/app/views/admin/application_settings/network.html.haml new file mode 100644 index 00000000000..26fd745f45f --- /dev/null +++ b/app/views/admin/application_settings/network.html.haml @@ -0,0 +1,36 @@ +- breadcrumb_title _("Network") +- page_title _("Network") +- @content_class = "limit-container-width" unless fluid_layout + +%section.settings.as-performance.no-animate#js-performance-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Performance optimization') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Various settings that affect GitLab performance.') + .settings-content + = render 'performance' + +%section.settings.as-ip-limits.no-animate#js-ip-limits-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('User and IP Rate Limits') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Configure limits for web and API requests.') + .settings-content + = render 'ip_limits' + +%section.settings.as-outbound.no-animate#js-outbound-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Outbound requests') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Allow requests to the local network from hooks and services.') + .settings-content + = render 'outbound' diff --git a/app/views/admin/application_settings/preferences.html.haml b/app/views/admin/application_settings/preferences.html.haml new file mode 100644 index 00000000000..75f76eea3b4 --- /dev/null +++ b/app/views/admin/application_settings/preferences.html.haml @@ -0,0 +1,69 @@ +- breadcrumb_title _("Preferences") +- 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?) } + .settings-header + %h4 + = _('Email') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Various email settings.') + .settings-content + = render 'email' + +%section.settings.as-help-page.no-animate#js-help-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Help page') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Help page text and support page url.') + .settings-content + = render 'help_page' + +%section.settings.as-pages.no-animate#js-pages-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Pages') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Size and domain settings for static websites') + .settings-content + = render 'pages' + +%section.settings.as-realtime.no-animate#js-realtime-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Real-time features') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Change this value to influence how frequently the GitLab UI polls for updates.') + .settings-content + = render 'realtime' + +%section.settings.as-background.no-animate#js-background-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Background jobs') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Configure Sidekiq job throttling.') + .settings-content + = render 'background_jobs' + +%section.settings.as-gitaly.no-animate#js-gitaly-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Gitaly') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Configure Gitaly timeouts.') + .settings-content + = render 'gitaly' diff --git a/app/views/admin/application_settings/reporting.html.haml b/app/views/admin/application_settings/reporting.html.haml new file mode 100644 index 00000000000..1c2d9ccdb2d --- /dev/null +++ b/app/views/admin/application_settings/reporting.html.haml @@ -0,0 +1,36 @@ +- breadcrumb_title _("Reporting") +- page_title _("Reporting") +- @content_class = "limit-container-width" unless fluid_layout + +%section.settings.as-spam.no-animate#js-spam-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Spam and Anti-bot Protection') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Enable reCAPTCHA or Akismet and set IP limits.') + .settings-content + = render 'spam' + +%section.settings.as-abuse.no-animate#js-abuse-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Abuse reports') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Set notification email for abuse reports.') + .settings-content + = render 'abuse' + +%section.settings.as-logging.no-animate#js-logging-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Error Reporting and Logging') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Enable Sentry for error reporting and logging.') + .settings-content + = render 'logging' diff --git a/app/views/admin/application_settings/repository.html.haml b/app/views/admin/application_settings/repository.html.haml new file mode 100644 index 00000000000..d8029e0c54a --- /dev/null +++ b/app/views/admin/application_settings/repository.html.haml @@ -0,0 +1,36 @@ +- breadcrumb_title _("Repository") +- page_title _("Repository") +- @content_class = "limit-container-width" unless fluid_layout + +%section.settings.as-mirror.no-animate#js-mirror-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Repository mirror') + %button.btn.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? 'Collapse' : 'Expand' + %p + = _('Configure push mirrors.') + .settings-content + = render partial: 'repository_mirrors_form' + +%section.settings.as-repository-storage.no-animate#js-repository-storage-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Repository storage') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Configure storage path and circuit breaker settings.') + .settings-content + = render 'repository_storage' + +%section.settings.as-repository-check.no-animate#js-repository-check-settings{ class: ('expanded' if expanded_by_default?) } + .settings-header + %h4 + = _('Repository maintenance') + %button.btn.btn-default.js-settings-toggle{ type: 'button' } + = expanded_by_default? ? _('Collapse') : _('Expand') + %p + = _('Configure automatic git checks and housekeeping on repositories.') + .settings-content + = render 'repository_check' diff --git a/app/views/admin/application_settings/show.html.haml b/app/views/admin/application_settings/show.html.haml index 194a8157013..e2043183a97 100644 --- a/app/views/admin/application_settings/show.html.haml +++ b/app/views/admin/application_settings/show.html.haml @@ -1,359 +1,93 @@ -- breadcrumb_title "Settings" -- page_title "Settings" +- breadcrumb_title _("Settings") +- page_title _("Settings") - @content_class = "limit-container-width" unless fluid_layout -- expanded = Rails.env.test? -%section.settings.as-visibility-access.no-animate#js-visibility-settings{ class: ('expanded' if expanded) } +%section.settings.as-visibility-access.no-animate#js-visibility-settings{ class: ('expanded' if expanded_by_default?) } .settings-header %h4 = _('Visibility and access controls') %button.btn.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') + = expanded_by_default? ? _('Collapse') : _('Expand') %p = _('Set default and restrict visibility levels. Configure import sources and git access protocol.') .settings-content = render 'visibility_and_access' -%section.settings.as-account-limit.no-animate#js-account-settings{ class: ('expanded' if expanded) } +%section.settings.as-account-limit.no-animate#js-account-settings{ class: ('expanded' if expanded_by_default?) } .settings-header %h4 = _('Account and limit') %button.btn.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') + = expanded_by_default? ? _('Collapse') : _('Expand') %p = _('Session expiration, projects limit and attachment size.') .settings-content = render 'account_and_limit' -%section.settings.as-signup.no-animate#js-signup-settings{ class: ('expanded' if expanded) } +%section.settings.as-signup.no-animate#js-signup-settings{ class: ('expanded' if expanded_by_default?) } .settings-header %h4 = _('Sign-up restrictions') %button.btn.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') + = expanded_by_default? ? _('Collapse') : _('Expand') %p = _('Configure the way a user creates a new account.') .settings-content = render 'signup' -%section.settings.as-signin.no-animate#js-signin-settings{ class: ('expanded' if expanded) } +%section.settings.as-signin.no-animate#js-signin-settings{ class: ('expanded' if expanded_by_default?) } .settings-header %h4 = _('Sign-in restrictions') %button.btn.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') + = expanded_by_default? ? _('Collapse') : _('Expand') %p = _('Set requirements for a user to sign-in. Enable mandatory two-factor authentication.') .settings-content = render 'signin' -%section.settings.as-terms.no-animate#js-terms-settings{ class: ('expanded' if expanded) } +%section.qa-terms-settings.settings.as-terms.no-animate#js-terms-settings{ class: ('expanded' if expanded_by_default?) } .settings-header %h4 = _('Terms of Service and Privacy Policy') %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') + = expanded_by_default? ? _('Collapse') : _('Expand') %p = _('Include a Terms of Service agreement and Privacy Policy that all users must accept.') .settings-content = render 'terms' -%section.settings.as-help-page.no-animate#js-help-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Help page') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Help page text and support page url.') - .settings-content - = render 'help_page' - -%section.settings.as-pages.no-animate#js-pages-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Pages') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Size and domain settings for static websites') - .settings-content - = render 'pages' - -%section.settings.as-ci-cd.no-animate#js-ci-cd-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Continuous Integration and Deployment') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Auto DevOps, runners and job artifacts') - .settings-content - = render 'ci_cd' - -%section.settings.as-influx.no-animate#js-influx-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Metrics - Influx') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Enable and configure InfluxDB metrics.') - .settings-content - = render 'influx' - -%section.settings.as-prometheus.no-animate#js-prometheus-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Metrics - Prometheus') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Enable and configure Prometheus metrics.') - .settings-content - = render 'prometheus' - -%section.settings.as-performance-bar.no-animate#js-performance-bar-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Profiling - Performance bar') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Enable the Performance Bar for a given group.') - = link_to icon('question-circle'), help_page_path('administration/monitoring/performance/performance_bar') - .settings-content - = render 'performance_bar' - -%section.settings.as-background.no-animate#js-background-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Background jobs') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Configure Sidekiq job throttling.') - .settings-content - = render 'background_jobs' - -%section.settings.as-spam.no-animate#js-spam-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Spam and Anti-bot Protection') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Enable reCAPTCHA or Akismet and set IP limits.') - .settings-content - = render 'spam' - -%section.settings.as-abuse.no-animate#js-abuse-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Abuse reports') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Set notification email for abuse reports.') - .settings-content - = render 'abuse' - -%section.settings.as-logging.no-animate#js-logging-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Error Reporting and Logging') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Enable Sentry for error reporting and logging.') - .settings-content - = render 'logging' - -%section.qa-repository-storage-settings.settings.as-repository-storage.no-animate#js-repository-storage-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Repository storage') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Configure storage path and circuit breaker settings.') - .settings-content - = render 'repository_storage' - -%section.settings.as-repository-check.no-animate#js-repository-check-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Repository maintenance') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Configure automatic git checks and housekeeping on repositories.') - .settings-content - = render 'repository_check' - -- if Gitlab.config.registry.enabled - %section.settings.as-registry.no-animate#js-registry-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Container Registry') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Various container registry settings.') - .settings-content - = render 'registry' - - if koding_enabled? - %section.settings.as-koding.no-animate#js-koding-settings{ class: ('expanded' if expanded) } + %section.settings.as-koding.no-animate#js-koding-settings{ class: ('expanded' if expanded_by_default?) } .settings-header %h4 = _('Koding') %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') + = expanded_by_default? ? _('Collapse') : _('Expand') %p = _('Online IDE integration settings.') .settings-content = render 'koding' -%section.settings.as-plantuml.no-animate#js-plantuml-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('PlantUML') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Allow rendering of PlantUML diagrams in Asciidoc documents.') - .settings-content - = render 'plantuml' - -%section.settings.as-usage.no-animate#js-usage-settings{ class: ('expanded' if expanded) } - .settings-header#usage-statistics - %h4 - = _('Usage statistics') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Enable or disable version check and usage ping.') - .settings-content - = render 'usage' - -%section.settings.as-email.no-animate#js-email-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Email') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Various email settings.') - .settings-content - = render 'email' - -%section.settings.as-gitaly.no-animate#js-gitaly-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Gitaly') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Configure Gitaly timeouts.') - .settings-content - = render 'gitaly' += render_if_exists 'admin/application_settings/external_authorization_service_form', expanded: expanded_by_default? -%section.settings.as-terminal.no-animate#js-terminal-settings{ class: ('expanded' if expanded) } +%section.settings.as-terminal.no-animate#js-terminal-settings{ class: ('expanded' if expanded_by_default?) } .settings-header %h4 = _('Web terminal') %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') + = expanded_by_default? ? _('Collapse') : _('Expand') %p = _('Set max session time for web terminal.') .settings-content = render 'terminal' -%section.settings.as-realtime.no-animate#js-realtime-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Real-time features') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Change this value to influence how frequently the GitLab UI polls for updates.') - .settings-content - = render 'realtime' - -%section.settings.as-performance.no-animate#js-performance-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Performance optimization') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Various settings that affect GitLab performance.') - .settings-content - = render 'performance' - -%section.settings.as-ip-limits.no-animate#js-ip-limits-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('User and IP Rate Limits') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Configure limits for web and API requests.') - .settings-content - = render 'ip_limits' - -%section.settings.as-outbound.no-animate#js-outbound-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Outbound requests') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Allow requests to the local network from hooks and services.') - .settings-content - = render 'outbound' - -%section.settings.as-mirror.no-animate#js-mirror-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Repository mirror') - %button.btn.js-settings-toggle{ type: 'button' } - = expanded ? 'Collapse' : 'Expand' - %p - = _('Configure push mirrors.') - .settings-content - = render partial: 'repository_mirrors_form' - -= render_if_exists 'admin/application_settings/geo', expanded: expanded - -= render_if_exists 'admin/application_settings/external_authorization_service_form', expanded: expanded - -= render_if_exists 'admin/application_settings/elasticsearch_form', expanded: expanded - -= render_if_exists 'admin/application_settings/slack', expanded: expanded - -= render_if_exists 'admin/application_settings/templates', expanded: expanded - -%section.settings.as-third-party-offers.no-animate#js-third-party-offers-settings{ class: ('expanded' if expanded) } - .settings-header - %h4 - = _('Third party offers') - %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') - %p - = _('Control the display of third party offers.') - .settings-content - = render 'third_party_offers', application_setting: @application_setting - -= render_if_exists 'admin/application_settings/custom_templates_form', expanded: expanded - -%section.settings.no-animate#js-web-ide-settings{ class: ('expanded' if expanded) } +%section.settings.no-animate#js-web-ide-settings{ class: ('expanded' if expanded_by_default?) } .settings-header %h4 = _('Web IDE') %button.btn.btn-default.js-settings-toggle{ type: 'button' } - = expanded ? _('Collapse') : _('Expand') + = expanded_by_default? ? _('Collapse') : _('Expand') %p = _('Manage Web IDE features') .settings-content @@ -370,5 +104,3 @@ = s_('IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation.') = f.submit _('Save changes'), class: "btn btn-success" - -= render_if_exists 'admin/application_settings/pseudonymizer_settings', expanded: expanded diff --git a/app/views/admin/applications/_form.html.haml b/app/views/admin/applications/_form.html.haml index 7f14cddebd8..585576ec799 100644 --- a/app/views/admin/applications/_form.html.haml +++ b/app/views/admin/applications/_form.html.haml @@ -33,5 +33,5 @@ = render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: application, scopes: @scopes .form-actions - = f.submit 'Submit', class: "btn btn-save wide" + = f.submit 'Submit', class: "btn btn-success wide" = link_to "Cancel", admin_applications_path, class: "btn btn-cancel" diff --git a/app/views/admin/broadcast_messages/_form.html.haml b/app/views/admin/broadcast_messages/_form.html.haml index 7f34357f147..c465d9f51d6 100644 --- a/app/views/admin/broadcast_messages/_form.html.haml +++ b/app/views/admin/broadcast_messages/_form.html.haml @@ -36,6 +36,6 @@ = f.datetime_select :ends_at, {}, class: 'form-control form-control-inline' .form-actions - if @broadcast_message.persisted? - = f.submit "Update broadcast message", class: "btn btn-create" + = f.submit "Update broadcast message", class: "btn btn-success" - else - = f.submit "Add broadcast message", class: "btn btn-create" + = f.submit "Add broadcast message", class: "btn btn-success" diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml index fac61f9d249..85c04f8a01d 100644 --- a/app/views/admin/dashboard/index.html.haml +++ b/app/views/admin/dashboard/index.html.haml @@ -14,7 +14,7 @@ Projects: = approximate_count_with_delimiters(@counts, Project) %hr - = link_to('New project', new_project_path, class: "btn btn-new") + = link_to('New project', new_project_path, class: "btn btn-success") .col-sm-4 .info-well.dark-well .well-segment.well-centered @@ -24,7 +24,7 @@ = approximate_count_with_delimiters(@counts, User) = render_if_exists 'admin/dashboard/users_statistics' %hr - = link_to 'New user', new_admin_user_path, class: "btn btn-new" + = link_to 'New user', new_admin_user_path, class: "btn btn-success" .col-sm-4 .info-well.dark-well .well-segment.well-centered @@ -33,7 +33,7 @@ Groups: = approximate_count_with_delimiters(@counts, Group) %hr - = link_to 'New group', new_admin_group_path, class: "btn btn-new" + = link_to 'New group', new_admin_group_path, class: "btn btn-success" .row .col-md-4 .info-well diff --git a/app/views/admin/deploy_keys/edit.html.haml b/app/views/admin/deploy_keys/edit.html.haml index b50adef362f..7c04ef03947 100644 --- a/app/views/admin/deploy_keys/edit.html.haml +++ b/app/views/admin/deploy_keys/edit.html.haml @@ -6,5 +6,5 @@ = form_for [:admin, @deploy_key], html: { class: 'deploy-key-form' } do |f| = render partial: 'shared/deploy_keys/form', locals: { form: f, deploy_key: @deploy_key } .form-actions - = f.submit 'Save changes', class: 'btn-save btn' + = f.submit 'Save changes', class: 'btn-success btn' = link_to 'Cancel', admin_deploy_keys_path, class: 'btn btn-cancel' diff --git a/app/views/admin/deploy_keys/index.html.haml b/app/views/admin/deploy_keys/index.html.haml index 52ab8bae119..01013be06d6 100644 --- a/app/views/admin/deploy_keys/index.html.haml +++ b/app/views/admin/deploy_keys/index.html.haml @@ -3,7 +3,7 @@ %h3.page-title.deploy-keys-title Public deploy keys (#{@deploy_keys.count}) .float-right - = link_to 'New deploy key', new_admin_deploy_key_path, class: 'btn btn-new btn-sm btn-inverted' + = link_to 'New deploy key', new_admin_deploy_key_path, class: 'btn btn-success btn-sm btn-inverted' - if @deploy_keys.any? .table-holder.deploy-keys-list diff --git a/app/views/admin/deploy_keys/new.html.haml b/app/views/admin/deploy_keys/new.html.haml index d4f8e340b69..9a563a5bc78 100644 --- a/app/views/admin/deploy_keys/new.html.haml +++ b/app/views/admin/deploy_keys/new.html.haml @@ -6,5 +6,5 @@ = form_for [:admin, @deploy_key], html: { class: 'deploy-key-form' } do |f| = render partial: 'shared/deploy_keys/form', locals: { form: f, deploy_key: @deploy_key } .form-actions - = f.submit 'Create', class: 'btn-create btn' + = f.submit 'Create', class: 'btn-success btn' = link_to 'Cancel', admin_deploy_keys_path, class: 'btn btn-cancel' diff --git a/app/views/admin/groups/_form.html.haml b/app/views/admin/groups/_form.html.haml index a3773e90cfb..2a117c1414e 100644 --- a/app/views/admin/groups/_form.html.haml +++ b/app/views/admin/groups/_form.html.haml @@ -26,12 +26,12 @@ .alert.alert-info = render 'shared/group_tips' .form-actions - = f.submit _('Create group'), class: "btn btn-create" + = f.submit _('Create group'), class: "btn btn-success" = link_to _('Cancel'), admin_groups_path, class: "btn btn-cancel" - else .form-actions - = f.submit _('Save changes'), class: "btn btn-save" + = f.submit _('Save changes'), class: "btn btn-success" = link_to _('Cancel'), admin_group_path(@group), class: "btn btn-cancel" = render_if_exists 'ldap_group_links/ldap_syncrhonizations', group: @group diff --git a/app/views/admin/groups/index.html.haml b/app/views/admin/groups/index.html.haml index 6a9b85b4109..cb833ffd9ac 100644 --- a/app/views/admin/groups/index.html.haml +++ b/app/views/admin/groups/index.html.haml @@ -12,7 +12,7 @@ = 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-new" do + = link_to new_admin_group_path, class: "btn btn-success" do = _('New group') %ul.content-list = render @groups diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml index 72b068ea6b5..0c683f86252 100644 --- a/app/views/admin/groups/show.html.haml +++ b/app/views/admin/groups/show.html.haml @@ -111,7 +111,7 @@ .prepend-top-10 = select_tag :access_level, options_for_select(GroupMember.access_level_roles), class: "project-access-select select2" %hr - = button_tag _('Add users to group'), class: "btn btn-create" + = button_tag _('Add users to group'), class: "btn btn-success" = render 'shared/members/requests', membership_source: @group, requesters: @requesters, force_mobile_view: true .card diff --git a/app/views/admin/hooks/edit.html.haml b/app/views/admin/hooks/edit.html.haml index b9a650e1f1f..486d0477f20 100644 --- a/app/views/admin/hooks/edit.html.haml +++ b/app/views/admin/hooks/edit.html.haml @@ -12,7 +12,7 @@ = form_for @hook, as: :hook, url: admin_hook_path do |f| = render partial: 'form', locals: { form: f, hook: @hook } .form-actions - = f.submit 'Save changes', class: 'btn btn-create' + = f.submit 'Save changes', class: 'btn btn-success' = render 'shared/web_hooks/test_button', triggers: SystemHook.triggers, hook: @hook = link_to 'Remove', admin_hook_path(@hook), method: :delete, class: 'btn btn-remove float-right', data: { confirm: 'Are you sure?' } diff --git a/app/views/admin/hooks/index.html.haml b/app/views/admin/hooks/index.html.haml index 87f9b0e86a7..5d462d7b732 100644 --- a/app/views/admin/hooks/index.html.haml +++ b/app/views/admin/hooks/index.html.haml @@ -10,7 +10,7 @@ .col-lg-8.append-bottom-default = form_for @hook, as: :hook, url: admin_hooks_path do |f| = render partial: 'form', locals: { form: f, hook: @hook } - = f.submit 'Add system hook', class: 'btn btn-create' + = f.submit 'Add system hook', class: 'btn btn-success' %hr diff --git a/app/views/admin/identities/_form.html.haml b/app/views/admin/identities/_form.html.haml index 946d868da01..3ab7990d9e2 100644 --- a/app/views/admin/identities/_form.html.haml +++ b/app/views/admin/identities/_form.html.haml @@ -12,5 +12,5 @@ = f.text_field :extern_uid, class: 'form-control', required: true .form-actions - = f.submit _('Save changes'), class: "btn btn-save" + = f.submit _('Save changes'), class: "btn btn-success" diff --git a/app/views/admin/identities/index.html.haml b/app/views/admin/identities/index.html.haml index df3df159947..9543bbcf977 100644 --- a/app/views/admin/identities/index.html.haml +++ b/app/views/admin/identities/index.html.haml @@ -3,7 +3,7 @@ - page_title _("Identities"), @user.name, _("Users") = render 'admin/users/head' -= link_to _('New identity'), new_admin_user_identity_path, class: 'float-right btn btn-new' += link_to _('New identity'), new_admin_user_identity_path, class: 'float-right btn btn-success' - if @identities.present? .table-holder %table.table diff --git a/app/views/admin/labels/_form.html.haml b/app/views/admin/labels/_form.html.haml index ee2d4c8430a..5e7b4817461 100644 --- a/app/views/admin/labels/_form.html.haml +++ b/app/views/admin/labels/_form.html.haml @@ -27,5 +27,5 @@ .form-actions - = f.submit _('Save'), class: 'btn btn-save js-save-button' + = f.submit _('Save'), class: 'btn btn-success js-save-button' = link_to _("Cancel"), admin_labels_path, class: 'btn btn-cancel' diff --git a/app/views/admin/labels/index.html.haml b/app/views/admin/labels/index.html.haml index f1b8658f84e..5a5b3d18c5f 100644 --- a/app/views/admin/labels/index.html.haml +++ b/app/views/admin/labels/index.html.haml @@ -1,7 +1,7 @@ - page_title _("Labels") %div - = link_to new_admin_label_path, class: "float-right btn btn-nr btn-new" do + = link_to new_admin_label_path, class: "float-right btn btn-nr btn-success" do = _('New label') %h3.page-title = _('Labels') diff --git a/app/views/admin/projects/index.html.haml b/app/views/admin/projects/index.html.haml index 57de792f92d..46bb57c78a8 100644 --- a/app/views/admin/projects/index.html.haml +++ b/app/views/admin/projects/index.html.haml @@ -21,7 +21,7 @@ = dropdown_content = dropdown_loading = render 'shared/projects/dropdown' - = link_to new_project_path, class: 'btn btn-new' do + = link_to new_project_path, class: 'btn btn-success' do New Project = button_tag "Search", class: "btn btn-primary btn-search hide" diff --git a/app/views/admin/runners/_runner.html.haml b/app/views/admin/runners/_runner.html.haml index 9c15226f0ec..e4fc2985087 100644 --- a/app/views/admin/runners/_runner.html.haml +++ b/app/views/admin/runners/_runner.html.haml @@ -1,47 +1,65 @@ .gl-responsive-table-row{ id: dom_id(runner) } - = render layout: 'runner_table_cell', locals: { label: _('Type') } do - - if runner.instance_type? - %span.badge.badge-success shared - - elsif runner.group_type? - %span.badge.badge-success group - - else - %span.badge.badge-info specific - - if runner.locked? - %span.badge.badge-warning locked - - unless runner.active? - %span.badge.badge-danger paused - - = render layout: 'runner_table_cell', locals: { label: _('Runner token') } do - = link_to runner.short_sha, admin_runner_path(runner) - - = render layout: 'runner_table_cell', locals: { label: _('Description') } do - = runner.description - - = render layout: 'runner_table_cell', locals: { label: _('Version') } do - = runner.version - - = render layout: 'runner_table_cell', locals: { label: _('IP Address') } do - = runner.ip_address - - = render layout: 'runner_table_cell', locals: { label: _('Projects') } do - - if runner.instance_type? || runner.group_type? - = _('n/a') - - else - = runner.projects.count(:all) - - = render layout: 'runner_table_cell', locals: { label: _('Jobs') } do - = runner.builds.count(:all) - - = render layout: 'runner_table_cell', locals: { label: _('Tags') } do - - runner.tag_list.sort.each do |tag| - %span.badge.badge-primary - = tag - - = render layout: 'runner_table_cell', locals: { label: _('Last contact') } do - - if runner.contacted_at - = time_ago_with_tooltip runner.contacted_at - - else - = _('Never') + .table-section.section-10.section-wrap + .table-mobile-header{ role: 'rowheader' }= _('Type') + .table-mobile-content + - if runner.instance_type? + %span.badge.badge-success shared + - elsif runner.group_type? + %span.badge.badge-success group + - else + %span.badge.badge-info specific + - if runner.locked? + %span.badge.badge-warning locked + - unless runner.active? + %span.badge.badge-danger paused + + .table-section.section-10 + .table-mobile-header{ role: 'rowheader' }= _('Runner token') + .table-mobile-content + = link_to runner.short_sha, admin_runner_path(runner) + + .table-section.section-15 + .table-mobile-header{ role: 'rowheader' }= _('Description') + .table-mobile-content.str-truncated.has-tooltip{ title: runner.description } + = runner.description + + .table-section.section-15 + .table-mobile-header{ role: 'rowheader' }= _('Version') + .table-mobile-content.str-truncated.has-tooltip{ title: runner.version } + = runner.version + + .table-section.section-10 + .table-mobile-header{ role: 'rowheader' }= _('IP Address') + .table-mobile-content + = runner.ip_address + + .table-section.section-5 + .table-mobile-header{ role: 'rowheader' }= _('Projects') + .table-mobile-content + - if runner.instance_type? || runner.group_type? + = _('n/a') + - else + = runner.projects.count(:all) + + .table-section.section-5 + .table-mobile-header{ role: 'rowheader' }= _('Jobs') + .table-mobile-content + = runner.builds.count(:all) + + .table-section.section-10.section-wrap + .table-mobile-header{ role: 'rowheader' }= _('Tags') + .table-mobile-content + - runner.tag_list.sort.each do |tag| + %span.badge.badge-primary + = tag + + .table-section.section-10 + .table-mobile-header{ role: 'rowheader' }= _('Last contact') + .table-mobile-content + - if runner.contacted_at + = time_ago_with_tooltip runner.contacted_at + - else + = _('Never') .table-section.table-button-footer.section-10 .btn-group.table-action-buttons diff --git a/app/views/admin/runners/_runner_table_cell.html.haml b/app/views/admin/runners/_runner_table_cell.html.haml deleted file mode 100644 index 78526ee6d23..00000000000 --- a/app/views/admin/runners/_runner_table_cell.html.haml +++ /dev/null @@ -1,4 +0,0 @@ -.table-section.section-10 - .table-mobile-header{ role: 'rowheader' }= label - .table-mobile-content - = yield diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml index 07333d63f2c..ee2e1703fdb 100644 --- a/app/views/admin/runners/index.html.haml +++ b/app/views/admin/runners/index.html.haml @@ -4,7 +4,7 @@ %div{ class: container_class } .bs-callout %p - = (_"A 'Runner' is a process which runs a job. You can setup as many Runners as you need.") + = (_"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 @@ -98,8 +98,16 @@ .runners-content.content-list .table-holder .gl-responsive-table-row.table-row-header{ role: 'row' } - - [_('Type'), _('Runner token'), _('Description'), _('Version'), _('IP Address'), _('Projects'), _('Jobs'), _('Tags'), _('Last contact')].each do |label| - .table-section.section-10{ role: 'rowheader' }= label + .table-section.section-10{ role: 'rowheader' }= _('Type') + .table-section.section-10{ role: 'rowheader' }= _('Runner token') + .table-section.section-15{ role: 'rowheader' }= _('Description') + .table-section.section-15{ 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 diff --git a/app/views/admin/services/_form.html.haml b/app/views/admin/services/_form.html.haml index 993006e8745..1798b44bbb7 100644 --- a/app/views/admin/services/_form.html.haml +++ b/app/views/admin/services/_form.html.haml @@ -7,4 +7,4 @@ = render 'shared/service_settings', form: form, subject: @service .footer-block.row-content-block - = form.submit 'Save', class: 'btn btn-save' + = form.submit 'Save', class: 'btn btn-success' diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml index 7f21bdb91c8..296ef073144 100644 --- a/app/views/admin/users/_form.html.haml +++ b/app/views/admin/users/_form.html.haml @@ -75,8 +75,8 @@ .form-actions - if @user.new_record? - = f.submit 'Create user', class: "btn btn-create" + = f.submit 'Create user', class: "btn btn-success" = link_to 'Cancel', admin_users_path, class: "btn btn-cancel" - else - = f.submit 'Save changes', class: "btn btn-save" + = f.submit 'Save changes', class: "btn btn-success" = link_to 'Cancel', admin_user_path(@user), class: "btn btn-cancel" diff --git a/app/views/admin/users/index.html.haml b/app/views/admin/users/index.html.haml index faeb82656ba..f910e90d6ca 100644 --- a/app/views/admin/users/index.html.haml +++ b/app/views/admin/users/index.html.haml @@ -31,7 +31,7 @@ = sort_title_recently_updated = link_to admin_users_path(sort: sort_value_oldest_updated, filter: params[:filter]) do = sort_title_oldest_updated - = link_to 'New user', new_admin_user_path, class: 'btn btn-new btn-search' + = link_to 'New user', new_admin_user_path, class: 'btn btn-success btn-search' .top-area.scrolling-tabs-container.inner-page-scroll-tabs .fade-left diff --git a/app/views/ci/runner/_how_to_setup_runner.html.haml b/app/views/ci/runner/_how_to_setup_runner.html.haml index c26eb873718..b1b142460b0 100644 --- a/app/views/ci/runner/_how_to_setup_runner.html.haml +++ b/app/views/ci/runner/_how_to_setup_runner.html.haml @@ -1,6 +1,6 @@ - link = link_to _("Install GitLab Runner"), 'https://docs.gitlab.com/runner/install/', target: '_blank' .append-bottom-10 - %h4= _("Setup a %{type} Runner manually") % { type: type } + %h4= _("Set up a %{type} Runner manually") % { type: type } %ol %li diff --git a/app/views/ci/runner/_how_to_setup_specific_runner.html.haml b/app/views/ci/runner/_how_to_setup_specific_runner.html.haml index e765a353fe4..afe57bdfa01 100644 --- a/app/views/ci/runner/_how_to_setup_specific_runner.html.haml +++ b/app/views/ci/runner/_how_to_setup_specific_runner.html.haml @@ -1,6 +1,6 @@ .bs-callout.help-callout .append-bottom-10 - %h4= _('Setup a specific Runner automatically') + %h4= _('Set up a specific Runner automatically') %p - link_to_help_page = link_to(_('Learn more about Kubernetes'), diff --git a/app/views/dashboard/_groups_head.html.haml b/app/views/dashboard/_groups_head.html.haml index d8f1e50544c..727784141bb 100644 --- a/app/views/dashboard/_groups_head.html.haml +++ b/app/views/dashboard/_groups_head.html.haml @@ -10,4 +10,4 @@ = render 'shared/groups/search_form' = render 'shared/groups/dropdown' - if current_user.can_create_group? - = link_to _("New group"), new_group_path, class: "btn btn-new" + = link_to _("New group"), new_group_path, class: "btn btn-success" diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml index 9b1d9b659f9..69a2e408073 100644 --- a/app/views/dashboard/_projects_head.html.haml +++ b/app/views/dashboard/_projects_head.html.haml @@ -19,4 +19,4 @@ = render 'shared/projects/search_form' = render 'shared/projects/dropdown' - if current_user.can_create_project? - = link_to "New project", new_project_path, class: "btn btn-new" + = link_to "New project", new_project_path, class: "btn btn-success" diff --git a/app/views/dashboard/_snippets_head.html.haml b/app/views/dashboard/_snippets_head.html.haml index e7e323a8683..4f38339b87a 100644 --- a/app/views/dashboard/_snippets_head.html.haml +++ b/app/views/dashboard/_snippets_head.html.haml @@ -9,4 +9,4 @@ - if current_user .nav-controls.d-none.d-sm-block - = link_to "New snippet", new_snippet_path, class: "btn btn-new", title: "New snippet" + = link_to "New snippet", new_snippet_path, class: "btn btn-success", title: "New snippet" diff --git a/app/views/dashboard/snippets/index.html.haml b/app/views/dashboard/snippets/index.html.haml index 4391624196b..b11dc2c8e9b 100644 --- a/app/views/dashboard/snippets/index.html.haml +++ b/app/views/dashboard/snippets/index.html.haml @@ -7,7 +7,7 @@ .d-block.d-sm-none - = link_to new_snippet_path, class: "btn btn-new btn-block", title: "New snippet" do + = link_to new_snippet_path, class: "btn btn-success btn-block", title: "New snippet" do New snippet = render partial: 'snippets/snippets', locals: { link_project: true } diff --git a/app/views/devise/sessions/_new_base.html.haml b/app/views/devise/sessions/_new_base.html.haml index 492c36081d8..7dacd0b1d72 100644 --- a/app/views/devise/sessions/_new_base.html.haml +++ b/app/views/devise/sessions/_new_base.html.haml @@ -17,4 +17,4 @@ = recaptcha_tags .submit-container.move-submit-down - = f.submit "Sign in", class: "btn btn-save qa-sign-in-button" + = f.submit "Sign in", class: "btn btn-success qa-sign-in-button" diff --git a/app/views/devise/sessions/_new_crowd.html.haml b/app/views/devise/sessions/_new_crowd.html.haml index 36ff42090be..131544ac0c0 100644 --- a/app/views/devise/sessions/_new_crowd.html.haml +++ b/app/views/devise/sessions/_new_crowd.html.haml @@ -10,4 +10,4 @@ %label{ for: "remember_me" } = check_box_tag :remember_me, '1', false, id: 'remember_me' %span Remember me - = submit_tag "Sign in", class: "btn-save btn" + = submit_tag "Sign in", class: "btn-success btn" diff --git a/app/views/devise/sessions/_new_ldap.html.haml b/app/views/devise/sessions/_new_ldap.html.haml index 6b04f69fe61..796c0cadda8 100644 --- a/app/views/devise/sessions/_new_ldap.html.haml +++ b/app/views/devise/sessions/_new_ldap.html.haml @@ -10,4 +10,4 @@ %label{ for: "remember_me" } = check_box_tag :remember_me, '1', false, id: 'remember_me' %span Remember me - = submit_tag "Sign in", class: "btn-save btn qa-sign-in-button" + = submit_tag "Sign in", class: "btn-success btn qa-sign-in-button" diff --git a/app/views/devise/sessions/two_factor.html.haml b/app/views/devise/sessions/two_factor.html.haml index ba168c4eab8..fefdf5f9531 100644 --- a/app/views/devise/sessions/two_factor.html.haml +++ b/app/views/devise/sessions/two_factor.html.haml @@ -11,7 +11,7 @@ = f.text_field :otp_attempt, class: 'form-control', required: true, autofocus: true, autocomplete: 'off', title: 'This field is required.' %p.form-text.text-muted.hint Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes. .prepend-top-20 - = f.submit "Verify code", class: "btn btn-save" + = f.submit "Verify code", class: "btn btn-success" - if @user.two_factor_u2f_enabled? = render "u2f/authenticate", locals: { params: params, resource: resource, resource_name: resource_name } diff --git a/app/views/doorkeeper/applications/_form.html.haml b/app/views/doorkeeper/applications/_form.html.haml index 0bc057a8864..78904f550c7 100644 --- a/app/views/doorkeeper/applications/_form.html.haml +++ b/app/views/doorkeeper/applications/_form.html.haml @@ -20,4 +20,4 @@ = render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: application, scopes: @scopes .prepend-top-default - = f.submit _('Save application'), class: "btn btn-create" + = f.submit _('Save application'), class: "btn btn-success" diff --git a/app/views/groups/group_members/_new_group_member.html.haml b/app/views/groups/group_members/_new_group_member.html.haml index aa03f8365f9..04683ec5a9a 100644 --- a/app/views/groups/group_members/_new_group_member.html.haml +++ b/app/views/groups/group_members/_new_group_member.html.haml @@ -19,4 +19,4 @@ On this date, the member(s) will automatically lose access to this group and all of its projects. .col-md-2 - = f.submit 'Add to group', class: "btn btn-create btn-block" + = f.submit 'Add to group', class: "btn btn-success btn-block" diff --git a/app/views/groups/labels/index.html.haml b/app/views/groups/labels/index.html.haml index 86178eb2ffd..003bd25dd06 100644 --- a/app/views/groups/labels/index.html.haml +++ b/app/views/groups/labels/index.html.haml @@ -7,7 +7,7 @@ - if can_admin_label - content_for(:header_content) do .nav-controls - = link_to _('New label'), new_group_label_path(@group), class: "btn btn-new" + = link_to _('New label'), new_group_label_path(@group), class: "btn btn-success" - if @labels.exists? || search.present? #promote-label-modal diff --git a/app/views/groups/milestones/_form.html.haml b/app/views/groups/milestones/_form.html.haml index 6d35457a0ec..39e3af5f6d2 100644 --- a/app/views/groups/milestones/_form.html.haml +++ b/app/views/groups/milestones/_form.html.haml @@ -19,9 +19,9 @@ .form-actions - if @milestone.new_record? - = f.submit 'Create milestone', class: "btn-create btn" + = f.submit 'Create milestone', class: "btn-success btn" = link_to "Cancel", group_milestones_path(@group), class: "btn btn-cancel" - else - = f.submit 'Update milestone', class: "btn-create btn" + = f.submit 'Update milestone', class: "btn-success btn" = link_to "Cancel", group_milestone_path(@group, @milestone), class: "btn btn-cancel" diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml index b6424df55cd..af4fe8f2ef8 100644 --- a/app/views/groups/milestones/index.html.haml +++ b/app/views/groups/milestones/index.html.haml @@ -6,7 +6,7 @@ .nav-controls = render 'shared/milestones_sort_dropdown' - if can?(current_user, :admin_milestone, @group) - = link_to "New milestone", new_group_milestone_path(@group), class: "btn btn-new" + = link_to "New milestone", new_group_milestone_path(@group), class: "btn btn-success" .milestones %ul.content-list diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml index 53f54db1ddf..683129fdf6e 100644 --- a/app/views/groups/new.html.haml +++ b/app/views/groups/new.html.haml @@ -36,5 +36,5 @@ = render 'shared/group_tips' .form-actions - = f.submit 'Create group', class: "btn btn-create" + = f.submit 'Create group', class: "btn btn-success" = link_to 'Cancel', dashboard_groups_path, class: 'btn btn-cancel' diff --git a/app/views/help/ui.html.haml b/app/views/help/ui.html.haml index b32b602ceb3..506f580b246 100644 --- a/app/views/help/ui.html.haml +++ b/app/views/help/ui.html.haml @@ -189,7 +189,7 @@ %li = link_to 'Sort by date', '#' - = link_to 'New issue', '#', class: 'btn btn-new btn-inverted' + = link_to 'New issue', '#', class: 'btn btn-success btn-inverted' .lead Only nav links without button and search diff --git a/app/views/import/fogbugz/new.html.haml b/app/views/import/fogbugz/new.html.haml index b54b1af1e0c..626080c284b 100644 --- a/app/views/import/fogbugz/new.html.haml +++ b/app/views/import/fogbugz/new.html.haml @@ -21,4 +21,4 @@ .col-md-4 = password_field_tag :password, nil, class: 'form-control' .form-actions - = submit_tag _('Continue to the next step'), class: 'btn btn-create' + = submit_tag _('Continue to the next step'), class: 'btn btn-success' diff --git a/app/views/import/fogbugz/new_user_map.html.haml b/app/views/import/fogbugz/new_user_map.html.haml index ff2f989c509..8ed9dc68bb3 100644 --- a/app/views/import/fogbugz/new_user_map.html.haml +++ b/app/views/import/fogbugz/new_user_map.html.haml @@ -39,4 +39,4 @@ scope: :all, email_user: true, selected: user[:gitlab_user]) .form-actions - = submit_tag _('Continue to the next step'), class: 'btn btn-create' + = submit_tag _('Continue to the next step'), class: 'btn btn-success' diff --git a/app/views/import/gitea/new.html.haml b/app/views/import/gitea/new.html.haml index 2b3102f9af9..a88b04eccbb 100644 --- a/app/views/import/gitea/new.html.haml +++ b/app/views/import/gitea/new.html.haml @@ -19,4 +19,4 @@ .col-sm-4 = text_field_tag :personal_access_token, nil, class: 'form-control' .form-actions - = submit_tag _('List Your Gitea Repositories'), class: 'btn btn-create' + = submit_tag _('List Your Gitea Repositories'), class: 'btn btn-success' diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml index c4218f3d787..877d945a09b 100644 --- a/app/views/import/gitlab_projects/new.html.haml +++ b/app/views/import/gitlab_projects/new.html.haml @@ -41,5 +41,5 @@ = file_field_tag :file, class: '' .row .form-actions.col-sm-12 - = submit_tag _('Import project'), class: 'btn btn-create' + = submit_tag _('Import project'), class: 'btn btn-success' = link_to _('Cancel'), new_project_path, class: 'btn btn-cancel' diff --git a/app/views/import/google_code/new.html.haml b/app/views/import/google_code/new.html.haml index fd6e4726fc5..7a6ad28f0aa 100644 --- a/app/views/import/google_code/new.html.haml +++ b/app/views/import/google_code/new.html.haml @@ -59,4 +59,4 @@ = _('Yes, let me map Google Code users to full names or GitLab users.') %li %p - = submit_tag _('Continue to the next step'), class: "btn btn-create" + = submit_tag _('Continue to the next step'), class: "btn btn-success" diff --git a/app/views/import/google_code/new_user_map.html.haml b/app/views/import/google_code/new_user_map.html.haml index baaaf6bdc63..f523b993aa7 100644 --- a/app/views/import/google_code/new_user_map.html.haml +++ b/app/views/import/google_code/new_user_map.html.haml @@ -33,4 +33,4 @@ = text_area_tag :user_map, JSON.pretty_generate(@user_map), class: 'form-control', rows: 15 .form-actions - = submit_tag _('Continue to the next step'), class: "btn btn-create" + = submit_tag _('Continue to the next step'), class: "btn btn-success" diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml index ff25b040913..a2636f8179a 100644 --- a/app/views/layouts/nav/sidebar/_admin.html.haml +++ b/app/views/layouts/nav/sidebar/_admin.html.haml @@ -199,10 +199,54 @@ = sprite_icon('settings') %span.nav-item-name = _('Settings') - %ul.sidebar-sub-level-items.is-fly-out-only + + %ul.sidebar-sub-level-items = nav_link(controller: :application_settings, html_options: { class: "fly-out-top-item" } ) do = link_to admin_application_settings_path do %strong.fly-out-top-item-name = _('Settings') + %li.divider.fly-out-top-item + = nav_link(path: 'application_settings#show') do + = link_to admin_application_settings_path, title: _('General') do + %span + = _('General') + = nav_link(path: 'application_settings#integrations') do + = link_to integrations_admin_application_settings_path, title: _('Integrations') do + %span + = _('Integrations') + = nav_link(path: 'application_settings#repository') do + = link_to repository_admin_application_settings_path, title: _('Repository') do + %span + = _('Repository') + - if template_exists?('admin/application_settings/templates') + = nav_link(path: 'application_settings#templates') do + = link_to templates_admin_application_settings_path, title: _('Templates') do + %span + = _('Templates') + = nav_link(path: 'application_settings#ci_cd') do + = link_to ci_cd_admin_application_settings_path, title: _('CI/CD') do + %span + = _('CI/CD') + = nav_link(path: 'application_settings#reporting') do + = link_to reporting_admin_application_settings_path, title: _('Reporting') do + %span + = _('Reporting') + = nav_link(path: 'application_settings#metrics_and_profiling') do + = link_to metrics_and_profiling_admin_application_settings_path, title: _('Metrics and profiling') do + %span + = _('Metrics and profiling') + = nav_link(path: 'application_settings#network') do + = link_to network_admin_application_settings_path, title: _('Network') do + %span + = _('Network') + - if template_exists?('admin/application_settings/geo') + = nav_link(path: 'application_settings#geo') do + = link_to geo_admin_application_settings_path, title: _('Geo') do + %span + = _('Geo') + = nav_link(path: 'application_settings#preferences') do + = link_to preferences_admin_application_settings_path, title: _('Preferences') do + %span + = _('Preferences') = render 'shared/sidebar_toggle_button' diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml index 7239780871c..25cd53b378a 100644 --- a/app/views/layouts/nav/sidebar/_project.html.haml +++ b/app/views/layouts/nav/sidebar/_project.html.haml @@ -245,7 +245,7 @@ = link_to _('Auto DevOps'), help_page_path('topics/autodevops/index.md') %span= _('uses Kubernetes clusters to deploy your code!') %hr - %button.btn.btn-create.btn-sm.dismiss-feature-highlight{ type: 'button' } + %button.btn.btn-success.btn-sm.dismiss-feature-highlight{ type: 'button' } %span= _("Got it!") = sprite_icon('thumb-up') diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml index c8faf2b3af3..1823f191fb3 100644 --- a/app/views/profiles/emails/index.html.haml +++ b/app/views/profiles/emails/index.html.haml @@ -15,7 +15,7 @@ = f.label :email, class: 'label-bold' = f.text_field :email, class: 'form-control' .prepend-top-default - = f.submit 'Add email address', class: 'btn btn-create' + = f.submit 'Add email address', class: 'btn btn-success' %hr %h4.prepend-top-0 Linked emails (#{@emails.count + 1}) diff --git a/app/views/profiles/gpg_keys/_form.html.haml b/app/views/profiles/gpg_keys/_form.html.haml index aa9b0aad034..6c4cb614a2b 100644 --- a/app/views/profiles/gpg_keys/_form.html.haml +++ b/app/views/profiles/gpg_keys/_form.html.haml @@ -7,4 +7,4 @@ = f.text_area :key, class: "form-control", rows: 8, required: true, placeholder: "Don't paste the private part of the GPG key. Paste the public part which begins with '-----BEGIN PGP PUBLIC KEY BLOCK-----'." .prepend-top-default - = f.submit 'Add key', class: "btn btn-create" + = f.submit 'Add key', class: "btn btn-success" diff --git a/app/views/profiles/keys/_form.html.haml b/app/views/profiles/keys/_form.html.haml index 700c22e1652..21eef08983c 100644 --- a/app/views/profiles/keys/_form.html.haml +++ b/app/views/profiles/keys/_form.html.haml @@ -16,7 +16,7 @@ %strong= _('Oops, are you sure?') %p= s_("Profiles|This doesn't look like a public SSH key, are you sure you want to add it?") - %button.btn.btn-create.js-add-ssh-key-validation-confirm-submit= _("Yes, add it") + %button.btn.btn-success.js-add-ssh-key-validation-confirm-submit= _("Yes, add it") .prepend-top-default - = f.submit s_('Profiles|Add key'), class: "btn btn-create js-add-ssh-key-validation-original-submit qa-add-key-button" + = f.submit s_('Profiles|Add key'), class: "btn btn-success js-add-ssh-key-validation-original-submit qa-add-key-button" diff --git a/app/views/profiles/passwords/edit.html.haml b/app/views/profiles/passwords/edit.html.haml index 9c8cc9c059b..0b4b9841ea1 100644 --- a/app/views/profiles/passwords/edit.html.haml +++ b/app/views/profiles/passwords/edit.html.haml @@ -29,6 +29,6 @@ = f.label :password_confirmation, class: 'label-bold' = f.password_field :password_confirmation, required: true, class: 'form-control' .prepend-top-default.append-bottom-default - = f.submit 'Save password', class: "btn btn-create append-right-10" + = f.submit 'Save password', class: "btn btn-success append-right-10" - unless @user.password_automatically_set? = link_to "I forgot my password", reset_profile_password_path, method: :put, class: "account-btn-link" diff --git a/app/views/profiles/passwords/new.html.haml b/app/views/profiles/passwords/new.html.haml index d98f09e2415..d265f3c44ba 100644 --- a/app/views/profiles/passwords/new.html.haml +++ b/app/views/profiles/passwords/new.html.haml @@ -22,4 +22,4 @@ .col-sm-10 = f.password_field :password_confirmation, required: true, class: 'form-control' .form-actions - = f.submit 'Set new password', class: "btn btn-create" + = f.submit 'Set new password', class: "btn btn-success" diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml index fd6dd74e1c5..156c0d05b02 100644 --- a/app/views/profiles/preferences/show.html.haml +++ b/app/views/profiles/preferences/show.html.haml @@ -58,4 +58,4 @@ .form-text.text-muted Choose what content you want to see on a project’s overview page .form-group - = f.submit 'Save changes', class: 'btn btn-save' + = f.submit 'Save changes', class: 'btn btn-success' diff --git a/app/views/projects/_commit_button.html.haml b/app/views/projects/_commit_button.html.haml index b387e38c1a6..1e27c71d20d 100644 --- a/app/views/projects/_commit_button.html.haml +++ b/app/views/projects/_commit_button.html.haml @@ -1,5 +1,5 @@ .form-actions - = button_tag 'Commit changes', class: 'btn commit-btn js-commit-button btn-create' + = button_tag 'Commit changes', class: 'btn commit-btn js-commit-button btn-success' = link_to 'Cancel', cancel_path, class: 'btn btn-cancel', data: {confirm: leave_edit_message} diff --git a/app/views/projects/_fork_suggestion.html.haml b/app/views/projects/_fork_suggestion.html.haml index c855bfaf067..0b616a0c1ce 100644 --- a/app/views/projects/_fork_suggestion.html.haml +++ b/app/views/projects/_fork_suggestion.html.haml @@ -6,6 +6,6 @@ edit files in this project directly. Please fork this project, make your changes there, and submit a merge request. - = link_to 'Fork', nil, method: :post, class: 'js-fork-suggestion-button btn btn-grouped btn-inverted btn-new' + = link_to 'Fork', nil, method: :post, class: 'js-fork-suggestion-button btn btn-grouped btn-inverted btn-success' %button.js-cancel-fork-suggestion-button.btn.btn-grouped{ type: 'button' } Cancel diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml index 001e65c0f66..db07c475866 100644 --- a/app/views/projects/_new_project_fields.html.haml +++ b/app/views/projects/_new_project_fields.html.haml @@ -60,5 +60,5 @@ .option-description Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository. -= f.submit 'Create project', class: "btn btn-create project-submit", tabindex: 4 += f.submit 'Create project', class: "btn btn-success project-submit", tabindex: 4 = link_to 'Cancel', dashboard_projects_path, class: 'btn btn-cancel' diff --git a/app/views/projects/_readme.html.haml b/app/views/projects/_readme.html.haml index 705338c083e..32624ac225b 100644 --- a/app/views/projects/_readme.html.haml +++ b/app/views/projects/_readme.html.haml @@ -20,4 +20,4 @@ distributed with computer software, forming part of its documentation. GitLab will render it here instead of this message. %p - = link_to "Add Readme", @project.add_readme_path, class: 'btn btn-new' + = link_to "Add Readme", @project.add_readme_path, class: 'btn btn-success' diff --git a/app/views/projects/blob/_new_dir.html.haml b/app/views/projects/blob/_new_dir.html.haml index 6f3a691518b..e9010dc63fc 100644 --- a/app/views/projects/blob/_new_dir.html.haml +++ b/app/views/projects/blob/_new_dir.html.haml @@ -15,7 +15,7 @@ = render 'shared/new_commit_form', placeholder: _("Add new directory") .form-actions - = submit_tag _("Create directory"), class: 'btn btn-create' + = submit_tag _("Create directory"), class: 'btn btn-success' = link_to "Cancel", '#', class: "btn btn-cancel", "data-dismiss" => "modal" = render 'shared/projects/edit_information' diff --git a/app/views/projects/blob/_upload.html.haml b/app/views/projects/blob/_upload.html.haml index 0a5c73c9037..d2b3c8ef96b 100644 --- a/app/views/projects/blob/_upload.html.haml +++ b/app/views/projects/blob/_upload.html.haml @@ -20,7 +20,7 @@ = render 'shared/new_commit_form', placeholder: placeholder .form-actions - = button_tag class: 'btn btn-create btn-upload-file', id: 'submit-all', type: 'button' do + = button_tag class: 'btn btn-success btn-upload-file', id: 'submit-all', type: 'button' do = icon('spin spinner', class: 'js-loading-icon hidden' ) = button_title = link_to _("Cancel"), '#', class: "btn btn-cancel", "data-dismiss" => "modal" diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml index d6568c9f64a..ca867961f6b 100644 --- a/app/views/projects/branches/index.html.haml +++ b/app/views/projects/branches/index.html.haml @@ -41,7 +41,7 @@ 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-create' do + = link_to new_project_branch_path(@project), class: 'btn btn-success' do = s_('Branches|New branch') - if can?(current_user, :admin_project, @project) diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml index 65b414c8af2..500536a5dbc 100644 --- a/app/views/projects/branches/new.html.haml +++ b/app/views/projects/branches/new.html.haml @@ -26,7 +26,7 @@ = render 'shared/ref_dropdown', dropdown_class: 'wide' .form-text.text-muted Existing branch name, tag, or commit SHA .form-actions - = button_tag 'Create branch', class: 'btn btn-create', tabindex: 3 + = button_tag 'Create branch', class: 'btn btn-success', tabindex: 3 = link_to 'Cancel', project_branches_path(@project), class: 'btn btn-cancel' -# haml-lint:disable InlineJavaScript %script#availableRefs{ type: "application/json" }= @project.repository.ref_names.to_json.html_safe diff --git a/app/views/projects/commit/_change.html.haml b/app/views/projects/commit/_change.html.haml index afd70ef5774..e71615dd1c5 100644 --- a/app/views/projects/commit/_change.html.haml +++ b/app/views/projects/commit/_change.html.haml @@ -33,7 +33,7 @@ - else = hidden_field_tag 'create_merge_request', 1, id: nil .form-actions - = submit_tag label, class: 'btn btn-create' + = submit_tag label, class: 'btn btn-success' = link_to _("Cancel"), '#', class: "btn btn-cancel", "data-dismiss" => "modal" = render 'shared/projects/edit_information' diff --git a/app/views/projects/compare/_form.html.haml b/app/views/projects/compare/_form.html.haml index 07112c98804..d24ee4a3251 100644 --- a/app/views/projects/compare/_form.html.haml +++ b/app/views/projects/compare/_form.html.haml @@ -22,7 +22,7 @@ .dropdown-toggle-text.str-truncated= params[:from] || _("Select branch/tag") = render 'shared/ref_dropdown' - = button_tag s_("CompareBranches|Compare"), class: "btn btn-create commits-compare-btn" + = button_tag s_("CompareBranches|Compare"), class: "btn btn-success commits-compare-btn" - if @merge_request.present? = link_to _("View open merge request"), project_merge_request_path(@project, @merge_request), class: 'prepend-left-10 btn' - elsif create_mr_button? diff --git a/app/views/projects/deploy_keys/_form.html.haml b/app/views/projects/deploy_keys/_form.html.haml index f8ab0c1ec54..568930595a2 100644 --- a/app/views/projects/deploy_keys/_form.html.haml +++ b/app/views/projects/deploy_keys/_form.html.haml @@ -21,4 +21,4 @@ Allow this key to push to repository as well? (Default only allows pull access.) .form-group.row - = f.submit "Add key", class: "btn-create btn" + = f.submit "Add key", class: "btn-success btn" diff --git a/app/views/projects/deploy_keys/edit.html.haml b/app/views/projects/deploy_keys/edit.html.haml index e009b6fef0e..3e7872ebc1c 100644 --- a/app/views/projects/deploy_keys/edit.html.haml +++ b/app/views/projects/deploy_keys/edit.html.haml @@ -6,5 +6,5 @@ = form_for [@project.namespace.becomes(Namespace), @project, @deploy_key], html: { class: 'js-requires-input' } do |f| = render partial: 'shared/deploy_keys/form', locals: { form: f, deploy_key: @deploy_key } .form-actions - = f.submit 'Save changes', class: 'btn-save btn' + = f.submit 'Save changes', class: 'btn-success btn' = link_to 'Cancel', project_settings_repository_path(@project), class: 'btn btn-cancel' diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml index acdde9e0f70..96ab582b050 100644 --- a/app/views/projects/edit.html.haml +++ b/app/views/projects/edit.html.haml @@ -59,7 +59,7 @@ - if @project.avatar? %hr = link_to _('Remove avatar'), project_avatar_path(@project), data: { confirm: _("Avatar will be removed. Are you sure?") }, method: :delete, class: "btn btn-danger btn-inverted" - = f.submit 'Save changes', class: "btn btn-success js-btn-save-general-project-settings" + = f.submit 'Save changes', class: "btn btn-success js-btn-success-general-project-settings" %section.settings.sharing-permissions.no-animate#js-shared-permissions{ class: ('expanded' if expanded) } .settings-header @@ -75,7 +75,7 @@ -# haml-lint:disable InlineJavaScript %script.js-project-permissions-form-data{ type: "application/json" }= project_permissions_panel_data_json(@project) .js-project-permissions-form - = f.submit 'Save changes', class: "btn btn-save" + = f.submit 'Save changes', class: "btn btn-success" = render_if_exists 'projects/issues_settings' @@ -93,7 +93,7 @@ = form_for [@project.namespace.becomes(Namespace), @project], remote: true, html: { multipart: true, class: "merge-request-settings-form" }, authenticity_token: true do |f| %input{ name: 'update_section', type: 'hidden', value: 'js-merge-request-settings' } = render 'projects/merge_request_settings', form: f - = f.submit 'Save changes', class: "btn btn-save qa-save-merge-request-changes" + = f.submit 'Save changes', class: "btn btn-success qa-save-merge-request-changes" = render_if_exists 'projects/service_desk_settings' diff --git a/app/views/projects/environments/_form.html.haml b/app/views/projects/environments/_form.html.haml index 0586dbdf0e2..f942b936037 100644 --- a/app/views/projects/environments/_form.html.haml +++ b/app/views/projects/environments/_form.html.haml @@ -18,5 +18,5 @@ = f.url_field :external_url, class: 'form-control' .form-actions - = f.submit 'Save', class: 'btn btn-save' + = f.submit 'Save', class: 'btn btn-success' = link_to 'Cancel', project_environments_path(@project), class: 'btn btn-cancel' diff --git a/app/views/projects/forks/index.html.haml b/app/views/projects/forks/index.html.haml index 57afc7ac9c3..b44ea89510b 100644 --- a/app/views/projects/forks/index.html.haml +++ b/app/views/projects/forks/index.html.haml @@ -30,11 +30,11 @@ - if current_user && can?(current_user, :fork_project, @project) - if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2 - = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn btn-new' do + = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn btn-success' do = sprite_icon('fork', size: 12) %span Fork - else - = link_to new_project_fork_path(@project), title: "Fork project", class: 'btn btn-new' do + = link_to new_project_fork_path(@project), title: "Fork project", class: 'btn btn-success' do = sprite_icon('fork', size: 12) %span Fork diff --git a/app/views/projects/hooks/_index.html.haml b/app/views/projects/hooks/_index.html.haml index 5990582fd55..0ab7863b77c 100644 --- a/app/views/projects/hooks/_index.html.haml +++ b/app/views/projects/hooks/_index.html.haml @@ -9,7 +9,7 @@ .col-lg-8.append-bottom-default = form_for @hook, as: :hook, url: polymorphic_path([@project.namespace.becomes(Namespace), @project, :hooks]) do |f| = render partial: 'shared/web_hooks/form', locals: { form: f, hook: @hook } - = f.submit 'Add webhook', class: 'btn btn-create' + = f.submit 'Add webhook', class: 'btn btn-success' %hr %h5.prepend-top-default diff --git a/app/views/projects/hooks/edit.html.haml b/app/views/projects/hooks/edit.html.haml index c31aef60453..57311284e11 100644 --- a/app/views/projects/hooks/edit.html.haml +++ b/app/views/projects/hooks/edit.html.haml @@ -11,7 +11,7 @@ = form_for [@project.namespace.becomes(Namespace), @project, @hook], as: :hook, url: project_hook_path(@project, @hook) do |f| = render partial: 'shared/web_hooks/form', locals: { form: f, hook: @hook } - = f.submit 'Save changes', class: 'btn btn-create' + = f.submit 'Save changes', class: 'btn btn-success' = render 'shared/web_hooks/test_button', triggers: ProjectHook.triggers, hook: @hook = link_to 'Remove', project_hook_path(@project, @hook), method: :delete, class: 'btn btn-remove float-right', data: { confirm: 'Are you sure?' } diff --git a/app/views/projects/imports/new.html.haml b/app/views/projects/imports/new.html.haml index 8ce822c43b7..1c50cfbde85 100644 --- a/app/views/projects/imports/new.html.haml +++ b/app/views/projects/imports/new.html.haml @@ -16,4 +16,4 @@ = render "shared/import_form", f: f .form-actions - = f.submit 'Start import', class: "btn btn-create", tabindex: 4 + = f.submit 'Start import', class: "btn btn-success", tabindex: 4 diff --git a/app/views/projects/issues/_nav_btns.html.haml b/app/views/projects/issues/_nav_btns.html.haml index 0dd2d2e6c5d..e4a0d4b8479 100644 --- a/app/views/projects/issues/_nav_btns.html.haml +++ b/app/views/projects/issues/_nav_btns.html.haml @@ -6,6 +6,6 @@ = link_to "New issue", new_project_issue_path(@project, issue: { assignee_id: finder.assignee.try(:id), milestone_id: finder.milestones.first.try(:id) }), - class: "btn btn-new", + class: "btn btn-success", title: "New issue", id: "new_issue_link" diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index b81d1a188f0..c39fd0063be 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -55,7 +55,7 @@ - if can_report_spam = link_to 'Submit as spam', mark_as_spam_project_issue_path(@project, @issue), method: :post, class: 'd-none d-sm-none d-md-block btn btn-grouped btn-spam', title: 'Submit as spam' - if can_create_issue - = link_to new_project_issue_path(@project), class: 'd-none d-sm-none d-md-block btn btn-grouped new-issue-link btn-new btn-inverted', title: 'New issue', id: 'new_issue_link' do + = link_to new_project_issue_path(@project), class: 'd-none d-sm-none d-md-block btn btn-grouped new-issue-link btn-success btn-inverted', title: 'New issue', id: 'new_issue_link' do New issue .issue-details.issuable-details diff --git a/app/views/projects/jobs/_header.html.haml b/app/views/projects/jobs/_header.html.haml index b83e8dddccb..e7245622b80 100644 --- a/app/views/projects/jobs/_header.html.haml +++ b/app/views/projects/jobs/_header.html.haml @@ -24,7 +24,7 @@ - if show_controls .nav-controls - if can?(current_user, :create_issue, @project) && @build.failed? - = link_to "New issue", new_project_issue_path(@project, issue: build_failed_issue_options), class: 'btn btn-new btn-inverted' + = link_to "New issue", new_project_issue_path(@project, issue: build_failed_issue_options), class: 'btn btn-success btn-inverted' - if can?(current_user, :update_build, @build) && @build.retryable? = link_to "Retry job", retry_project_job_path(@project, @build), class: 'btn btn-inverted-secondary', method: :post %button.btn.btn-default.float-right.d-block.d-sm-none.d-md-none.build-gutter-toggle.js-sidebar-build-toggle{ role: "button", type: "button" } diff --git a/app/views/projects/jobs/show.html.haml b/app/views/projects/jobs/show.html.haml index cf8d42976f8..5321bc46e73 100644 --- a/app/views/projects/jobs/show.html.haml +++ b/app/views/projects/jobs/show.html.haml @@ -3,6 +3,9 @@ - breadcrumb_title "##{@build.id}" - page_title "#{@build.name} (##{@build.id})", "Jobs" +- content_for :page_specific_javascripts do + = stylesheet_link_tag 'page_bundles/xterm' + %div{ class: container_class } .build-page.js-build-page #js-build-header-vue diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml index 1bfd8a85f0f..683dda4f166 100644 --- a/app/views/projects/labels/index.html.haml +++ b/app/views/projects/labels/index.html.haml @@ -6,7 +6,7 @@ - if can_admin_label - content_for(:header_content) do .nav-controls - = link_to _('New label'), new_project_label_path(@project), class: "btn btn-new" + = link_to _('New label'), new_project_label_path(@project), class: "btn btn-success" - if @labels.exists? || @prioritized_labels.exists? || search.present? #promote-label-modal diff --git a/app/views/projects/mattermosts/_team_selection.html.haml b/app/views/projects/mattermosts/_team_selection.html.haml index 37c09f12f63..d0a7f89df31 100644 --- a/app/views/projects/mattermosts/_team_selection.html.haml +++ b/app/views/projects/mattermosts/_team_selection.html.haml @@ -43,4 +43,4 @@ .clearfix .float-right = link_to 'Cancel', edit_project_service_path(@project, @service), class: 'btn btn-lg' - = f.submit 'Install', class: 'btn btn-save btn-lg' + = f.submit 'Install', class: 'btn btn-success btn-lg' diff --git a/app/views/projects/merge_requests/_nav_btns.html.haml b/app/views/projects/merge_requests/_nav_btns.html.haml index e73dab8ad4a..b7498216334 100644 --- a/app/views/projects/merge_requests/_nav_btns.html.haml +++ b/app/views/projects/merge_requests/_nav_btns.html.haml @@ -1,5 +1,5 @@ - if @can_bulk_update = button_tag "Edit merge requests", class: "btn append-right-10 js-bulk-update-toggle" - if merge_project - = link_to new_merge_request_path, class: "btn btn-new", title: "New merge request" do + = link_to new_merge_request_path, class: "btn btn-success", title: "New merge request" do New merge request diff --git a/app/views/projects/merge_requests/creations/_new_compare.html.haml b/app/views/projects/merge_requests/creations/_new_compare.html.haml index afa7eb06cb4..1fd71a38472 100644 --- a/app/views/projects/merge_requests/creations/_new_compare.html.haml +++ b/app/views/projects/merge_requests/creations/_new_compare.html.haml @@ -61,4 +61,4 @@ - if @merge_request.errors.any? = form_errors(@merge_request) - = f.submit 'Compare branches and continue', class: "btn btn-new mr-compare-btn" + = f.submit 'Compare branches and continue', class: "btn btn-success mr-compare-btn" diff --git a/app/views/projects/merge_requests/diffs/_diffs.html.haml b/app/views/projects/merge_requests/diffs/_diffs.html.haml index bf3df0abf86..9ebd91dea0b 100644 --- a/app/views/projects/merge_requests/diffs/_diffs.html.haml +++ b/app/views/projects/merge_requests/diffs/_diffs.html.haml @@ -14,7 +14,7 @@ %span.ref-name= @merge_request.source_branch and %span.ref-name= @merge_request.target_branch - .text-center= link_to 'Create commit', project_new_blob_path(@project, @merge_request.source_branch), class: 'btn btn-save' + .text-center= link_to 'Create commit', project_new_blob_path(@project, @merge_request.source_branch), class: 'btn btn-success' - else - diff_viewable = @merge_request_diff ? @merge_request_diff.viewable? : true - if diff_viewable diff --git a/app/views/projects/milestones/_form.html.haml b/app/views/projects/milestones/_form.html.haml index 28f0a167128..ebd3229e42b 100644 --- a/app/views/projects/milestones/_form.html.haml +++ b/app/views/projects/milestones/_form.html.haml @@ -20,8 +20,8 @@ .form-actions - if @milestone.new_record? - = f.submit 'Create milestone', class: "btn-create btn qa-milestone-create-button" + = f.submit 'Create milestone', class: "btn-success btn qa-milestone-create-button" = link_to "Cancel", project_milestones_path(@project), class: "btn btn-cancel" - else - = f.submit 'Save changes', class: "btn-save btn" + = f.submit 'Save changes', class: "btn-success btn" = link_to "Cancel", project_milestone_path(@project, @milestone), class: "btn btn-cancel" diff --git a/app/views/projects/milestones/index.html.haml b/app/views/projects/milestones/index.html.haml index 26d2ea8447b..57f3c640696 100644 --- a/app/views/projects/milestones/index.html.haml +++ b/app/views/projects/milestones/index.html.haml @@ -8,7 +8,7 @@ .nav-controls = render 'shared/milestones_sort_dropdown' - if can?(current_user, :admin_milestone, @project) - = link_to new_project_milestone_path(@project), class: "btn btn-new qa-new-project-milestone", title: 'New milestone' do + = link_to new_project_milestone_path(@project), class: "btn btn-success qa-new-project-milestone", title: 'New milestone' do New milestone .milestones diff --git a/app/views/projects/mirrors/_mirror_repos.html.haml b/app/views/projects/mirrors/_mirror_repos.html.haml index c6764c7607a..d523df1cd90 100644 --- a/app/views/projects/mirrors/_mirror_repos.html.haml +++ b/app/views/projects/mirrors/_mirror_repos.html.haml @@ -32,7 +32,7 @@ = link_to icon('question-circle'), help_page_path('user/project/protected_branches') .panel-footer - = f.submit _('Mirror repository'), class: 'btn btn-create', name: :update_remote_mirror + = f.submit _('Mirror repository'), class: 'btn btn-success', name: :update_remote_mirror .panel.panel-default .table-responsive diff --git a/app/views/projects/pages/show.html.haml b/app/views/projects/pages/show.html.haml index 7e1a3b9bea6..88ab486a248 100644 --- a/app/views/projects/pages/show.html.haml +++ b/app/views/projects/pages/show.html.haml @@ -4,7 +4,7 @@ Pages - if can?(current_user, :update_pages, @project) && (Gitlab.config.pages.external_http || Gitlab.config.pages.external_https) - = link_to new_project_pages_domain_path(@project), class: 'btn btn-new float-right', title: 'New Domain' do + = link_to new_project_pages_domain_path(@project), class: 'btn btn-success float-right', title: 'New Domain' do New Domain %p.light diff --git a/app/views/projects/pages_domains/edit.html.haml b/app/views/projects/pages_domains/edit.html.haml index ee70de22f13..342b1482df7 100644 --- a/app/views/projects/pages_domains/edit.html.haml +++ b/app/views/projects/pages_domains/edit.html.haml @@ -8,4 +8,4 @@ = form_for [@project.namespace.becomes(Namespace), @project, @domain], html: { class: 'fieldset-form' } do |f| = render 'form', { f: f } .form-actions - = f.submit 'Save Changes', class: "btn btn-save" + = f.submit 'Save Changes', class: "btn btn-success" diff --git a/app/views/projects/pages_domains/new.html.haml b/app/views/projects/pages_domains/new.html.haml index 376ce3f68aa..94ad1470052 100644 --- a/app/views/projects/pages_domains/new.html.haml +++ b/app/views/projects/pages_domains/new.html.haml @@ -7,6 +7,6 @@ = form_for [@project.namespace.becomes(Namespace), @project, @domain], html: { class: 'fieldset-form' } do |f| = render 'form', { f: f } .form-actions - = f.submit 'Create New Domain', class: "btn btn-save" + = f.submit 'Create New Domain', class: "btn btn-success" .float-right = link_to _('Cancel'), project_pages_path(@project), class: 'btn btn-cancel' diff --git a/app/views/projects/pipeline_schedules/_form.html.haml b/app/views/projects/pipeline_schedules/_form.html.haml index 9a981d53ab6..259979417e0 100644 --- a/app/views/projects/pipeline_schedules/_form.html.haml +++ b/app/views/projects/pipeline_schedules/_form.html.haml @@ -39,5 +39,5 @@ = f.check_box :active, required: false, value: @schedule.active? = _('Active') .footer-block.row-content-block - = f.submit _('Save pipeline schedule'), class: 'btn btn-create', tabindex: 3 + = f.submit _('Save pipeline schedule'), class: 'btn btn-success', tabindex: 3 = link_to _('Cancel'), pipeline_schedules_path(@project), class: 'btn btn-cancel' diff --git a/app/views/projects/pipeline_schedules/index.html.haml b/app/views/projects/pipeline_schedules/index.html.haml index 3677666070e..0580c15ad15 100644 --- a/app/views/projects/pipeline_schedules/index.html.haml +++ b/app/views/projects/pipeline_schedules/index.html.haml @@ -11,7 +11,7 @@ - if can?(current_user, :create_pipeline_schedule, @project) .nav-controls - = link_to new_project_pipeline_schedule_path(@project), class: 'btn btn-create' do + = link_to new_project_pipeline_schedule_path(@project), class: 'btn btn-success' do %span= _('New schedule') - if @schedules.present? diff --git a/app/views/projects/project_members/_new_project_group.html.haml b/app/views/projects/project_members/_new_project_group.html.haml index 7de24ec5ad2..74570769117 100644 --- a/app/views/projects/project_members/_new_project_group.html.haml +++ b/app/views/projects/project_members/_new_project_group.html.haml @@ -17,4 +17,4 @@ .clearable-input = text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date-groups', placeholder: _('Expiration date'), id: 'expires_at_groups' %i.clear-icon.js-clear-input - = submit_tag _("Invite"), class: "btn btn-create" + = submit_tag _("Invite"), class: "btn btn-success" diff --git a/app/views/projects/project_members/_new_project_member.html.haml b/app/views/projects/project_members/_new_project_member.html.haml index 6272687be1c..517fd249f6e 100644 --- a/app/views/projects/project_members/_new_project_member.html.haml +++ b/app/views/projects/project_members/_new_project_member.html.haml @@ -17,5 +17,5 @@ = label_tag :expires_at, 'Access expiration date', class: 'label-bold' = text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date', placeholder: 'Expiration date' %i.clear-icon.js-clear-input - = f.submit "Add to project", class: "btn btn-create" + = f.submit "Add to project", class: "btn btn-success" = link_to "Import", import_project_project_members_path(@project), class: "btn btn-default", title: "Import members from another project" diff --git a/app/views/projects/project_members/import.html.haml b/app/views/projects/project_members/import.html.haml index 6a52e72bfd8..8b93e81cd31 100644 --- a/app/views/projects/project_members/import.html.haml +++ b/app/views/projects/project_members/import.html.haml @@ -11,5 +11,5 @@ .col-sm-10= select_tag(:source_project_id, options_from_collection_for_select(@projects, :id, :name_with_namespace), prompt: "Select project", class: "select2 lg", required: true) .form-actions - = button_tag 'Import project members', class: "btn btn-create" + = button_tag 'Import project members', class: "btn btn-success" = link_to "Cancel", project_project_members_path(@project), class: "btn btn-cancel" diff --git a/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml b/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml index df2dcf19ed4..c3b8f2f8964 100644 --- a/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml +++ b/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml @@ -30,4 +30,4 @@ = yield :push_access_levels .card-footer - = f.submit 'Protect', class: 'btn-create btn', disabled: true + = f.submit 'Protect', class: 'btn-success btn', disabled: true diff --git a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml index f98781b77f4..b274c73d035 100644 --- a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml +++ b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml @@ -26,4 +26,4 @@ = yield :create_access_levels .card-footer - = f.submit 'Protect', class: 'btn-create btn', disabled: true + = f.submit 'Protect', class: 'btn-success btn', disabled: true diff --git a/app/views/projects/releases/edit.html.haml b/app/views/projects/releases/edit.html.haml index 8093cc2c2d7..52c6c7ec424 100644 --- a/app/views/projects/releases/edit.html.haml +++ b/app/views/projects/releases/edit.html.haml @@ -19,5 +19,5 @@ = render 'shared/notes/hints' .error-alert .prepend-top-default - = f.submit 'Save changes', class: 'btn btn-save' + = 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/runners/_group_runners.html.haml b/app/views/projects/runners/_group_runners.html.haml index 86de71c732b..a6c16c70313 100644 --- a/app/views/projects/runners/_group_runners.html.haml +++ b/app/views/projects/runners/_group_runners.html.haml @@ -28,7 +28,7 @@ - group_link = link_to _('Group CI/CD settings'), group_settings_ci_cd_path(@project.group) = _('Group maintainers can register group runners in the %{link}').html_safe % { link: group_link } - else - = _('Ask your group maintainer to setup a group Runner.') + = _('Ask your group maintainer to set up a group Runner.') - else %h4.underlined-title diff --git a/app/views/projects/settings/ci_cd/_form.html.haml b/app/views/projects/settings/ci_cd/_form.html.haml index 9134257b631..ae923d8e6dc 100644 --- a/app/views/projects/settings/ci_cd/_form.html.haml +++ b/app/views/projects/settings/ci_cd/_form.html.haml @@ -121,7 +121,7 @@ go test -cover (Go) %code coverage: \d+.\d+% of statements - = f.submit _('Save changes'), class: "btn btn-save" + = f.submit _('Save changes'), class: "btn btn-success" %hr diff --git a/app/views/projects/snippets/_actions.html.haml b/app/views/projects/snippets/_actions.html.haml index 4a3aa3dc626..ea963510a68 100644 --- a/app/views/projects/snippets/_actions.html.haml +++ b/app/views/projects/snippets/_actions.html.haml @@ -8,7 +8,7 @@ = link_to project_snippet_path(@project, @snippet), method: :delete, data: { confirm: _("Are you sure?") }, class: "btn btn-grouped btn-inverted btn-remove", title: _('Delete Snippet') do = _('Delete') - if can?(current_user, :create_project_snippet, @project) - = link_to new_project_snippet_path(@project), class: 'btn btn-grouped btn-inverted btn-create', title: _("New snippet") do + = link_to new_project_snippet_path(@project), class: 'btn btn-grouped btn-inverted btn-success', title: _("New snippet") do = _('New snippet') - if @snippet.submittable_as_spam_by?(current_user) = link_to _('Submit as spam'), mark_as_spam_project_snippet_path(@project, @snippet), method: :post, class: 'btn btn-grouped btn-spam', title: _('Submit as spam') diff --git a/app/views/projects/snippets/index.html.haml b/app/views/projects/snippets/index.html.haml index 1c4c73dc776..a4974d89c1a 100644 --- a/app/views/projects/snippets/index.html.haml +++ b/app/views/projects/snippets/index.html.haml @@ -7,6 +7,6 @@ .nav-controls - if can?(current_user, :create_project_snippet, @project) - = link_to _("New snippet"), new_project_snippet_path(@project), class: "btn btn-new", title: _("New snippet") + = link_to _("New snippet"), new_project_snippet_path(@project), class: "btn btn-success", title: _("New snippet") = render 'snippets/snippets' diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml index 20b4705521c..37535370940 100644 --- a/app/views/projects/tags/index.html.haml +++ b/app/views/projects/tags/index.html.haml @@ -25,7 +25,7 @@ %li = link_to title, filter_tags_path(sort: value), class: ("is-active" if @sort == value) - if can?(current_user, :push_code, @project) - = link_to new_project_tag_path(@project), class: 'btn btn-create new-tag-btn' do + = link_to new_project_tag_path(@project), class: 'btn btn-success new-tag-btn' do = s_('TagsPage|New tag') = link_to project_tags_path(@project, rss_url_options), title: _("Tags feed"), class: 'btn rss-btn has-tooltip' do = icon("rss") diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml index da822ac5675..24724394259 100644 --- a/app/views/projects/tags/new.html.haml +++ b/app/views/projects/tags/new.html.haml @@ -41,7 +41,7 @@ .form-text.text-muted = s_('TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page.') .form-actions - = button_tag s_('TagsPage|Create tag'), class: 'btn btn-create' + = button_tag s_('TagsPage|Create tag'), class: 'btn btn-success' = link_to s_('TagsPage|Cancel'), project_tags_path(@project), class: 'btn btn-cancel' -# haml-lint:disable InlineJavaScript %script#availableRefs{ type: "application/json" }= @project.repository.ref_names.to_json.html_safe diff --git a/app/views/projects/triggers/_form.html.haml b/app/views/projects/triggers/_form.html.haml index 1a5fc56f429..a9abfac239c 100644 --- a/app/views/projects/triggers/_form.html.haml +++ b/app/views/projects/triggers/_form.html.haml @@ -8,4 +8,4 @@ .form-group = f.label :key, "Description", class: "label-bold" = f.text_field :description, class: "form-control", required: true, title: 'Trigger description is required.', placeholder: "Trigger description" - = f.submit btn_text, class: "btn btn-save" + = f.submit btn_text, class: "btn btn-success" diff --git a/app/views/projects/update.js.haml b/app/views/projects/update.js.haml index e8681da6528..70f1bf8ef46 100644 --- a/app/views/projects/update.js.haml +++ b/app/views/projects/update.js.haml @@ -7,4 +7,4 @@ $(".project-edit-errors").html("#{escape_javascript(render('errors'))}"); $('.save-project-loader').hide(); $('.project-edit-container').show(); - $('.edit-project .js-btn-save-general-project-settings').enable(); + $('.edit-project .js-btn-success-general-project-settings').enable(); diff --git a/app/views/projects/wikis/_form.html.haml b/app/views/projects/wikis/_form.html.haml index 35872d70db4..7d8826e540c 100644 --- a/app/views/projects/wikis/_form.html.haml +++ b/app/views/projects/wikis/_form.html.haml @@ -51,10 +51,10 @@ .form-actions - if @page && @page.persisted? - = f.submit _("Save changes"), class: 'btn-save btn' + = f.submit _("Save changes"), class: 'btn-success btn' .float-right = link_to _("Cancel"), project_wiki_path(@project, @page), class: 'btn btn-cancel btn-grouped' - else - = f.submit s_("Wiki|Create page"), class: 'btn-create btn' + = f.submit s_("Wiki|Create page"), class: 'btn-success btn' .float-right = link_to _("Cancel"), project_wiki_path(@project, :home), class: 'btn btn-cancel' diff --git a/app/views/projects/wikis/_main_links.html.haml b/app/views/projects/wikis/_main_links.html.haml index 8d91f411f89..643b51e01d1 100644 --- a/app/views/projects/wikis/_main_links.html.haml +++ b/app/views/projects/wikis/_main_links.html.haml @@ -1,6 +1,6 @@ - if (@page && @page.persisted?) - if can?(current_user, :create_wiki, @project) - = link_to '#modal-new-wiki', class: "add-new-wiki btn btn-new", "data-toggle" => "modal" do + = link_to '#modal-new-wiki', class: "add-new-wiki btn btn-success", "data-toggle" => "modal" do = s_("Wiki|New page") = link_to project_wiki_history_path(@project, @page), class: "btn" do = s_("Wiki|Page history") diff --git a/app/views/projects/wikis/_new.html.haml b/app/views/projects/wikis/_new.html.haml index 38382aae67c..dc12e368b35 100644 --- a/app/views/projects/wikis/_new.html.haml +++ b/app/views/projects/wikis/_new.html.haml @@ -15,4 +15,4 @@ = icon('lightbulb-o') = s_("WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories.") .form-actions - = button_tag s_("Wiki|Create page"), class: "build-new-wiki btn btn-create" + = button_tag s_("Wiki|Create page"), class: "build-new-wiki btn btn-success" diff --git a/app/views/projects/wikis/edit.html.haml b/app/views/projects/wikis/edit.html.haml index e12b8f2858c..80aa1500d53 100644 --- a/app/views/projects/wikis/edit.html.haml +++ b/app/views/projects/wikis/edit.html.haml @@ -22,7 +22,7 @@ .nav-controls - if can?(current_user, :create_wiki, @project) - = link_to '#modal-new-wiki', class: "add-new-wiki btn btn-new", "data-toggle" => "modal" do + = link_to '#modal-new-wiki', class: "add-new-wiki btn btn-success", "data-toggle" => "modal" do = s_("Wiki|New page") - if @page.persisted? = link_to project_wiki_history_path(@project, @page), class: "btn" do diff --git a/app/views/shared/_new_project_item_select.html.haml b/app/views/shared/_new_project_item_select.html.haml index d38d161047b..9bc67a7c715 100644 --- a/app/views/shared/_new_project_item_select.html.haml +++ b/app/views/shared/_new_project_item_select.html.haml @@ -1,7 +1,7 @@ - if any_projects?(@projects) .project-item-select-holder.btn-group - %a.btn.btn-new.new-project-item-link.qa-new-project-item-link{ href: '', data: { label: local_assigns[:label], type: local_assigns[:type] } } + %a.btn.btn-success.new-project-item-link.qa-new-project-item-link{ href: '', data: { label: local_assigns[:label], type: local_assigns[:type] } } = icon('spinner spin') = project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups], order_by: 'last_activity_at', relative_path: local_assigns[:path] }, with_feature_enabled: local_assigns[:with_feature_enabled] - %button.btn.btn-new.new-project-item-select-button.qa-new-project-item-select-button + %button.btn.btn-success.new-project-item-select-button.qa-new-project-item-select-button = icon('caret-down') diff --git a/app/views/shared/_personal_access_tokens_form.html.haml b/app/views/shared/_personal_access_tokens_form.html.haml index 58d310fac16..f4df7bdcd83 100644 --- a/app/views/shared/_personal_access_tokens_form.html.haml +++ b/app/views/shared/_personal_access_tokens_form.html.haml @@ -26,4 +26,4 @@ = render 'shared/tokens/scopes_form', prefix: 'personal_access_token', token: token, scopes: scopes .prepend-top-default - = f.submit "Create #{type} token", class: "btn btn-create" + = f.submit "Create #{type} token", class: "btn btn-success" diff --git a/app/views/shared/_recaptcha_form.html.haml b/app/views/shared/_recaptcha_form.html.haml index a0ba1afc284..10f358402c1 100644 --- a/app/views/shared/_recaptcha_form.html.haml +++ b/app/views/shared/_recaptcha_form.html.haml @@ -17,4 +17,4 @@ - if has_submit .row-content-block.footer-block - = f.submit "Submit #{humanized_resource_name}", class: 'btn btn-create' + = f.submit "Submit #{humanized_resource_name}", class: 'btn btn-success' diff --git a/app/views/shared/empty_states/_labels.html.haml b/app/views/shared/empty_states/_labels.html.haml index e8749ee3956..b629ceafeb3 100644 --- a/app/views/shared/empty_states/_labels.html.haml +++ b/app/views/shared/empty_states/_labels.html.haml @@ -7,5 +7,5 @@ %h4= _("Labels can be applied to issues and merge requests to categorize them.") %p= _("You can also star a label to make it a priority label.") - if can?(current_user, :admin_label, @project) - = link_to _('New label'), new_project_label_path(@project), class: 'btn btn-new', title: _('New label'), id: 'new_label_link' + = link_to _('New label'), new_project_label_path(@project), class: 'btn btn-success', title: _('New label'), id: 'new_label_link' = link_to _('Generate a default set of labels'), generate_project_labels_path(@project), method: :post, class: 'btn btn-success btn-inverted', title: _('Generate a default set of labels'), id: 'generate_labels_link' diff --git a/app/views/shared/empty_states/_merge_requests.html.haml b/app/views/shared/empty_states/_merge_requests.html.haml index 186139f3526..421a1b2415b 100644 --- a/app/views/shared/empty_states/_merge_requests.html.haml +++ b/app/views/shared/empty_states/_merge_requests.html.haml @@ -17,7 +17,7 @@ - if project_select_button = render 'shared/new_project_item_select', path: 'merge_requests/new', label: _('New merge request'), type: :merge_requests, with_feature_enabled: 'merge_requests' - else - = link_to _('New merge request'), button_path, class: 'btn btn-new', title: _('New merge request'), id: 'new_merge_request_link' + = link_to _('New merge request'), button_path, class: 'btn btn-success', title: _('New merge request'), id: 'new_merge_request_link' - else %h4.text-center = _("There are no merge requests to show") diff --git a/app/views/shared/empty_states/_wikis.html.haml b/app/views/shared/empty_states/_wikis.html.haml index f1a41074c28..5351c9ce6a4 100644 --- a/app/views/shared/empty_states/_wikis.html.haml +++ b/app/views/shared/empty_states/_wikis.html.haml @@ -2,7 +2,7 @@ - if can?(current_user, :create_wiki, @project) - create_path = project_wiki_path(@project, params[:id], { view: 'create' }) - - create_link = link_to s_('WikiEmpty|Create your first page'), create_path, class: 'btn btn-new', title: s_('WikiEmpty|Create your first page') + - create_link = link_to s_('WikiEmpty|Create your first page'), create_path, class: 'btn btn-success', title: s_('WikiEmpty|Create your first page') = render layout: layout_path, locals: { image_path: 'illustrations/wiki_login_empty.svg' } do %h4 @@ -13,7 +13,7 @@ - elsif can?(current_user, :read_issue, @project) - issues_link = link_to s_('WikiEmptyIssueMessage|issue tracker'), project_issues_path(@project) - - new_issue_link = link_to s_('WikiEmpty|Suggest wiki improvement'), new_project_issue_path(@project), class: 'btn btn-new', title: s_('WikiEmptyIssueMessage|Suggest wiki improvement') + - new_issue_link = link_to s_('WikiEmpty|Suggest wiki improvement'), new_project_issue_path(@project), class: 'btn btn-success', title: s_('WikiEmptyIssueMessage|Suggest wiki improvement') = render layout: layout_path, locals: { image_path: 'illustrations/wiki_logout_empty.svg' } do %h4 diff --git a/app/views/shared/issuable/_board_create_list_dropdown.html.haml b/app/views/shared/issuable/_board_create_list_dropdown.html.haml index 23b2e1b91e5..4597d9439fa 100644 --- a/app/views/shared/issuable/_board_create_list_dropdown.html.haml +++ b/app/views/shared/issuable/_board_create_list_dropdown.html.haml @@ -1,5 +1,5 @@ .dropdown.prepend-left-10#js-add-list - %button.btn.btn-create.btn-inverted.js-new-board-list{ type: "button", data: board_list_data } + %button.btn.btn-success.btn-inverted.js-new-board-list{ type: "button", data: board_list_data } Add list .dropdown-menu.dropdown-menu-paging.dropdown-menu-right.dropdown-menu-issues-board-new.dropdown-menu-selectable.js-tab-container-labels = render partial: "shared/issuable/label_page_default", locals: { show_footer: true, show_create: true, show_boards_content: true, title: "Add list" } diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml index b49e47a7266..5b28a43a361 100644 --- a/app/views/shared/issuable/_form.html.haml +++ b/app/views/shared/issuable/_form.html.haml @@ -69,9 +69,9 @@ %span.append-right-10 - if issuable.new_record? - = form.submit "Submit #{issuable.class.model_name.human.downcase}", class: 'btn btn-create qa-issuable-create-button' + = form.submit "Submit #{issuable.class.model_name.human.downcase}", class: 'btn btn-success qa-issuable-create-button' - else - = form.submit 'Save changes', class: 'btn btn-save' + = form.submit 'Save changes', class: 'btn btn-success' - if !issuable.persisted? && !issuable.project.empty_repo? && (guide_url = issuable.project.present.contribution_guide_path) .inline.prepend-top-10 diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml index 0ca35ea1298..32b609eed0d 100644 --- a/app/views/shared/issuable/_sidebar.html.haml +++ b/app/views/shared/issuable/_sidebar.html.haml @@ -159,7 +159,7 @@ = dropdown_content = dropdown_loading = dropdown_footer add_content_class: true do - %button.btn.btn-new.sidebar-move-issue-confirmation-button.js-move-issue-confirmation-button{ disabled: true } + %button.btn.btn-success.sidebar-move-issue-confirmation-button.js-move-issue-confirmation-button{ disabled: true } = _('Move') = icon('spinner spin', class: 'sidebar-move-issue-confirmation-loading-icon') diff --git a/app/views/shared/labels/_form.html.haml b/app/views/shared/labels/_form.html.haml index 2bf5efae1e6..335c34a4632 100644 --- a/app/views/shared/labels/_form.html.haml +++ b/app/views/shared/labels/_form.html.haml @@ -28,7 +28,7 @@ .form-actions - if @label.persisted? - = f.submit 'Save changes', class: 'btn btn-save js-save-button' + = f.submit 'Save changes', class: 'btn btn-success js-save-button' - else - = f.submit 'Create label', class: 'btn btn-create js-save-button' + = f.submit 'Create label', class: 'btn btn-success js-save-button' = link_to 'Cancel', back_path, class: 'btn btn-cancel' diff --git a/app/views/shared/notes/_comment_button.html.haml b/app/views/shared/notes/_comment_button.html.haml index ed336df4e9d..0674c822d63 100644 --- a/app/views/shared/notes/_comment_button.html.haml +++ b/app/views/shared/notes/_comment_button.html.haml @@ -1,7 +1,7 @@ - noteable_name = @note.noteable.human_class_name .float-left.btn-group.append-right-10.droplab-dropdown.comment-type-dropdown.js-comment-type-dropdown - %input.btn.btn-nr.btn-create.comment-btn.js-comment-button.js-comment-submit-button{ type: 'submit', value: 'Comment' } + %input.btn.btn-nr.btn-success.comment-btn.js-comment-button.js-comment-submit-button{ type: 'submit', value: 'Comment' } - if @note.can_be_discussion_note? = button_tag type: 'button', class: 'btn btn-nr dropdown-toggle comment-btn js-note-new-discussion js-disable-on-submit', data: { 'dropdown-trigger' => '#resolvable-comment-menu' }, 'aria-label' => 'Open comment type dropdown' do diff --git a/app/views/shared/notes/_edit_form.html.haml b/app/views/shared/notes/_edit_form.html.haml index 71a5b94e958..fec966069b9 100644 --- a/app/views/shared/notes/_edit_form.html.haml +++ b/app/views/shared/notes/_edit_form.html.haml @@ -9,6 +9,6 @@ .note-form-actions.clearfix .settings-message.note-edit-warning.js-finish-edit-warning Finish editing this message first! - = submit_tag 'Save comment', class: 'btn btn-nr btn-save js-comment-save-button' + = submit_tag 'Save comment', class: 'btn btn-nr btn-success js-comment-save-button' %button.btn.btn-nr.btn-cancel.note-edit-cancel{ type: 'button' } Cancel diff --git a/app/views/shared/runners/_form.html.haml b/app/views/shared/runners/_form.html.haml index fa93307be31..daf08d9bb2c 100644 --- a/app/views/shared/runners/_form.html.haml +++ b/app/views/shared/runners/_form.html.haml @@ -51,6 +51,6 @@ = _('Tags') .col-sm-10 = f.text_field :tag_list, value: runner.tag_list.sort.join(', '), class: 'form-control' - .form-text.text-muted= _('You can setup jobs to only use Runners with specific tags. Separate tags with commas.') + .form-text.text-muted= _('You can set up jobs to only use Runners with specific tags. Separate tags with commas.') .form-actions = f.submit _('Save changes'), class: 'btn btn-success' diff --git a/app/views/shared/runners/_runner_description.html.haml b/app/views/shared/runners/_runner_description.html.haml index da5c032add5..5935750ca06 100644 --- a/app/views/shared/runners/_runner_description.html.haml +++ b/app/views/shared/runners/_runner_description.html.haml @@ -1,6 +1,6 @@ .light.prepend-top-default %p - = _("A 'Runner' is a process which runs a job. You can setup as many Runners as you need.") + = _("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, and even on your local machine.') diff --git a/app/views/shared/snippets/_form.html.haml b/app/views/shared/snippets/_form.html.haml index 5e5c050d5c3..1b66d3acd40 100644 --- a/app/views/shared/snippets/_form.html.haml +++ b/app/views/shared/snippets/_form.html.haml @@ -32,9 +32,9 @@ .form-actions - if @snippet.new_record? - = f.submit 'Create snippet', class: "btn-create btn" + = f.submit 'Create snippet', class: "btn-success btn" - else - = f.submit 'Save changes', class: "btn-save btn" + = f.submit 'Save changes', class: "btn-success btn" - if @snippet.project_id = link_to "Cancel", project_snippets_path(@project), class: "btn btn-cancel" diff --git a/app/views/snippets/_actions.html.haml b/app/views/snippets/_actions.html.haml index ae69d0d07c7..0ce13ee7a53 100644 --- a/app/views/snippets/_actions.html.haml +++ b/app/views/snippets/_actions.html.haml @@ -7,7 +7,7 @@ - if can?(current_user, :admin_personal_snippet, @snippet) = link_to snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-inverted btn-remove", title: 'Delete Snippet' do Delete - = link_to new_snippet_path, class: "btn btn-grouped btn-inverted btn-create", title: "New snippet" do + = link_to new_snippet_path, class: "btn btn-grouped btn-inverted btn-success", title: "New snippet" do New snippet - if @snippet.submittable_as_spam_by?(current_user) = link_to 'Submit as spam', mark_as_spam_snippet_path(@snippet), method: :post, class: 'btn btn-grouped btn-spam', title: 'Submit as spam' diff --git a/app/workers/new_merge_request_worker.rb b/app/workers/new_merge_request_worker.rb index 62f9d9b6f57..fa48c1b29a8 100644 --- a/app/workers/new_merge_request_worker.rb +++ b/app/workers/new_merge_request_worker.rb @@ -10,7 +10,7 @@ class NewMergeRequestWorker EventCreateService.new.open_mr(issuable, user) NotificationService.new.new_merge_request(issuable, user) - issuable.diffs.write_cache + issuable.diffs(include_stats: false).write_cache issuable.create_cross_references!(user) end diff --git a/changelogs/unreleased/44768-lazy-load-xterm-css.yml b/changelogs/unreleased/44768-lazy-load-xterm-css.yml new file mode 100644 index 00000000000..85f7b1984e0 --- /dev/null +++ b/changelogs/unreleased/44768-lazy-load-xterm-css.yml @@ -0,0 +1,5 @@ +--- +title: Lazy load xterm custom colors css +merge_request: +author: +type: performance diff --git a/changelogs/unreleased/44998-split-admin-settings-into-multiple-sub-pages.yml b/changelogs/unreleased/44998-split-admin-settings-into-multiple-sub-pages.yml new file mode 100644 index 00000000000..4b398e9419d --- /dev/null +++ b/changelogs/unreleased/44998-split-admin-settings-into-multiple-sub-pages.yml @@ -0,0 +1,5 @@ +--- +title: Split admin settings into multiple sub pages +merge_request: 21467 +author: +type: other diff --git a/changelogs/unreleased/51549-runners-table.yml b/changelogs/unreleased/51549-runners-table.yml new file mode 100644 index 00000000000..fe36bfc1b30 --- /dev/null +++ b/changelogs/unreleased/51549-runners-table.yml @@ -0,0 +1,5 @@ +--- +title: Fixes admin runners table not wrapping content +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/51571-wrapper-rake-task-uploads-migrate-os.yml b/changelogs/unreleased/51571-wrapper-rake-task-uploads-migrate-os.yml new file mode 100644 index 00000000000..50710ca0aa8 --- /dev/null +++ b/changelogs/unreleased/51571-wrapper-rake-task-uploads-migrate-os.yml @@ -0,0 +1,5 @@ +--- +title: Add wrapper rake task to migrate all uploads to OS +merge_request: 21779 +author: +type: other diff --git a/changelogs/unreleased/force-post-migration-dir-schema-load.yml b/changelogs/unreleased/force-post-migration-dir-schema-load.yml new file mode 100644 index 00000000000..19119515929 --- /dev/null +++ b/changelogs/unreleased/force-post-migration-dir-schema-load.yml @@ -0,0 +1,5 @@ +--- +title: Ensure the schema is loaded with post_migrations included +merge_request: 21689 +author: +type: changed diff --git a/changelogs/unreleased/mr-legacy-diff-notes.yml b/changelogs/unreleased/mr-legacy-diff-notes.yml new file mode 100644 index 00000000000..bca5ac8297f --- /dev/null +++ b/changelogs/unreleased/mr-legacy-diff-notes.yml @@ -0,0 +1,5 @@ +--- +title: Correctly show legacy diff notes in the merge request changes tab +merge_request: 21652 +author: +type: fixed diff --git a/changelogs/unreleased/osw-use-diff-stats-rpc-on-comparison-views.yml b/changelogs/unreleased/osw-use-diff-stats-rpc-on-comparison-views.yml new file mode 100644 index 00000000000..c71d4e58d6f --- /dev/null +++ b/changelogs/unreleased/osw-use-diff-stats-rpc-on-comparison-views.yml @@ -0,0 +1,5 @@ +--- +title: Use stats RPC when comparing diffs +merge_request: 21778 +author: +type: fixed diff --git a/changelogs/unreleased/sh-delete-tags-outside-transaction.yml b/changelogs/unreleased/sh-delete-tags-outside-transaction.yml new file mode 100644 index 00000000000..974da70251e --- /dev/null +++ b/changelogs/unreleased/sh-delete-tags-outside-transaction.yml @@ -0,0 +1,5 @@ +--- +title: Delete container repository tags outside of transaction +merge_request: 21679 +author: +type: fixed diff --git a/changelogs/unreleased/vendor-gitlab-ci-auto-devops-yml.yml b/changelogs/unreleased/vendor-gitlab-ci-auto-devops-yml.yml new file mode 100644 index 00000000000..98d0e24c00a --- /dev/null +++ b/changelogs/unreleased/vendor-gitlab-ci-auto-devops-yml.yml @@ -0,0 +1,5 @@ +--- +title: Make AutoDevOps work behind proxy +merge_request: 21775 +author: Sergej - @kinolaev +type: other diff --git a/config/application.rb b/config/application.rb index f3c53fa63f3..79fdd8a1a63 100644 --- a/config/application.rb +++ b/config/application.rb @@ -134,6 +134,7 @@ module Gitlab config.assets.precompile << "notify.css" config.assets.precompile << "mailers/*.css" config.assets.precompile << "page_bundles/ide.css" + config.assets.precompile << "page_bundles/xterm.css" config.assets.precompile << "performance_bar.css" config.assets.precompile << "lib/ace.js" config.assets.precompile << "test.css" diff --git a/config/initializers/0_post_deployment_migrations.rb b/config/initializers/0_post_deployment_migrations.rb index 3d81b869b52..2d647f72840 100644 --- a/config/initializers/0_post_deployment_migrations.rb +++ b/config/initializers/0_post_deployment_migrations.rb @@ -1,14 +1,4 @@ # Post deployment migrations are included by default. This file must be loaded # before other initializers as Rails may otherwise memoize a list of migrations # excluding the post deployment migrations. -unless ENV['SKIP_POST_DEPLOYMENT_MIGRATIONS'] - Rails.application.config.paths['db'].each do |db_path| - path = Rails.root.join(db_path, 'post_migrate').to_s - - Rails.application.config.paths['db/migrate'] << path - - # Rails memoizes migrations at certain points where it won't read the above - # path just yet. As such we must also update the following list of paths. - ActiveRecord::Migrator.migrations_paths << path - end -end +Gitlab::Database.add_post_migrate_path_to_rails diff --git a/config/routes/admin.rb b/config/routes/admin.rb index fa1f79a90be..7489b01ded6 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -110,6 +110,7 @@ namespace :admin do put :reset_runners_token put :reset_health_check_token put :clear_repository_check_states + get :integrations, :repository, :templates, :ci_cd, :reporting, :metrics_and_profiling, :network, :geo, :preferences end resources :labels diff --git a/danger/commit_messages/Dangerfile b/danger/commit_messages/Dangerfile index a152ff837a9..c5ebb9b457e 100644 --- a/danger/commit_messages/Dangerfile +++ b/danger/commit_messages/Dangerfile @@ -38,6 +38,10 @@ def fail_commit(commit, message) fail("#{commit.sha}: #{message}") end +def warn_commit(commit, message) + warn("#{commit.sha}: #{message}") +end + def lines_changed_in_commit(commit) commit.diff_parent.stats[:total][:lines] end @@ -87,13 +91,21 @@ def lint_commits(commits) failures = true end - if subject.length > 50 + if subject.length > 72 fail_commit( commit, - 'The commit subject may not be longer than 50 characters' + 'The commit subject may not be longer than 72 characters' ) failures = true + elsif subject.length > 50 + warn_commit( + commit, + "This commit's subject line could be improved. " \ + 'Commit subjects are ideally no longer than roughly 50 characters, ' \ + 'though we allow up to 72 characters in the subject. ' \ + 'If possible, try to reduce the length of the subject to roughly 50 characters.' + ) end unless subject_starts_with_capital?(subject) diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md index 1f3bc611cdf..757865ea2c5 100644 --- a/doc/administration/job_artifacts.md +++ b/doc/administration/job_artifacts.md @@ -127,6 +127,7 @@ The connection settings match those provided by [Fog](https://github.com/fog), a | `host` | S3 compatible host for when not using AWS, e.g. `localhost` or `storage.example.com` | s3.amazonaws.com | | `endpoint` | Can be used when configuring an S3 compatible service such as [Minio](https://www.minio.io), by entering a URL such as `http://127.0.0.1:9000` | (optional) | | `path_style` | Set to true to use `host/bucket_name/object` style paths instead of `bucket_name.host/object`. Leave as false for AWS S3 | false | +| `use_iam_profile` | Set to true to use IAM profile instead of access keys | false **In Omnibus installations:** diff --git a/doc/administration/raketasks/uploads/migrate.md b/doc/administration/raketasks/uploads/migrate.md index 0cd33ffc122..b5c40478ea5 100644 --- a/doc/administration/raketasks/uploads/migrate.md +++ b/doc/administration/raketasks/uploads/migrate.md @@ -7,10 +7,32 @@ After [configuring the object storage](../../uploads.md#using-object-storage) fo >**Note:** All of the processing will be done in a background worker and requires **no downtime**. -This tasks uses 3 parameters to find uploads to migrate. +### All-in-one rake task + +GitLab provides a wrapper rake task that migrates all uploaded files - avatars, +logos, attachments, favicon, etc. - to object storage in one go. Under the hood, +it invokes individual rake tasks to migrate files falling under each of this +category one by one. The specifications of these individual rake tasks are +described in the next section. + +**Omnibus Installation** + +```bash +gitlab-rake "gitlab:uploads:migrate:all" +``` + +**Source Installation** + +```bash +sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:migrate:all +``` + +### Individual rake tasks >**Note:** -These parameters are mainly internal to GitLab's structure, you may want to refer to the task list instead below. +If you already ran the rake task mentioned above, no need to run these individual rake tasks as that has been done automatically. + +The rake task uses 3 parameters to find uploads to migrate. Parameter | Type | Description --------- | ---- | ----------- @@ -18,6 +40,9 @@ Parameter | Type | Description `model_class` | string | Type of the model to migrate from `mount_point` | string/symbol | Name of the model's column on which the uploader is mounted on. +>**Note:** +These parameters are mainly internal to GitLab's structure, you may want to refer to the task list instead below. + This task also accepts some environment variables which you can use to override certain values: @@ -25,7 +50,7 @@ Variable | Type | Description -------- | ---- | ----------- `BATCH` | integer | Specifies the size of the batch. Defaults to 200. -** Omnibus Installation** +**Omnibus Installation** ```bash # gitlab-rake gitlab:uploads:migrate[uploader_class, model_class, mount_point] @@ -40,6 +65,9 @@ gitlab-rake "gitlab:uploads:migrate[AttachmentUploader, Note, :attachment]" gitlab-rake "gitlab:uploads:migrate[AttachmentUploader, Appearance, :logo]" gitlab-rake "gitlab:uploads:migrate[AttachmentUploader, Appearance, :header_logo]" +# Favicon +gitlab-rake "gitlab:uploads:migrate[FaviconUploader, Appearance, :favicon]" + # Markdown gitlab-rake "gitlab:uploads:migrate[FileUploader, Project]" gitlab-rake "gitlab:uploads:migrate[PersonalFileUploader, Snippet]" @@ -65,6 +93,9 @@ sudo -u git -H bundle exec rake "gitlab:uploads:migrate[AttachmentUploader, Note sudo -u git -H bundle exec rake "gitlab:uploads:migrate[AttachmentUploader, Appearance, :logo]" sudo -u git -H bundle exec rake "gitlab:uploads:migrate[AttachmentUploader, Appearance, :header_logo]" +# Favicon +sudo -u git -H bundle exec rake "gitlab:uploads:migrate[FaviconUploader, Appearance, :favicon]" + # Markdown sudo -u git -H bundle exec rake "gitlab:uploads:migrate[FileUploader, Project]" sudo -u git -H bundle exec rake "gitlab:uploads:migrate[PersonalFileUploader, Snippet]" diff --git a/doc/administration/uploads.md b/doc/administration/uploads.md index 467deb43644..ce83da16067 100644 --- a/doc/administration/uploads.md +++ b/doc/administration/uploads.md @@ -86,6 +86,7 @@ The connection settings match those provided by [Fog](https://github.com/fog), a | `host` | S3 compatible host for when not using AWS, e.g. `localhost` or `storage.example.com` | s3.amazonaws.com | | `endpoint` | Can be used when configuring an S3 compatible service such as [Minio](https://www.minio.io), by entering a URL such as `http://127.0.0.1:9000` | (optional) | | `path_style` | Set to true to use `host/bucket_name/object` style paths instead of `bucket_name.host/object`. Leave as false for AWS S3 | false | +| `use_iam_profile` | Set to true to use IAM profile instead of access keys | false **In Omnibus installations:** diff --git a/doc/development/README.md b/doc/development/README.md index d8dbc993442..94e604d125d 100644 --- a/doc/development/README.md +++ b/doc/development/README.md @@ -94,6 +94,7 @@ description: 'Learn how to contribute to GitLab.' - [Verifying database capabilities](verifying_database_capabilities.md) - [Database Debugging and Troubleshooting](database_debugging.md) - [Query Count Limits](query_count_limits.md) +- [Database helper modules](database_helpers.md) ## Testing guides diff --git a/doc/development/database_helpers.md b/doc/development/database_helpers.md new file mode 100644 index 00000000000..21e4e725de6 --- /dev/null +++ b/doc/development/database_helpers.md @@ -0,0 +1,63 @@ +# Database helpers + +There are a number of useful helper modules defined in `/lib/gitlab/database/`. + +## Subquery + +In some cases it is not possible to perform an operation on a query. +For example: + +```ruby +Geo::EventLog.where('id < 100').limit(10).delete_all +``` + +Will give this error: + +> ActiveRecord::ActiveRecordError: delete_all doesn't support limit + +One solution would be to wrap it in another `where`: + +```ruby +Geo::EventLog.where(id: Geo::EventLog.where('id < 100').limit(10)).delete_all +``` + +This works with PostgreSQL, but with MySQL it gives this error: + +> ActiveRecord::StatementInvalid: Mysql2::Error: This version of MySQL +> doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' + +Also, that query doesn't have very good performance. Using a +`INNER JOIN` with itself is better. + +So instead of this query: + +```sql +SELECT geo_event_log.* +FROM geo_event_log +WHERE geo_event_log.id IN + (SELECT geo_event_log.id + FROM geo_event_log + WHERE (id < 100) + LIMIT 10) +``` + +It's better to write: + +```sql +SELECT geo_event_log.* +FROM geo_event_log +INNER JOIN + (SELECT geo_event_log.* + FROM geo_event_log + WHERE (id < 100) + LIMIT 10) t2 ON geo_event_log.id = t2.id +``` + +And this is where `Gitlab::Database::Subquery.self_join` can help +you. So you can rewrite the above statement as: + +```ruby +Gitlab::Database::Subquery.self_join(Geo::EventLog.where('id < 100').limit(10)).delete_all +``` + +And this also works with MySQL, so you don't need to worry about that. diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md index 7ac211ed550..d6ae4cb39f0 100644 --- a/doc/development/documentation/index.md +++ b/doc/development/documentation/index.md @@ -411,6 +411,22 @@ The following GitLab features are used among others: Every GitLab instance includes the documentation, which is available from `/help` (`http://my-instance.com/help`), e.g., <https://gitlab.com/help>. +The documentation available online on docs.gitlab.com is continuously +deployed every hour from the `master` branch of CE, EE, Omnibus, and Runner. Therefore, +once a merge request gets merged, it will be available online on the same day, +but they will be shipped (and available on `/help`) within the milestone assigned +to the MR. + +For instance, let's say your merge request has a milestone set to 11.3, which +will be released on 2018-09-22. If it gets merged on 2018-09-15, it will be +available online on 2018-09-15, but, as the feature freeze date has passed, if +the MR does not have a "pick into 11.3" label, the milestone has to be changed +to 11.4 and it will be shipped with all GitLab packages only on 2018-10-22, +with GitLab 11.4. Meaning, it will only be available under `/help` from GitLab +11.4 onwards, but available on docs.gitlab.com on the same day it was merged. + +### Linking to `/help` + When you're building a new feature, you may need to link the documentation from GitLab, the application. This is normally done in files inside the `app/views/` directory with the help of the `help_page_path` helper method. diff --git a/doc/development/file_storage.md b/doc/development/file_storage.md index fdbd7f1fa37..6e014e8c751 100644 --- a/doc/development/file_storage.md +++ b/doc/development/file_storage.md @@ -45,6 +45,11 @@ In the case of Issues/MR/Notes Markdown attachments, there is a different approa instead of basing the path into a mutable variable `:project_path_with_namespace`, it's possible to use the hash of the project ID instead, if project migrates to the new approach (introduced in 10.2). +> Note: We provide an [all-in-one rake task] to migrate all uploads to object +> storage in one go. If a new Uploader class or model type is introduced, make +> sure you add a rake task invocation corresponding to it to the [category +> list]. + ### Path segments Files are stored at multiple locations and use different path schemes. @@ -137,3 +142,5 @@ end [CarrierWave]: https://github.com/carrierwaveuploader/carrierwave [Hashed Storage]: ../administration/repository_storage_types.md +[all-in-one rake task]: ../administration/raketasks/uploads/migrate.md +[category list]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/tasks/gitlab/uploads/migrate.rake diff --git a/doc/development/testing_guide/index.md b/doc/development/testing_guide/index.md index 0cd63a54b55..67e4cfeda0e 100644 --- a/doc/development/testing_guide/index.md +++ b/doc/development/testing_guide/index.md @@ -59,6 +59,12 @@ parallelization, monitoring. --- +## [Review apps](review_apps.md) + +How review apps are set up for GitLab CE/EE and how to use them. + +--- + ## [Testing Rake tasks](testing_rake_tasks.md) Everything you should know about how to test Rake tasks. diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md new file mode 100644 index 00000000000..38ea2f1dde1 --- /dev/null +++ b/doc/development/testing_guide/review_apps.md @@ -0,0 +1,82 @@ +# Review apps + +We currently have review apps available as a manual job in EE pipelines. Here is +[the first implementation](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/6259). + +That said, [the Quality team is working](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/6665) +on making Review Apps automatically deployed by each pipeline, both in CE and EE. + +## How does it work? + +1. On every EE [pipeline][gitlab-pipeline] during the `test` stage, you can + start the [`review` job][review-job] +1. The `review` job [triggers a pipeline][cng-pipeline] in the + [`CNG-mirror`][cng-mirror] [^1] project +1. The `CNG-mirror` pipeline creates the Docker images of each component (e.g. `gitlab-rails-ee`, + `gitlab-shell`, `gitaly` etc.) based on the commit from the + [GitLab pipeline][gitlab-pipeline] and store them in its + [registry][cng-mirror-registry] +1. Once all images are built, the review app is deployed using + [the official GitLab Helm chart][helm-chart] [^2] to the + [`review-apps-ee` Kubernetes cluster on GCP][review-apps-ee] + - The actual scripts used to deploy the review app can be found at + [`scripts/review_apps/review-apps.sh`][review-apps.sh] + - These scripts are basically + [our official Auto DevOps scripts][Auto-DevOps.gitlab-ci.yml] where the + default CNG images are overriden with the images built and stored in the + [`CNG-mirror` project's registry][cng-mirror-registry] +1. Once the `review` job succeeds, you should be able to use your review app + thanks to the direct link to it from the MR widget. The default username is + `root` and its password can be found in the 1Password secure note named + **gitlab-{ce,ee} review app's root password**. + +**Additional notes:** + +- The Kubernetes cluster is connected to the `gitlab-ee` project using [GitLab's + Kubernetes integration][gitlab-k8s-integration]. This basically allows to have + a link to the review app directly from the merge request widget. +- The manual `stop_review` in the `post-cleanup` stage can be used to stop a + review app manually, and is also started by GitLab once a branch is deleted +- [TBD] Review apps are cleaned up regularly using a pipeline schedule that runs + the [`scripts/review_apps/automated_cleanup.rb`][automated_cleanup.rb] script + +[^1]: We use the `CNG-mirror` project so that the `CNG`, (**C**loud **N**ative **G**itLab), project's registry is + not overloaded with a lot of transient Docker images. +[^2]: Since we're using [the official GitLab Helm chart][helm-chart], this means + you get the a dedicated environment for your branch that's very close to what it + would look in production + +## Frequently Asked Questions + +**Will it be too much to trigger CNG image builds on every test run? This could create thousands of unused docker images.** + + > We have to start somewhere and improve later. If we see this getting out of hand, we will revisit. + +**How big is the Kubernetes cluster?** + + > The cluster is currently setup with a single pool of preemptible + nodes, with a minimum of 1 node and a maximum of 30 nodes. + +**What are the machine running on the cluster?** + + > We're currently using `n1-standard-4` (4 vCPUs, 15 GB memory) machines. + +**How do we secure this from abuse? Apps are open to the world so we need to find a way to limit it to only us.** + + > This won't work for forks. We will add a root password to 1password shared vault. + +[gitlab-pipeline]: https://gitlab.com/gitlab-org/gitlab-ee/pipelines/29302122 +[review-job]: https://gitlab.com/gitlab-org/gitlab-ee/-/jobs/94294136 +[cng-mirror]: https://gitlab.com/gitlab-org/build/CNG-mirror +[cng-pipeline]: https://gitlab.com/gitlab-org/build/CNG-mirror/pipelines/29307727 +[cng-mirror-registry]: https://gitlab.com/gitlab-org/build/CNG-mirror/container_registry +[helm-chart]: https://gitlab.com/charts/gitlab/ +[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 +[automated_cleanup.rb]: https://gitlab.com/gitlab-org/gitlab-ee/blob/master/scripts/review_apps/automated_cleanup.rb +[Auto-DevOps.gitlab-ci.yml]: https://gitlab.com/gitlab-org/gitlab-ci-yml/blob/master/Auto-DevOps.gitlab-ci.yml +[gitlab-k8s-integration]: https://docs.gitlab.com/ee/user/project/clusters/index.html + +--- + +[Return to Testing documentation](index.md) diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md index 7f028565412..fc7b97b3cc2 100644 --- a/doc/policy/maintenance.md +++ b/doc/policy/maintenance.md @@ -44,7 +44,7 @@ This decision is made on a case-by-case basis. ## Upgrade recommendations -We encourage everyone to run the [latest stable release](https://about.gitlab.com/blog/categories/release/) to ensure that you can +We encourage everyone to run the [latest stable release](https://about.gitlab.com/blog/categories/releases/) to ensure that you can easily upgrade to the most secure and feature-rich GitLab experience. In order to make sure you can easily run the most recent stable release, we are working hard to keep the update process simple and reliable. diff --git a/doc/update/9.4-to-9.5.md b/doc/update/9.4-to-9.5.md index 1bfc1167c36..6a655f77a55 100644 --- a/doc/update/9.4-to-9.5.md +++ b/doc/update/9.4-to-9.5.md @@ -154,7 +154,7 @@ sudo -u git -H make #### New Gitaly configuration options required -In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell'. +In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`. ```shell echo ' diff --git a/doc/update/9.5-to-10.0.md b/doc/update/9.5-to-10.0.md index 8d1cf0f737b..7790d192a82 100644 --- a/doc/update/9.5-to-10.0.md +++ b/doc/update/9.5-to-10.0.md @@ -154,7 +154,7 @@ sudo -u git -H make #### New Gitaly configuration options required -In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell'. +In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`. ```shell echo ' diff --git a/doc/user/project/integrations/img/webhooks_ssl.png b/doc/user/project/integrations/img/webhooks_ssl.png Binary files differindex f023e9665f2..e5777a2e99b 100644 --- a/doc/user/project/integrations/img/webhooks_ssl.png +++ b/doc/user/project/integrations/img/webhooks_ssl.png diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md index 6104eadde35..e22f8e976be 100644 --- a/doc/user/project/integrations/webhooks.md +++ b/doc/user/project/integrations/webhooks.md @@ -57,6 +57,14 @@ You can turn this off in the webhook settings in your GitLab projects. ![SSL Verification](img/webhooks_ssl.png) +## Branch filtering + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/20338) in GitLab 11.3. + +Push events can be filtered by branch using a branch name or wildcard pattern +to limit which push events are sent to your webhook endpoint. By default the +field is blank causing all push events to be sent to your webhook endpoint. + ## Events Below are described the supported events. diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md index ad0ef60373c..127a30d6669 100644 --- a/doc/user/project/wiki/index.md +++ b/doc/user/project/wiki/index.md @@ -40,11 +40,6 @@ support Markdown, RDoc and AsciiDoc. For Markdown based pages, all the [Markdown features](../../markdown.md) are supported and for links there is some [wiki specific](../../markdown.md#wiki-specific-markdown) behavior. ->**Note:** -The wiki is based on a Git repository and contains only text files. Uploading -files via the web interface will upload them in GitLab itself, and they will -not be available if you clone the wiki repo locally. - In the web interface the commit message is optional, but the GitLab Wiki is based on Git and needs a commit message, so one will be created for you if you do not enter one. @@ -53,6 +48,14 @@ When you're ready, click the **Create page** and the new page will be created. ![New page](img/wiki_create_new_page.png) +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/33475) in GitLab 11.3. + +Starting with GitLab 11.3, any file that is uploaded to the wiki via GitLab's +interface will be stored in the wiki Git repository, and it will be available +if you clone the wiki repository locally. All uploaded files prior to GitLab +11.3 are stored in GitLab itself. If you want them to be part of the wiki's Git +repository, you will have to upload them again. + ## Editing a wiki page To edit a page, simply click on the **Edit** button. From there on, you can diff --git a/doc/workflow/lfs/lfs_administration.md b/doc/workflow/lfs/lfs_administration.md index 3f9ffedd61a..444d1483fcc 100644 --- a/doc/workflow/lfs/lfs_administration.md +++ b/doc/workflow/lfs/lfs_administration.md @@ -95,6 +95,7 @@ Here is a configuration example with S3. | `host` | S3 compatible host for when not using AWS, e.g. `localhost` or `storage.example.com` | s3.amazonaws.com | | `endpoint` | Can be used when configuring an S3 compatible service such as [Minio](https://www.minio.io), by entering a URL such as `http://127.0.0.1:9000` | (optional) | | `path_style` | Set to true to use `host/bucket_name/object` style paths instead of `bucket_name.host/object`. Leave as false for AWS S3 | false | +| `use_iam_profile` | Set to true to use IAM profile instead of access keys | false Here is a configuration example with GCS. diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb index e8dbde176ef..e02d403f7b1 100644 --- a/lib/extracts_path.rb +++ b/lib/extracts_path.rb @@ -54,7 +54,7 @@ module ExtractsPath valid_refs = ref_names.select { |v| id.start_with?("#{v}/") } - if valid_refs.length == 0 + if valid_refs.empty? # No exact ref match, so just try our best pair = id.match(%r{([^/]+)(.*)}).captures else diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb index 8eacad078c8..42f9605f5ac 100644 --- a/lib/gitlab/database.rb +++ b/lib/gitlab/database.rb @@ -249,5 +249,21 @@ module Gitlab end private_class_method :database_version + + def self.add_post_migrate_path_to_rails(force: false) + return if ENV['SKIP_POST_DEPLOYMENT_MIGRATIONS'] && !force + + Rails.application.config.paths['db'].each do |db_path| + path = Rails.root.join(db_path, 'post_migrate').to_s + + unless Rails.application.config.paths['db/migrate'].include? path + Rails.application.config.paths['db/migrate'] << path + + # Rails memoizes migrations at certain points where it won't read the above + # path just yet. As such we must also update the following list of paths. + ActiveRecord::Migrator.migrations_paths << path + end + end + end end end diff --git a/lib/gitlab/database/subquery.rb b/lib/gitlab/database/subquery.rb new file mode 100644 index 00000000000..2a6f39c6a27 --- /dev/null +++ b/lib/gitlab/database/subquery.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Gitlab + module Database + module Subquery + class << self + def self_join(relation) + t = relation.arel_table + t2 = relation.arel.as('t2') + + relation.unscoped.joins(t.join(t2).on(t[:id].eq(t2[:id])).join_sources.first) + end + end + end + end +end diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb index d2ca7a070fa..fb117baca9e 100644 --- a/lib/gitlab/diff/file.rb +++ b/lib/gitlab/diff/file.rb @@ -20,8 +20,9 @@ module Gitlab DiffViewer::Image ].sort_by { |v| v.binary? ? 0 : 1 }.freeze - def initialize(diff, repository:, diff_refs: nil, fallback_diff_refs: nil) + def initialize(diff, repository:, diff_refs: nil, fallback_diff_refs: nil, stats: nil) @diff = diff + @stats = stats @repository = repository @diff_refs = diff_refs @fallback_diff_refs = fallback_diff_refs @@ -165,11 +166,11 @@ module Gitlab end def added_lines - diff_lines.count(&:added?) + @stats&.additions || diff_lines.count(&:added?) end def removed_lines - diff_lines.count(&:removed?) + @stats&.deletions || diff_lines.count(&:removed?) end def file_identifier diff --git a/lib/gitlab/diff/file_collection/base.rb b/lib/gitlab/diff/file_collection/base.rb index 2acb0e43b69..b79ff771a2b 100644 --- a/lib/gitlab/diff/file_collection/base.rb +++ b/lib/gitlab/diff/file_collection/base.rb @@ -2,23 +2,27 @@ module Gitlab module Diff module FileCollection class Base + include Gitlab::Utils::StrongMemoize + attr_reader :project, :diff_options, :diff_refs, :fallback_diff_refs, :diffable delegate :count, :size, :real_size, to: :diff_files def self.default_options - ::Commit.max_diff_options.merge(ignore_whitespace_change: false, expanded: false) + ::Commit.max_diff_options.merge(ignore_whitespace_change: false, expanded: false, include_stats: true) end def initialize(diffable, project:, diff_options: nil, diff_refs: nil, fallback_diff_refs: nil) diff_options = self.class.default_options.merge(diff_options || {}) @diffable = diffable + @include_stats = diff_options.delete(:include_stats) @diffs = diffable.raw_diffs(diff_options) @project = project @diff_options = diff_options @diff_refs = diff_refs @fallback_diff_refs = fallback_diff_refs + @repository = project.repository end def diff_files @@ -43,10 +47,27 @@ module Gitlab private + def diff_stats_collection + strong_memoize(:diff_stats) do + # There are scenarios where we don't need to request Diff Stats, + # when caching for instance. + next unless @include_stats + next unless diff_refs + + @repository.diff_stats(diff_refs.base_sha, diff_refs.head_sha) + end + end + def decorate_diff!(diff) return diff if diff.is_a?(File) - Gitlab::Diff::File.new(diff, repository: project.repository, diff_refs: diff_refs, fallback_diff_refs: fallback_diff_refs) + stats = diff_stats_collection&.find_by_path(diff.new_path) + + Gitlab::Diff::File.new(diff, + repository: project.repository, + diff_refs: diff_refs, + fallback_diff_refs: fallback_diff_refs, + stats: stats) end end end diff --git a/lib/gitlab/diff/position.rb b/lib/gitlab/diff/position.rb index 978962ab2eb..4b6016e00bc 100644 --- a/lib/gitlab/diff/position.rb +++ b/lib/gitlab/diff/position.rb @@ -116,6 +116,10 @@ module Gitlab end end + def diff_options + { paths: paths, expanded: true, include_stats: false } + end + def diff_line(repository) @diff_line ||= diff_file(repository)&.line_for_position(self) end @@ -130,7 +134,7 @@ module Gitlab return unless diff_refs.complete? return unless comparison = diff_refs.compare_in(repository.project) - comparison.diffs(paths: paths, expanded: true).diff_files.first + comparison.diffs(diff_options).diff_files.first end def get_formatter_class(type) diff --git a/lib/gitlab/git/diff_stats_collection.rb b/lib/gitlab/git/diff_stats_collection.rb index 84d9e46f98e..d4033f56387 100644 --- a/lib/gitlab/git/diff_stats_collection.rb +++ b/lib/gitlab/git/diff_stats_collection.rb @@ -3,6 +3,7 @@ module Gitlab module Git class DiffStatsCollection + include Gitlab::Utils::StrongMemoize include Enumerable def initialize(diff_stats) @@ -12,6 +13,18 @@ module Gitlab def each(&block) @collection.each(&block) end + + def find_by_path(path) + indexed_by_path[path] + end + + private + + def indexed_by_path + strong_memoize(:indexed_by_path) do + index_by { |stats| stats.path } + end + end end end end diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index fa22294ac51..3d5a63bdbac 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -444,7 +444,7 @@ module Gitlab end Gitlab::Git::DiffStatsCollection.new(stats) - rescue CommandError + rescue CommandError, TypeError Gitlab::Git::DiffStatsCollection.new([]) end diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake index 69166851816..74cd70c6e9f 100644 --- a/lib/tasks/gitlab/db.rake +++ b/lib/tasks/gitlab/db.rake @@ -51,6 +51,8 @@ namespace :gitlab do if ActiveRecord::Base.connection.tables.count > 1 Rake::Task['db:migrate'].invoke else + # Add post-migrate paths to ensure we mark all migrations as up + Gitlab::Database.add_post_migrate_path_to_rails(force: true) Rake::Task['db:schema:load'].invoke Rake::Task['db:seed_fu'].invoke end diff --git a/lib/tasks/gitlab/uploads/migrate.rake b/lib/tasks/gitlab/uploads/migrate.rake index f548a266b99..1c93609a006 100644 --- a/lib/tasks/gitlab/uploads/migrate.rake +++ b/lib/tasks/gitlab/uploads/migrate.rake @@ -1,6 +1,30 @@ namespace :gitlab do namespace :uploads do - desc 'GitLab | Uploads | Migrate the uploaded files to object storage' + namespace :migrate do + desc "GitLab | Uploads | Migrate all uploaded files to object storage" + task all: :environment do + categories = [%w(AvatarUploader Project :avatar), + %w(AvatarUploader Group :avatar), + %w(AvatarUploader User :avatar), + %w(AttachmentUploader Note :attachment), + %w(AttachmentUploader Appearance :logo), + %w(AttachmentUploader Appearance :header_logo), + %w(FaviconUploader Appearance :favicon), + %w(FileUploader Project), + %w(PersonalFileUploader Snippet), + %w(NamespaceFileUploader Snippet), + %w(FileUploader MergeRequest)] + + categories.each do |args| + Rake::Task["gitlab:uploads:migrate"].invoke(*args) + Rake::Task["gitlab:uploads:migrate"].reenable + end + end + end + + # The following is the actual rake task that migrates uploads of specified + # category to object storage + desc 'GitLab | Uploads | Migrate the uploaded files of specified type to object storage' task :migrate, [:uploader_class, :model_class, :mounted_as] => :environment do |task, args| batch_size = ENV.fetch('BATCH', 200).to_i @to_store = ObjectStorage::Store::REMOTE diff --git a/locale/ar_SA/gitlab.po b/locale/ar_SA/gitlab.po index a9a1e87c479..662e69e27c6 100644 --- a/locale/ar_SA/gitlab.po +++ b/locale/ar_SA/gitlab.po @@ -444,7 +444,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -891,7 +891,7 @@ msgstr "" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6702,10 +6702,10 @@ msgstr "" msgid "Settings" msgstr "" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8316,7 +8316,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po index 8aae50168be..dc4d2618ab7 100644 --- a/locale/bg/gitlab.po +++ b/locale/bg/gitlab.po @@ -308,7 +308,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -755,7 +755,7 @@ msgstr "" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6510,10 +6510,10 @@ msgstr "зададете парола" msgid "Settings" msgstr "" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8108,7 +8108,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/ca_ES/gitlab.po b/locale/ca_ES/gitlab.po index 2bdf9db1fb5..6bfe59669b5 100644 --- a/locale/ca_ES/gitlab.po +++ b/locale/ca_ES/gitlab.po @@ -308,7 +308,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -755,7 +755,7 @@ msgstr "" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6510,10 +6510,10 @@ msgstr "" msgid "Settings" msgstr "" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8108,7 +8108,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/cs_CZ/gitlab.po b/locale/cs_CZ/gitlab.po index 98eb5b1aba6..0e349d2b12a 100644 --- a/locale/cs_CZ/gitlab.po +++ b/locale/cs_CZ/gitlab.po @@ -376,7 +376,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -823,7 +823,7 @@ msgstr "Artefakty" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6606,10 +6606,10 @@ msgstr "" msgid "Settings" msgstr "" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8212,7 +8212,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/da_DK/gitlab.po b/locale/da_DK/gitlab.po index d1757972cfe..c32bf9eb38d 100644 --- a/locale/da_DK/gitlab.po +++ b/locale/da_DK/gitlab.po @@ -308,7 +308,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -755,7 +755,7 @@ msgstr "" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6510,10 +6510,10 @@ msgstr "" msgid "Settings" msgstr "" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8108,7 +8108,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po index 562251fa483..71e6504e306 100644 --- a/locale/de/gitlab.po +++ b/locale/de/gitlab.po @@ -308,7 +308,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -755,7 +755,7 @@ msgstr "" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6510,10 +6510,10 @@ msgstr "ein Passwort festlegst" msgid "Settings" msgstr "Einstellungen" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8108,7 +8108,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po index 8aff5c0a62b..456235b2fa6 100644 --- a/locale/eo/gitlab.po +++ b/locale/eo/gitlab.po @@ -308,7 +308,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -755,7 +755,7 @@ msgstr "" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6510,10 +6510,10 @@ msgstr "kreos pasvorton" msgid "Settings" msgstr "" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8108,7 +8108,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po index ef26024bd48..eba59fdd3d8 100644 --- a/locale/es/gitlab.po +++ b/locale/es/gitlab.po @@ -308,7 +308,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -755,7 +755,7 @@ msgstr "Artefactos" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6510,10 +6510,10 @@ msgstr "establecer una contraseña" msgid "Settings" msgstr "Configuración" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8108,7 +8108,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/et_EE/gitlab.po b/locale/et_EE/gitlab.po index 2fdb8197acd..dbaff32f1b5 100644 --- a/locale/et_EE/gitlab.po +++ b/locale/et_EE/gitlab.po @@ -308,7 +308,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -755,7 +755,7 @@ msgstr "" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6510,10 +6510,10 @@ msgstr "" msgid "Settings" msgstr "" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8108,7 +8108,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/fil_PH/gitlab.po b/locale/fil_PH/gitlab.po index 58254366594..20943d89ea0 100644 --- a/locale/fil_PH/gitlab.po +++ b/locale/fil_PH/gitlab.po @@ -308,7 +308,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -755,7 +755,7 @@ msgstr "" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6510,10 +6510,10 @@ msgstr "" msgid "Settings" msgstr "" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8108,7 +8108,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/fr/gitlab.po b/locale/fr/gitlab.po index 84bc10a9cd2..c0ce98832de 100644 --- a/locale/fr/gitlab.po +++ b/locale/fr/gitlab.po @@ -308,7 +308,7 @@ msgstr "<strong>%{pushes}</strong> poussées Git, plus de <strong>%{commits}</s msgid "<strong>Removes</strong> source branch" msgstr "<strong>Supprime</strong> la branche source" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "Un « exécuteur » est un processus qui exécute une tâche. Vous pouvez configurer autant d’exécuteurs que nécessaire." msgid "A collection of graphs regarding Continuous Integration" @@ -755,7 +755,7 @@ msgstr "Artéfacts" msgid "Ascending" msgstr "Croissant" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "Demandez au responsable du groupe de configurer un exécuteur de groupe." msgid "Assertion consumer service URL" @@ -6510,10 +6510,10 @@ msgstr "définir un mot de passe" msgid "Settings" msgstr "Paramètres" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "Configurer automatiquement un exécuteur spécifique" msgid "Share" @@ -8108,7 +8108,7 @@ msgstr "Vous ne pouvez modifier des fichiers que dans une branche" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "Vous pouvez résoudre le conflit de fusion Git soit en mode interactif, en cliquant sur les boutons « %{use_ours} » ou « %{use_theirs} », soit en modifiant directement les fichiers. Valider ces modifications dans la branche « %{branch_name} »" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 3e6baeae87a..a55cf9c5927 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -250,7 +250,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -637,7 +637,7 @@ msgstr "" msgid "Artifacts" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assign custom color like #FF0000" @@ -1050,6 +1050,9 @@ msgstr "" msgid "CI / CD Settings" msgstr "" +msgid "CI/CD" +msgstr "" + msgid "CI/CD configuration" msgstr "" @@ -2841,6 +2844,9 @@ msgstr "" msgid "Generate a default set of labels" msgstr "" +msgid "Geo" +msgstr "" + msgid "Git" msgstr "" @@ -3708,6 +3714,9 @@ msgstr "" msgid "Metrics - Prometheus" msgstr "" +msgid "Metrics and profiling" +msgstr "" + msgid "Metrics|Check out the CI/CD documentation on deploying to an environment" msgstr "" @@ -4995,6 +5004,9 @@ msgstr "" msgid "Reply to this email directly or %{view_it_on_gitlab}." msgstr "" +msgid "Reporting" +msgstr "" + msgid "Reports|%{failedString} and %{resolvedString}" msgstr "" @@ -5363,19 +5375,19 @@ msgstr "" msgid "Set up Koding" msgstr "" -msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically." +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "SetPasswordToCloneLink|set a password" +msgid "Set up a specific Runner automatically" msgstr "" -msgid "Settings" +msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically." msgstr "" -msgid "Setup a %{type} Runner manually" +msgid "SetPasswordToCloneLink|set a password" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Settings" msgstr "" msgid "Share" @@ -5796,6 +5808,9 @@ msgstr "" msgid "Template" msgstr "" +msgid "Templates" +msgstr "" + msgid "Terms of Service Agreement and Privacy Policy" msgstr "" @@ -6799,7 +6814,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to this read-only GitLab instance." diff --git a/locale/gl_ES/gitlab.po b/locale/gl_ES/gitlab.po index 5caaba0ee8f..5574ed0613f 100644 --- a/locale/gl_ES/gitlab.po +++ b/locale/gl_ES/gitlab.po @@ -308,7 +308,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -755,7 +755,7 @@ msgstr "" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6510,10 +6510,10 @@ msgstr "" msgid "Settings" msgstr "" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8108,7 +8108,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/he_IL/gitlab.po b/locale/he_IL/gitlab.po index 308d138a534..4eeac683e67 100644 --- a/locale/he_IL/gitlab.po +++ b/locale/he_IL/gitlab.po @@ -376,7 +376,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -823,7 +823,7 @@ msgstr "" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6606,10 +6606,10 @@ msgstr "" msgid "Settings" msgstr "" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8212,7 +8212,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/id_ID/gitlab.po b/locale/id_ID/gitlab.po index ee5305c8ec8..e185f4f71b7 100644 --- a/locale/id_ID/gitlab.po +++ b/locale/id_ID/gitlab.po @@ -274,7 +274,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -721,7 +721,7 @@ msgstr "" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6462,10 +6462,10 @@ msgstr "" msgid "Settings" msgstr "" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8056,7 +8056,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po index 50d627ea6de..a4e20f4fe65 100644 --- a/locale/it/gitlab.po +++ b/locale/it/gitlab.po @@ -308,7 +308,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -755,7 +755,7 @@ msgstr "Artefatti" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6510,10 +6510,10 @@ msgstr "imposta una password" msgid "Settings" msgstr "Impostazioni" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8108,7 +8108,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/ja/gitlab.po b/locale/ja/gitlab.po index 9864aded546..f1d84529a25 100644 --- a/locale/ja/gitlab.po +++ b/locale/ja/gitlab.po @@ -274,7 +274,7 @@ msgstr "<strong>%{pushes}</strong>回ã®ãƒ—ッシュã€<strong>%{commits}</stron msgid "<strong>Removes</strong> source branch" msgstr "ソースブランãƒã‚’<strong>削除</strong>" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "「Runnerã€ã¯ã‚¸ãƒ§ãƒ–を実行ã™ã‚‹ãƒ—ãƒã‚»ã‚¹ã§ã™ã€‚å¿…è¦ãªæ•°ã® Runner ã‚’ä»»æ„ã«ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ã§ãã¾ã™ã€‚" msgid "A collection of graphs regarding Continuous Integration" @@ -721,7 +721,7 @@ msgstr "アーティファクト" msgid "Ascending" msgstr "æ˜‡é †" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "グループ Runner ã®è¨å®šã¯ã€ã‚°ãƒ«ãƒ¼ãƒ—ã® Maintainer ã«ä¾é ¼ã—ã¦ãã ã•ã„。" msgid "Assertion consumer service URL" @@ -6462,10 +6462,10 @@ msgstr "パスワードをè¨å®š" msgid "Settings" msgstr "è¨å®š" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8056,7 +8056,7 @@ msgstr "ファイルを編集ã™ã‚‹ã«ã¯ã€ã©ã“ã‹ã®ãƒ–ランãƒã«ã„ãªã‘ msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/ko/gitlab.po b/locale/ko/gitlab.po index 6528dd0235a..416e0712a75 100644 --- a/locale/ko/gitlab.po +++ b/locale/ko/gitlab.po @@ -274,7 +274,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "'러너(Runner)'는 ìž‘ì—…ì„ ì‹¤í–‰í•˜ëŠ” 프로세스입니다. 필요한 ë§Œí¼ ëŸ¬ë„ˆë¥¼ ì…‹ì—…í• ìˆ˜ 있습니다." msgid "A collection of graphs regarding Continuous Integration" @@ -721,7 +721,7 @@ msgstr "" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "그룹 관리ìžì—게 그룹 Runner 를 ì„¤ì •í•˜ë„ë¡ ìš”ì²í•˜ì„¸ìš”" msgid "Assertion consumer service URL" @@ -6462,10 +6462,10 @@ msgstr "패스워드 ì„¤ì •" msgid "Settings" msgstr "ì„¤ì •" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "íŠ¹ì • Runner ìžë™ ì„¤ì •" msgid "Share" @@ -8056,7 +8056,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/nl_NL/gitlab.po b/locale/nl_NL/gitlab.po index e210fbb6acb..8234f120676 100644 --- a/locale/nl_NL/gitlab.po +++ b/locale/nl_NL/gitlab.po @@ -308,7 +308,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -755,7 +755,7 @@ msgstr "" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6510,10 +6510,10 @@ msgstr "" msgid "Settings" msgstr "" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8108,7 +8108,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/pl_PL/gitlab.po b/locale/pl_PL/gitlab.po index c619c74fa81..6cc1b4472c7 100644 --- a/locale/pl_PL/gitlab.po +++ b/locale/pl_PL/gitlab.po @@ -376,7 +376,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -823,7 +823,7 @@ msgstr "" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6606,10 +6606,10 @@ msgstr "" msgid "Settings" msgstr "" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8212,7 +8212,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po index 9eb6ac8906b..a0e18f2be2f 100644 --- a/locale/pt_BR/gitlab.po +++ b/locale/pt_BR/gitlab.po @@ -308,7 +308,7 @@ msgstr "<strong>%{pushes}</strong> pushes, mais que <strong>%{commits}</strong> msgid "<strong>Removes</strong> source branch" msgstr "<strong>Remover</strong> branch de origem" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "'Runner' é um processo que executa um job. Você pode configurar quantos Runners você precisar." msgid "A collection of graphs regarding Continuous Integration" @@ -755,7 +755,7 @@ msgstr "Artefatos" msgid "Ascending" msgstr "Ascendente" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "Solicite a um mantenedor do grupo para configurar um Runner de grupo." msgid "Assertion consumer service URL" @@ -6510,10 +6510,10 @@ msgstr "defina uma senha" msgid "Settings" msgstr "Configurações" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "Configurar um Runner especÃfico automaticamente" msgid "Share" @@ -8108,7 +8108,7 @@ msgstr "Você só pode editar arquivos quando estiver em um branch" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "Você pode resolver o conflito de merge usando o modo Interativo, escolhendo os botões %{use_ours} ou %{use_theirs} ou editando os arquivos diretamente. Confirme essas alterações em %{branch_name}" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/ro_RO/gitlab.po b/locale/ro_RO/gitlab.po index 4ac7b482d51..f333a5aeba1 100644 --- a/locale/ro_RO/gitlab.po +++ b/locale/ro_RO/gitlab.po @@ -342,7 +342,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -789,7 +789,7 @@ msgstr "" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6558,10 +6558,10 @@ msgstr "" msgid "Settings" msgstr "" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8160,7 +8160,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/ru/gitlab.po b/locale/ru/gitlab.po index 8fd8001f30c..4b66d59bebd 100644 --- a/locale/ru/gitlab.po +++ b/locale/ru/gitlab.po @@ -376,7 +376,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "<strong>УдалÑет</strong> иÑходную ветку" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "«Runner» - Ñто процеÑÑ, который выполнÑет задание (обработчиков заданий). Ð’Ñ‹ можете наÑтроить Ñтолько таких процеÑÑов, Ñколько вам нужно." msgid "A collection of graphs regarding Continuous Integration" @@ -823,7 +823,7 @@ msgstr "Ðртефакты" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6606,10 +6606,10 @@ msgstr "уÑтановите пароль" msgid "Settings" msgstr "ÐаÑтройки" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "ÐаÑтроить конкретный обработчик заданий автоматичеÑки" msgid "Share" @@ -8212,7 +8212,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/sq_AL/gitlab.po b/locale/sq_AL/gitlab.po index 6fe5001d729..762d4ef53a7 100644 --- a/locale/sq_AL/gitlab.po +++ b/locale/sq_AL/gitlab.po @@ -308,7 +308,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -755,7 +755,7 @@ msgstr "" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6510,10 +6510,10 @@ msgstr "" msgid "Settings" msgstr "" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8108,7 +8108,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/tr_TR/gitlab.po b/locale/tr_TR/gitlab.po index a3dd9cb738e..e7e44caf077 100644 --- a/locale/tr_TR/gitlab.po +++ b/locale/tr_TR/gitlab.po @@ -308,7 +308,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -755,7 +755,7 @@ msgstr "" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6510,10 +6510,10 @@ msgstr "" msgid "Settings" msgstr "" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8108,7 +8108,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/uk/gitlab.po b/locale/uk/gitlab.po index 2f965fc0ff0..c8f5cf5cae8 100644 --- a/locale/uk/gitlab.po +++ b/locale/uk/gitlab.po @@ -376,7 +376,7 @@ msgstr "<strong>%{pushes}</strong> відправок (push), більше ніРmsgid "<strong>Removes</strong> source branch" msgstr "<strong>ВидалÑÑ”</strong> гілку-джерело" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "'Runner' — це процеÑ, Ñкий виконує завданнÑ. Ви можете Ñтворити потрібну кількіÑÑ‚ÑŒ Runner'ів." msgid "A collection of graphs regarding Continuous Integration" @@ -823,7 +823,7 @@ msgstr "Ðртефакти" msgid "Ascending" msgstr "За зроÑтаннÑм" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "ПопроÑÑ–Ñ‚ÑŒ керівника групи, щоб налаштувати груповий Runner." msgid "Assertion consumer service URL" @@ -6606,10 +6606,10 @@ msgstr "вÑтановити пароль" msgid "Settings" msgstr "ÐалаштуваннÑ" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "Ðвтоматично налаштувати Ñпецифічний runner" msgid "Share" @@ -8212,7 +8212,7 @@ msgstr "Ви можете редагувати файли, лише перебу msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "Ви можете розв’Ñзати цей конфлікт Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð° допомогою інтерактивного режиму (викориÑтовуючи кнопки %{use_ours} та %{use_theirs}), або безпоÑередньо редагуючи файли. Закомітити зміни у %{branch_name}" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po index 969ce34ac5c..e93bfd7cfb8 100644 --- a/locale/zh_CN/gitlab.po +++ b/locale/zh_CN/gitlab.po @@ -274,7 +274,7 @@ msgstr "<strong>%{pushes}</strong> 个推é€ï¼Œè¶…å‰ <strong>%{people}</strong> msgid "<strong>Removes</strong> source branch" msgstr "<strong>åˆ é™¤</strong>æºåˆ†æ”¯" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "Runner是一个执行任务的进程。您å¯ä»¥æ ¹æ®éœ€è¦é…置任æ„æ•°é‡çš„Runner。" msgid "A collection of graphs regarding Continuous Integration" @@ -721,7 +721,7 @@ msgstr "产物" msgid "Ascending" msgstr "å‡åºæŽ’列" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "请群组维护者é…置一个群组级 Runner。" msgid "Assertion consumer service URL" @@ -6462,10 +6462,10 @@ msgstr "设置密ç " msgid "Settings" msgstr "设置" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "自动创建专用Runner" msgid "Share" @@ -8056,7 +8056,7 @@ msgstr "åªèƒ½åœ¨åˆ†æ”¯ä¸Šç¼–辑文件" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "您å¯ä»¥ä½¿ç”¨äº¤äº’模å¼ï¼Œé€šè¿‡é€‰æ‹© %{use_ours} 或 %{use_theirs} 按钮æ¥è§£å†³åˆå¹¶å†²çªã€‚也å¯ä»¥é€šè¿‡ç›´æŽ¥ç¼–辑文件æ¥è§£å†³åˆå¹¶å†²çªã€‚然åŽå°†è¿™äº›æ›´æ”¹æ交到 %{branch_name}" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po index 424ca95d24c..49fbfc224e4 100644 --- a/locale/zh_HK/gitlab.po +++ b/locale/zh_HK/gitlab.po @@ -274,7 +274,7 @@ msgstr "" msgid "<strong>Removes</strong> source branch" msgstr "" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "" msgid "A collection of graphs regarding Continuous Integration" @@ -721,7 +721,7 @@ msgstr "" msgid "Ascending" msgstr "" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "" msgid "Assertion consumer service URL" @@ -6462,10 +6462,10 @@ msgstr "è¨ç½®å¯†ç¢¼" msgid "Settings" msgstr "" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "" msgid "Share" @@ -8056,7 +8056,7 @@ msgstr "" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po index d7ca7996926..5c9746ad6b4 100644 --- a/locale/zh_TW/gitlab.po +++ b/locale/zh_TW/gitlab.po @@ -274,7 +274,7 @@ msgstr "æŽ¨é€ <strong>%{pushes}</strong> 個,<strong>%{people}</strong> å€‹è² msgid "<strong>Removes</strong> source branch" msgstr "<strong>刪除</strong>來æºåˆ†æ”¯" -msgid "A 'Runner' is a process which runs a job. You can setup as many Runners as you need." +msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need." msgstr "一個「執行器ã€æ˜¯ä¸€å€‹åŸ·è¡Œå·¥ä½œçš„é€²ç¨‹ã€‚ä½ å¯ä»¥å®‰è£ä½ 需è¦çš„多個執行器。" msgid "A collection of graphs regarding Continuous Integration" @@ -721,7 +721,7 @@ msgstr "產物" msgid "Ascending" msgstr "é †åº" -msgid "Ask your group maintainer to setup a group Runner." +msgid "Ask your group maintainer to set up a group Runner." msgstr "è©¢å•æ‚¨çš„群組ç¶è·è€…以安è£ç¾¤çµ„執行器。" msgid "Assertion consumer service URL" @@ -6462,10 +6462,10 @@ msgstr "è¨å®šå¯†ç¢¼" msgid "Settings" msgstr "è¨å®š" -msgid "Setup a %{type} Runner manually" +msgid "Set up a %{type} Runner manually" msgstr "" -msgid "Setup a specific Runner automatically" +msgid "Set up a specific Runner automatically" msgstr "自動è¨ç½®ç‰¹å®šçš„執行器" msgid "Share" @@ -8056,7 +8056,7 @@ msgstr "您åªèƒ½åœ¨åˆ†æ”¯ä¸Šç·¨è¼¯æ–‡ä»¶" msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}" msgstr "您å¯ä»¥é€éŽä½¿ç”¨äº’動模å¼é¸æ“‡ %{use_ours} 或 %{use_theirs} 按鈕ã€æˆ–者是直接編輯檔案來解決åˆä½µè¡çªï¼Œä¸¦å°‡é€™äº›è®Šæ›´æ交到 %{branch_name}。" -msgid "You can setup jobs to only use Runners with specific tags. Separate tags with commas." +msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas." msgstr "" msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead." diff --git a/qa/qa/factory/resource/branch.rb b/qa/qa/factory/resource/branch.rb index bc252bf3148..60539992073 100644 --- a/qa/qa/factory/resource/branch.rb +++ b/qa/qa/factory/resource/branch.rb @@ -64,7 +64,7 @@ module QA end page.wait(reload: false) do - !page.first('.btn-create').disabled? + !page.first('.btn-success').disabled? end page.protect_branch diff --git a/qa/qa/page/admin/settings/main.rb b/qa/qa/page/admin/settings/main.rb index db3387b4557..73034ffe0d8 100644 --- a/qa/qa/page/admin/settings/main.rb +++ b/qa/qa/page/admin/settings/main.rb @@ -6,11 +6,11 @@ module QA include QA::Page::Settings::Common view 'app/views/admin/application_settings/show.html.haml' do - element :repository_storage_settings + element :terms_settings end def expand_repository_storage(&block) - expand_section(:repository_storage_settings) do + expand_section(:terms_settings) do RepositoryStorage.perform(&block) end end diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb index c200f14f4fb..befb7c1809a 100644 --- a/qa/qa/page/merge_request/show.rb +++ b/qa/qa/page/merge_request/show.rb @@ -5,6 +5,9 @@ module QA view 'app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue' do element :merge_button element :fast_forward_message, 'Fast-forward merge without a merge commit' + element :merge_moment_dropdown + element :merge_when_pipeline_succeeds_option + element :merge_immediately_option end view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue' do @@ -27,7 +30,20 @@ module QA def has_merge_button? refresh - has_selector?('.accept-merge-request') + has_css?(element_selector_css(:merge_button)) + end + + def has_merge_options? + has_css?(element_selector_css(:merge_moment_dropdown)) + end + + def merge_immediately + if has_merge_options? + click_element :merge_moment_dropdown + click_element :merge_immediately_option + else + click_element :merge_button + end end def rebase! @@ -59,7 +75,7 @@ module QA !first(element_selector_css(:merge_button)).disabled? end - click_element :merge_button + merge_immediately wait(reload: false) do has_text?('The changes were merged into') diff --git a/rubocop/cop/ruby_interpolation_in_translation.rb b/rubocop/cop/ruby_interpolation_in_translation.rb index b9411fcfd6c..c431b4a1977 100644 --- a/rubocop/cop/ruby_interpolation_in_translation.rb +++ b/rubocop/cop/ruby_interpolation_in_translation.rb @@ -6,7 +6,6 @@ module RuboCop MSG = "Don't use ruby interpolation \#{} inside translated strings, instead use \%{}" TRANSLATION_METHODS = ':_ :s_ :N_ :n_' - RUBY_INTERPOLATION_REGEX = /.*\#\{.*\}/ def_node_matcher :translation_method?, <<~PATTERN (send nil? {#{TRANSLATION_METHODS}} $dstr ...) diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb index 026dea8d22c..a6ab6a5696a 100644 --- a/spec/features/admin/admin_runners_spec.rb +++ b/spec/features/admin/admin_runners_spec.rb @@ -19,7 +19,7 @@ describe "Admin Runners" do create(:ci_build, pipeline: pipeline, runner_id: runner.id) visit admin_runners_path - expect(page).to have_text "Setup a shared Runner manually" + expect(page).to have_text "Set up a shared Runner manually" expect(page).to have_text "Runners currently online: 1" end @@ -125,7 +125,7 @@ describe "Admin Runners" do end it 'has all necessary texts including no runner message' do - expect(page).to have_text "Setup a shared Runner manually" + expect(page).to have_text "Set up a shared Runner manually" expect(page).to have_text "Runners currently online: 0" expect(page).to have_text 'No runners found' end diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index 3c65b5898b4..3fb818af8f0 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -9,340 +9,375 @@ describe 'Admin updates settings' do before do stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') sign_in(admin) - visit admin_application_settings_path end - it 'Change visibility settings' do - page.within('.as-visibility-access') do - choose "application_setting_default_project_visibility_20" - click_button 'Save changes' + context 'General page' do + before do + visit admin_application_settings_path end - expect(page).to have_content "Application settings saved successfully" - end + it 'Change visibility settings' do + page.within('.as-visibility-access') do + choose "application_setting_default_project_visibility_20" + click_button 'Save changes' + end - it 'Uncheck all restricted visibility levels' do - page.within('.as-visibility-access') do - find('#application_setting_visibility_level_0').set(false) - find('#application_setting_visibility_level_10').set(false) - find('#application_setting_visibility_level_20').set(false) - click_button 'Save changes' + expect(page).to have_content "Application settings saved successfully" end - expect(page).to have_content "Application settings saved successfully" - expect(find('#application_setting_visibility_level_0')).not_to be_checked - expect(find('#application_setting_visibility_level_10')).not_to be_checked - expect(find('#application_setting_visibility_level_20')).not_to be_checked - end + it 'Uncheck all restricted visibility levels' do + page.within('.as-visibility-access') do + find('#application_setting_visibility_level_0').set(false) + find('#application_setting_visibility_level_10').set(false) + find('#application_setting_visibility_level_20').set(false) + click_button 'Save changes' + end + + expect(page).to have_content "Application settings saved successfully" + expect(find('#application_setting_visibility_level_0')).not_to be_checked + expect(find('#application_setting_visibility_level_10')).not_to be_checked + expect(find('#application_setting_visibility_level_20')).not_to be_checked + end + + it 'Modify import sources' do + expect(Gitlab::CurrentSettings.import_sources).not_to be_empty + + page.within('.as-visibility-access') do + Gitlab::ImportSources.options.map do |name, _| + uncheck name + end + + click_button 'Save changes' + end - it 'Modify import sources' do - expect(Gitlab::CurrentSettings.import_sources).not_to be_empty + expect(page).to have_content "Application settings saved successfully" + expect(Gitlab::CurrentSettings.import_sources).to be_empty - page.within('.as-visibility-access') do - Gitlab::ImportSources.options.map do |name, _| - uncheck name + page.within('.as-visibility-access') do + check "Repo by URL" + click_button 'Save changes' end - click_button 'Save changes' + expect(page).to have_content "Application settings saved successfully" + expect(Gitlab::CurrentSettings.import_sources).to eq(['git']) end - expect(page).to have_content "Application settings saved successfully" - expect(Gitlab::CurrentSettings.import_sources).to be_empty + it 'Change Visibility and Access Controls' do + page.within('.as-visibility-access') do + uncheck 'Project export enabled' + click_button 'Save changes' + end - page.within('.as-visibility-access') do - check "Repo by URL" - click_button 'Save changes' + expect(Gitlab::CurrentSettings.project_export_enabled).to be_falsey + expect(page).to have_content "Application settings saved successfully" end - expect(page).to have_content "Application settings saved successfully" - expect(Gitlab::CurrentSettings.import_sources).to eq(['git']) - end + it 'Change Keys settings' do + page.within('.as-visibility-access') do + select 'Are forbidden', from: 'RSA SSH keys' + select 'Are allowed', from: 'DSA SSH keys' + select 'Must be at least 384 bits', from: 'ECDSA SSH keys' + select 'Are forbidden', from: 'ED25519 SSH keys' + click_on 'Save changes' + end + + forbidden = ApplicationSetting::FORBIDDEN_KEY_VALUE.to_s - it 'Change Visibility and Access Controls' do - page.within('.as-visibility-access') do - uncheck 'Project export enabled' - click_button 'Save changes' + expect(page).to have_content 'Application settings saved successfully' + expect(find_field('RSA SSH keys').value).to eq(forbidden) + expect(find_field('DSA SSH keys').value).to eq('0') + expect(find_field('ECDSA SSH keys').value).to eq('384') + expect(find_field('ED25519 SSH keys').value).to eq(forbidden) end - expect(Gitlab::CurrentSettings.project_export_enabled).to be_falsey - expect(page).to have_content "Application settings saved successfully" - end + it 'Change Account and Limit Settings' do + page.within('.as-account-limit') do + uncheck 'Gravatar enabled' + click_button 'Save changes' + end - it 'Change Account and Limit Settings' do - page.within('.as-account-limit') do - uncheck 'Gravatar enabled' - click_button 'Save changes' + expect(Gitlab::CurrentSettings.gravatar_enabled).to be_falsey + expect(page).to have_content "Application settings saved successfully" end - expect(Gitlab::CurrentSettings.gravatar_enabled).to be_falsey - expect(page).to have_content "Application settings saved successfully" - end + it 'Change New users set to external', :js do + user_internal_regex = find('#application_setting_user_default_internal_regex', visible: :all) - it 'Change New users set to external', :js do - user_internal_regex = find('#application_setting_user_default_internal_regex', visible: :all) + expect(user_internal_regex).to be_readonly + expect(user_internal_regex['placeholder']).to eq 'To define internal users, first enable new users set to external' - expect(user_internal_regex).to be_readonly - expect(user_internal_regex['placeholder']).to eq 'To define internal users, first enable new users set to external' + check 'application_setting_user_default_external' - check 'application_setting_user_default_external' + expect(user_internal_regex).not_to be_readonly + expect(user_internal_regex['placeholder']).to eq 'Regex pattern' + end - expect(user_internal_regex).not_to be_readonly - expect(user_internal_regex['placeholder']).to eq 'Regex pattern' - end + it 'Change Sign-in restrictions' do + page.within('.as-signin') do + fill_in 'Home page URL', with: 'https://about.gitlab.com/' + click_button 'Save changes' + end - it 'Change Sign-in restrictions' do - page.within('.as-signin') do - fill_in 'Home page URL', with: 'https://about.gitlab.com/' - click_button 'Save changes' + expect(Gitlab::CurrentSettings.home_page_url).to eq "https://about.gitlab.com/" + expect(page).to have_content "Application settings saved successfully" end - expect(Gitlab::CurrentSettings.home_page_url).to eq "https://about.gitlab.com/" - expect(page).to have_content "Application settings saved successfully" - end + it 'Terms of Service' do + # Already have the admin accept terms, so they don't need to accept in this spec. + _existing_terms = create(:term) + accept_terms(admin) - it 'Terms of Service' do - # Already have the admin accept terms, so they don't need to accept in this spec. - _existing_terms = create(:term) - accept_terms(admin) + page.within('.as-terms') do + check 'Require all users to accept Terms of Service and Privacy Policy when they access GitLab.' + fill_in 'Terms of Service Agreement', with: 'Be nice!' + click_button 'Save changes' + end - page.within('.as-terms') do - check 'Require all users to accept Terms of Service and Privacy Policy when they access GitLab.' - fill_in 'Terms of Service Agreement', with: 'Be nice!' - click_button 'Save changes' + expect(Gitlab::CurrentSettings.enforce_terms).to be(true) + expect(Gitlab::CurrentSettings.terms).to eq 'Be nice!' + expect(page).to have_content 'Application settings saved successfully' end - expect(Gitlab::CurrentSettings.enforce_terms).to be(true) - expect(Gitlab::CurrentSettings.terms).to eq 'Be nice!' - expect(page).to have_content 'Application settings saved successfully' - end + it 'Modify oauth providers' do + expect(Gitlab::CurrentSettings.disabled_oauth_sign_in_sources).to be_empty - it 'Modify oauth providers' do - expect(Gitlab::CurrentSettings.disabled_oauth_sign_in_sources).to be_empty + page.within('.as-signin') do + uncheck 'Google' + click_button 'Save changes' + end - page.within('.as-signin') do - uncheck 'Google' - click_button 'Save changes' - end + expect(page).to have_content "Application settings saved successfully" + expect(Gitlab::CurrentSettings.disabled_oauth_sign_in_sources).to include('google_oauth2') - expect(page).to have_content "Application settings saved successfully" - expect(Gitlab::CurrentSettings.disabled_oauth_sign_in_sources).to include('google_oauth2') + page.within('.as-signin') do + check "Google" + click_button 'Save changes' + end - page.within('.as-signin') do - check "Google" - click_button 'Save changes' + expect(page).to have_content "Application settings saved successfully" + expect(Gitlab::CurrentSettings.disabled_oauth_sign_in_sources).not_to include('google_oauth2') end - expect(page).to have_content "Application settings saved successfully" - expect(Gitlab::CurrentSettings.disabled_oauth_sign_in_sources).not_to include('google_oauth2') - end + it 'Oauth providers do not raise validation errors when saving unrelated changes' do + expect(Gitlab::CurrentSettings.disabled_oauth_sign_in_sources).to be_empty - it 'Oauth providers do not raise validation errors when saving unrelated changes' do - expect(Gitlab::CurrentSettings.disabled_oauth_sign_in_sources).to be_empty + page.within('.as-signin') do + uncheck 'Google' + click_button 'Save changes' + end - page.within('.as-signin') do - uncheck 'Google' - click_button 'Save changes' - end + expect(page).to have_content "Application settings saved successfully" + expect(Gitlab::CurrentSettings.disabled_oauth_sign_in_sources).to include('google_oauth2') - expect(page).to have_content "Application settings saved successfully" - expect(Gitlab::CurrentSettings.disabled_oauth_sign_in_sources).to include('google_oauth2') + # Remove google_oauth2 from the Omniauth strategies + allow(Devise).to receive(:omniauth_providers).and_return([]) - # Remove google_oauth2 from the Omniauth strategies - allow(Devise).to receive(:omniauth_providers).and_return([]) + # Save an unrelated setting + page.within('.as-terms') do + click_button 'Save changes' + end - # Save an unrelated setting - page.within('.as-ci-cd') do - click_button 'Save changes' + expect(page).to have_content "Application settings saved successfully" + expect(Gitlab::CurrentSettings.disabled_oauth_sign_in_sources).to include('google_oauth2') end - expect(page).to have_content "Application settings saved successfully" - expect(Gitlab::CurrentSettings.disabled_oauth_sign_in_sources).to include('google_oauth2') - end + it 'Configure web terminal' do + page.within('.as-terminal') do + fill_in 'Max session time', with: 15 + click_button 'Save changes' + end - it 'Change Help page' do - page.within('.as-help-page') do - fill_in 'Help page text', with: 'Example text' - check 'Hide marketing-related entries from help' - fill_in 'Support page URL', with: 'http://example.com/help' - click_button 'Save changes' + expect(page).to have_content "Application settings saved successfully" + expect(Gitlab::CurrentSettings.terminal_max_session_time).to eq(15) end - - expect(Gitlab::CurrentSettings.help_page_text).to eq "Example text" - expect(Gitlab::CurrentSettings.help_page_hide_commercial_content).to be_truthy - expect(Gitlab::CurrentSettings.help_page_support_url).to eq "http://example.com/help" - expect(page).to have_content "Application settings saved successfully" end - it 'Change Pages settings' do - page.within('.as-pages') do - fill_in 'Maximum size of pages (MB)', with: 15 - check 'Require users to prove ownership of custom domains' - click_button 'Save changes' + context 'Integrations page' do + before do + visit integrations_admin_application_settings_path end - expect(Gitlab::CurrentSettings.max_pages_size).to eq 15 - expect(Gitlab::CurrentSettings.pages_domain_verification_enabled?).to be_truthy - expect(page).to have_content "Application settings saved successfully" - end + it 'Enable hiding third party offers' do + page.within('.as-third-party-offers') do + check 'Do not display offers from third parties within GitLab' + click_button 'Save changes' + end - it 'Change CI/CD settings' do - page.within('.as-ci-cd') do - check 'Default to Auto DevOps pipeline for all projects' - fill_in 'Auto devops domain', with: 'domain.com' - click_button 'Save changes' + expect(page).to have_content "Application settings saved successfully" + expect(Gitlab::CurrentSettings.hide_third_party_offers).to be true end - expect(Gitlab::CurrentSettings.auto_devops_enabled?).to be true - expect(Gitlab::CurrentSettings.auto_devops_domain).to eq('domain.com') - expect(page).to have_content "Application settings saved successfully" - end + it 'Change Slack Notifications Service template settings' do + first(:link, 'Service Templates').click + click_link 'Slack notifications' + fill_in 'Webhook', with: 'http://localhost' + fill_in 'Username', with: 'test_user' + fill_in 'service_push_channel', with: '#test_channel' + page.check('Notify only broken pipelines') + page.check('Notify only default branch') - it 'Change Influx settings' do - page.within('.as-influx') do - check 'Enable InfluxDB Metrics' - click_button 'Save changes' - end + check_all_events + click_on 'Save' - expect(Gitlab::CurrentSettings.metrics_enabled?).to be true - expect(page).to have_content "Application settings saved successfully" - end + expect(page).to have_content 'Application settings saved successfully' - it 'Change Prometheus settings' do - page.within('.as-prometheus') do - check 'Enable Prometheus Metrics' - click_button 'Save changes' - end + click_link 'Slack notifications' - expect(Gitlab::CurrentSettings.prometheus_metrics_enabled?).to be true - expect(page).to have_content "Application settings saved successfully" + page.all('input[type=checkbox]').each do |checkbox| + expect(checkbox).to be_checked + end + expect(find_field('Webhook').value).to eq 'http://localhost' + expect(find_field('Username').value).to eq 'test_user' + expect(find('#service_push_channel').value).to eq '#test_channel' + end end - it 'Change Performance bar settings' do - group = create(:group) + context 'CI/CD page' do + it 'Change CI/CD settings' do + visit ci_cd_admin_application_settings_path + + page.within('.as-ci-cd') do + check 'Default to Auto DevOps pipeline for all projects' + fill_in 'Auto devops domain', with: 'domain.com' + click_button 'Save changes' + end - page.within('.as-performance-bar') do - check 'Enable the Performance Bar' - fill_in 'Allowed group', with: group.path - click_on 'Save changes' + expect(Gitlab::CurrentSettings.auto_devops_enabled?).to be true + expect(Gitlab::CurrentSettings.auto_devops_domain).to eq('domain.com') + expect(page).to have_content "Application settings saved successfully" end + end - expect(page).to have_content "Application settings saved successfully" - expect(find_field('Enable the Performance Bar')).to be_checked - expect(find_field('Allowed group').value).to eq group.path + context 'Reporting page' do + it 'Change Spam settings' do + visit reporting_admin_application_settings_path - page.within('.as-performance-bar') do - uncheck 'Enable the Performance Bar' - click_on 'Save changes' - end + page.within('.as-spam') do + check 'Enable reCAPTCHA' + fill_in 'reCAPTCHA Site Key', with: 'key' + fill_in 'reCAPTCHA Private Key', with: 'key' + fill_in 'IPs per user', with: 15 + click_button 'Save changes' + end - expect(page).to have_content 'Application settings saved successfully' - expect(find_field('Enable the Performance Bar')).not_to be_checked - expect(find_field('Allowed group').value).to be_nil + expect(page).to have_content "Application settings saved successfully" + expect(Gitlab::CurrentSettings.recaptcha_enabled).to be true + expect(Gitlab::CurrentSettings.unique_ips_limit_per_user).to eq(15) + end end - it 'Change Background jobs settings' do - page.within('.as-background') do - fill_in 'Throttling Factor', with: 1 - click_button 'Save changes' + context 'Metrics and profiling page' do + before do + visit metrics_and_profiling_admin_application_settings_path end - expect(Gitlab::CurrentSettings.sidekiq_throttling_factor).to eq(1) - expect(page).to have_content "Application settings saved successfully" - end + it 'Change Influx settings' do + page.within('.as-influx') do + check 'Enable InfluxDB Metrics' + click_button 'Save changes' + end - it 'Change Spam settings' do - page.within('.as-spam') do - check 'Enable reCAPTCHA' - fill_in 'reCAPTCHA Site Key', with: 'key' - fill_in 'reCAPTCHA Private Key', with: 'key' - fill_in 'IPs per user', with: 15 - click_button 'Save changes' + expect(Gitlab::CurrentSettings.metrics_enabled?).to be true + expect(page).to have_content "Application settings saved successfully" end - expect(page).to have_content "Application settings saved successfully" - expect(Gitlab::CurrentSettings.recaptcha_enabled).to be true - expect(Gitlab::CurrentSettings.unique_ips_limit_per_user).to eq(15) - end + it 'Change Prometheus settings' do + page.within('.as-prometheus') do + check 'Enable Prometheus Metrics' + click_button 'Save changes' + end - it 'Configure web terminal' do - page.within('.as-terminal') do - fill_in 'Max session time', with: 15 - click_button 'Save changes' + expect(Gitlab::CurrentSettings.prometheus_metrics_enabled?).to be true + expect(page).to have_content "Application settings saved successfully" end - expect(page).to have_content "Application settings saved successfully" - expect(Gitlab::CurrentSettings.terminal_max_session_time).to eq(15) - end + it 'Change Performance bar settings' do + group = create(:group) - it 'Enable outbound requests' do - page.within('.as-outbound') do - check 'Allow requests to the local network from hooks and services' - click_button 'Save changes' - end + page.within('.as-performance-bar') do + check 'Enable the Performance Bar' + fill_in 'Allowed group', with: group.path + click_on 'Save changes' + end - expect(page).to have_content "Application settings saved successfully" - expect(Gitlab::CurrentSettings.allow_local_requests_from_hooks_and_services).to be true - end + expect(page).to have_content "Application settings saved successfully" + expect(find_field('Enable the Performance Bar')).to be_checked + expect(find_field('Allowed group').value).to eq group.path + + page.within('.as-performance-bar') do + uncheck 'Enable the Performance Bar' + click_on 'Save changes' + end - it 'Enable hiding third party offers' do - page.within('.as-third-party-offers') do - check 'Do not display offers from third parties within GitLab' - click_button 'Save changes' + expect(page).to have_content 'Application settings saved successfully' + expect(find_field('Enable the Performance Bar')).not_to be_checked + expect(find_field('Allowed group').value).to be_nil end - expect(page).to have_content "Application settings saved successfully" - expect(Gitlab::CurrentSettings.hide_third_party_offers).to be true - end + it 'loads usage ping payload on click', :js do + expect(page).to have_button 'Preview payload' - it 'Change Slack Notifications Service template settings' do - first(:link, 'Service Templates').click - click_link 'Slack notifications' - fill_in 'Webhook', with: 'http://localhost' - fill_in 'Username', with: 'test_user' - fill_in 'service_push_channel', with: '#test_channel' - page.check('Notify only broken pipelines') - page.check('Notify only default branch') + find('.js-usage-ping-payload-trigger').click - check_all_events - click_on 'Save' + expect(page).to have_selector '.js-usage-ping-payload' + expect(page).to have_button 'Hide payload' + end + end - expect(page).to have_content 'Application settings saved successfully' + context 'Network page' do + it 'Enable outbound requests' do + visit network_admin_application_settings_path - click_link 'Slack notifications' + page.within('.as-outbound') do + check 'Allow requests to the local network from hooks and services' + click_button 'Save changes' + end - page.all('input[type=checkbox]').each do |checkbox| - expect(checkbox).to be_checked + expect(page).to have_content "Application settings saved successfully" + expect(Gitlab::CurrentSettings.allow_local_requests_from_hooks_and_services).to be true end - expect(find_field('Webhook').value).to eq 'http://localhost' - expect(find_field('Username').value).to eq 'test_user' - expect(find('#service_push_channel').value).to eq '#test_channel' end - it 'Change Keys settings' do - page.within('.as-visibility-access') do - select 'Are forbidden', from: 'RSA SSH keys' - select 'Are allowed', from: 'DSA SSH keys' - select 'Must be at least 384 bits', from: 'ECDSA SSH keys' - select 'Are forbidden', from: 'ED25519 SSH keys' - click_on 'Save changes' + context 'Preferences page' do + before do + visit preferences_admin_application_settings_path end - forbidden = ApplicationSetting::FORBIDDEN_KEY_VALUE.to_s + it 'Change Help page' do + page.within('.as-help-page') do + fill_in 'Help page text', with: 'Example text' + check 'Hide marketing-related entries from help' + fill_in 'Support page URL', with: 'http://example.com/help' + click_button 'Save changes' + end - expect(page).to have_content 'Application settings saved successfully' - expect(find_field('RSA SSH keys').value).to eq(forbidden) - expect(find_field('DSA SSH keys').value).to eq('0') - expect(find_field('ECDSA SSH keys').value).to eq('384') - expect(find_field('ED25519 SSH keys').value).to eq(forbidden) - end + expect(Gitlab::CurrentSettings.help_page_text).to eq "Example text" + expect(Gitlab::CurrentSettings.help_page_hide_commercial_content).to be_truthy + expect(Gitlab::CurrentSettings.help_page_support_url).to eq "http://example.com/help" + expect(page).to have_content "Application settings saved successfully" + end + + it 'Change Pages settings' do + page.within('.as-pages') do + fill_in 'Maximum size of pages (MB)', with: 15 + check 'Require users to prove ownership of custom domains' + click_button 'Save changes' + end - it 'loads usage ping payload on click', :js do - expect(page).to have_button 'Preview payload' + expect(Gitlab::CurrentSettings.max_pages_size).to eq 15 + expect(Gitlab::CurrentSettings.pages_domain_verification_enabled?).to be_truthy + expect(page).to have_content "Application settings saved successfully" + end - find('.js-usage-ping-payload-trigger').click + it 'Change Background jobs settings' do + page.within('.as-background') do + fill_in 'Throttling Factor', with: 1 + click_button 'Save changes' + end - expect(page).to have_selector '.js-usage-ping-payload' - expect(page).to have_button 'Hide payload' + expect(Gitlab::CurrentSettings.sidekiq_throttling_factor).to eq(1) + expect(page).to have_content "Application settings saved successfully" + end end def check_all_events diff --git a/spec/features/admin/admin_uses_repository_checks_spec.rb b/spec/features/admin/admin_uses_repository_checks_spec.rb index e658f1b6738..d04bb9acd9e 100644 --- a/spec/features/admin/admin_uses_repository_checks_spec.rb +++ b/spec/features/admin/admin_uses_repository_checks_spec.rb @@ -33,7 +33,7 @@ describe 'Admin uses repository checks' do end it 'to clear all repository checks', :js do - visit admin_application_settings_path + visit repository_admin_application_settings_path expect(RepositoryCheck::ClearWorker).to receive(:perform_async) diff --git a/spec/features/dashboard/group_spec.rb b/spec/features/dashboard/group_spec.rb index 1c7932e7964..e57fcde8b2c 100644 --- a/spec/features/dashboard/group_spec.rb +++ b/spec/features/dashboard/group_spec.rb @@ -13,7 +13,7 @@ RSpec.describe 'Dashboard Group' do it 'creates new group', :js do visit dashboard_groups_path - find('.btn-new').click + find('.btn-success').click new_path = 'Samurai' new_description = 'Tokugawa Shogunate' diff --git a/spec/features/labels_hierarchy_spec.rb b/spec/features/labels_hierarchy_spec.rb index 6f917f522bc..09904cb907f 100644 --- a/spec/features/labels_hierarchy_spec.rb +++ b/spec/features/labels_hierarchy_spec.rb @@ -156,7 +156,7 @@ describe 'Labels Hierarchy', :js, :nested_groups do find('a.label-item', text: parent_group_label.title).click find('a.label-item', text: project_label_1.title).click - find('.btn-create').click + find('.btn-success').click expect(page.find('.issue-details h2.title')).to have_content('new created issue') expect(page).to have_selector('span.badge', text: grandparent_group_label.title) 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 b6ed3686de2..fa148715855 100644 --- a/spec/features/merge_request/user_posts_diff_notes_spec.rb +++ b/spec/features/merge_request/user_posts_diff_notes_spec.rb @@ -200,23 +200,20 @@ describe 'Merge request > User posts diff notes', :js do end context 'with a new line' do - # TODO: https://gitlab.com/gitlab-org/gitlab-ce/issues/48034 - xit 'allows commenting' do - should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]').find(:xpath, '..')) + it 'allows commenting' do + should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_10_9"]')) end end context 'with an old line' do - # TODO: https://gitlab.com/gitlab-org/gitlab-ce/issues/48034 - xit 'allows commenting' do - should_allow_commenting(find('[id="6eb14e00385d2fb284765eb1cd8d420d33d63fc9_22_22"]').find(:xpath, '..')) + it 'allows commenting' do + should_allow_commenting(find('[id="6eb14e00385d2fb284765eb1cd8d420d33d63fc9_22_22"]')) end end context 'with an unchanged line' do - # TODO: https://gitlab.com/gitlab-org/gitlab-ce/issues/48034 - xit 'allows commenting' do - should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7"]').find(:xpath, '..')) + it 'allows commenting' do + should_allow_commenting(find('[id="2f6fcd96b88b36ce98c38da085c795a27d92a3dd_7_7"]')) end end diff --git a/spec/features/merge_request/user_posts_notes_spec.rb b/spec/features/merge_request/user_posts_notes_spec.rb index 260c5f9c28b..ee5f5377ca6 100644 --- a/spec/features/merge_request/user_posts_notes_spec.rb +++ b/spec/features/merge_request/user_posts_notes_spec.rb @@ -111,7 +111,7 @@ describe 'Merge request > User posts notes', :js do it 'allows using markdown buttons after saving a note and then trying to edit it again' do page.within('.current-note-edit-form') do fill_in 'note[note]', with: 'This is the new content' - find('.btn-save').click + find('.btn-success').click end find('.note').hover @@ -129,7 +129,7 @@ describe 'Merge request > User posts notes', :js do it 'appends the edited at time to the note' do page.within('.current-note-edit-form') do fill_in 'note[note]', with: 'Some new content' - find('.btn-save').click + find('.btn-success').click end page.within("#note_#{note.id}") do diff --git a/spec/features/merge_request/user_resolves_conflicts_spec.rb b/spec/features/merge_request/user_resolves_conflicts_spec.rb index 629052442b4..50c723776a3 100644 --- a/spec/features/merge_request/user_resolves_conflicts_spec.rb +++ b/spec/features/merge_request/user_resolves_conflicts_spec.rb @@ -44,9 +44,7 @@ describe 'Merge request > User resolves conflicts', :js do within find('.diff-file', text: 'files/ruby/regex.rb') do expect(page).to have_selector('.line_content.new', text: "def username_regexp") - expect(page).not_to have_selector('.line_content.new', text: "def username_regex") expect(page).to have_selector('.line_content.new', text: "def project_name_regexp") - expect(page).not_to have_selector('.line_content.new', text: "def project_name_regex") expect(page).to have_selector('.line_content.new', text: "def path_regexp") expect(page).to have_selector('.line_content.new', text: "def archive_formats_regexp") expect(page).to have_selector('.line_content.new', text: "def git_reference_regexp") @@ -110,12 +108,8 @@ describe 'Merge request > User resolves conflicts', :js do click_link('conflicts', href: %r{/conflicts\Z}) end - # TODO: https://gitlab.com/gitlab-org/gitlab-ce/issues/48034 - # include_examples "conflicts are resolved in Interactive mode" - # include_examples "conflicts are resolved in Edit inline mode" - - it 'prevents RSpec/EmptyExampleGroup' do - end + include_examples "conflicts are resolved in Interactive mode" + include_examples "conflicts are resolved in Edit inline mode" end context 'in Parallel view mode' do @@ -124,12 +118,8 @@ describe 'Merge request > User resolves conflicts', :js do click_button 'Side-by-side' end - # TODO: https://gitlab.com/gitlab-org/gitlab-ce/issues/48034 - # include_examples "conflicts are resolved in Interactive mode" - # include_examples "conflicts are resolved in Edit inline mode" - - it 'prevents RSpec/EmptyExampleGroup' do - end + include_examples "conflicts are resolved in Interactive mode" + include_examples "conflicts are resolved in Edit inline mode" end end diff --git a/spec/features/projects/members/invite_group_spec.rb b/spec/features/projects/members/invite_group_spec.rb index 0fb3eb20b5b..fceead0b45e 100644 --- a/spec/features/projects/members/invite_group_spec.rb +++ b/spec/features/projects/members/invite_group_spec.rb @@ -40,7 +40,7 @@ describe 'Project > Members > Invite group', :js do select2 group_to_share_with.id, from: '#link_group_id' page.find('body').click - find('.btn-create').click + find('.btn-success').click page.within('.project-members-groups') do expect(page).to have_content(group_to_share_with.name) @@ -122,7 +122,7 @@ describe 'Project > Members > Invite group', :js do fill_in 'expires_at_groups', with: (Time.now + 4.5.days).strftime('%Y-%m-%d') click_on 'invite-group-tab' - find('.btn-create').click + find('.btn-success').click end it 'the group link shows the expiration time with a warning class' do diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb index 0c6cf3dc477..cb7a912946c 100644 --- a/spec/features/runners_spec.rb +++ b/spec/features/runners_spec.rb @@ -198,7 +198,7 @@ describe 'Runners' do expect(page).to have_content 'This group does not provide any group Runners yet' expect(page).to have_content 'Group maintainers can register group runners in the Group CI/CD settings' - expect(page).not_to have_content 'Ask your group maintainer to setup a group Runner' + expect(page).not_to have_content 'Ask your group maintainer to set up a group Runner' end end end @@ -224,7 +224,7 @@ describe 'Runners' do expect(page).to have_content 'This group does not provide any group Runners yet.' expect(page).not_to have_content 'Group maintainers can register group runners in the Group CI/CD settings' - expect(page).to have_content 'Ask your group maintainer to setup a group Runner.' + expect(page).to have_content 'Ask your group maintainer to set up a group Runner.' end end diff --git a/spec/features/snippets/notes_on_personal_snippets_spec.rb b/spec/features/snippets/notes_on_personal_snippets_spec.rb index 1442e011d52..eeacaf5f72a 100644 --- a/spec/features/snippets/notes_on_personal_snippets_spec.rb +++ b/spec/features/snippets/notes_on_personal_snippets_spec.rb @@ -103,7 +103,7 @@ describe 'Comments on personal snippets', :js do page.within('.current-note-edit-form') do fill_in 'note[note]', with: 'new content' - find('.btn-save').click + find('.btn-success').click end page.within("#notes-list li#note_#{snippet_notes[0].id}") do diff --git a/spec/javascripts/shortcuts_issuable_spec.js b/spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js index a4753ab7cde..01b5bc112b2 100644 --- a/spec/javascripts/shortcuts_issuable_spec.js +++ b/spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js @@ -1,6 +1,6 @@ import $ from 'jquery'; import initCopyAsGFM from '~/behaviors/markdown/copy_as_gfm'; -import ShortcutsIssuable from '~/shortcuts_issuable'; +import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable'; initCopyAsGFM(); diff --git a/spec/javascripts/boards/board_blank_state_spec.js b/spec/javascripts/boards/board_blank_state_spec.js index 89a4fae4b59..0e4e1697fd0 100644 --- a/spec/javascripts/boards/board_blank_state_spec.js +++ b/spec/javascripts/boards/board_blank_state_spec.js @@ -64,7 +64,7 @@ describe('Boards blank state', () => { }); it('creates pre-defined labels', (done) => { - vm.$el.querySelector('.btn-create').click(); + vm.$el.querySelector('.btn-success').click(); setTimeout(() => { expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2); @@ -78,7 +78,7 @@ describe('Boards blank state', () => { it('resets the store if request fails', (done) => { fail = true; - vm.$el.querySelector('.btn-create').click(); + vm.$el.querySelector('.btn-success').click(); setTimeout(() => { expect(gl.issueBoards.BoardsStore.welcomeIsHidden()).toBeFalsy(); diff --git a/spec/javascripts/diffs/store/actions_spec.js b/spec/javascripts/diffs/store/actions_spec.js index cfb8f862598..4c662fac231 100644 --- a/spec/javascripts/diffs/store/actions_spec.js +++ b/spec/javascripts/diffs/store/actions_spec.js @@ -5,7 +5,23 @@ import { INLINE_DIFF_VIEW_TYPE, PARALLEL_DIFF_VIEW_TYPE, } from '~/diffs/constants'; -import * as actions from '~/diffs/store/actions'; +import actions, { + setBaseConfig, + fetchDiffFiles, + assignDiscussionsToDiff, + removeDiscussionsFromDiff, + startRenderDiffsQueue, + setInlineDiffViewType, + setParallelDiffViewType, + showCommentForm, + cancelCommentForm, + loadMoreLines, + scrollToLineIfNeededInline, + scrollToLineIfNeededParallel, + loadCollapsedDiff, + expandAllFiles, + toggleFileDiscussions, +} from '~/diffs/store/actions'; import * as types from '~/diffs/store/mutation_types'; import { reduceDiscussionsToLineCodes } from '~/notes/stores/utils'; import axios from '~/lib/utils/axios_utils'; @@ -37,7 +53,7 @@ describe('DiffsStoreActions', () => { const projectPath = '/root/project'; testAction( - actions.setBaseConfig, + setBaseConfig, { endpoint, projectPath }, { endpoint: '', projectPath: '' }, [{ type: types.SET_BASE_CONFIG, payload: { endpoint, projectPath } }], @@ -55,7 +71,7 @@ describe('DiffsStoreActions', () => { mock.onGet(endpoint).reply(200, res); testAction( - actions.fetchDiffFiles, + fetchDiffFiles, {}, { endpoint }, [ @@ -139,7 +155,7 @@ describe('DiffsStoreActions', () => { const discussions = reduceDiscussionsToLineCodes([singleDiscussion]); testAction( - actions.assignDiscussionsToDiff, + assignDiscussionsToDiff, discussions, state, [ @@ -157,6 +173,7 @@ describe('DiffsStoreActions', () => { newPath: 'file1', oldLine: 5, oldPath: 'file2', + lineCode: 'ABC_1_1', }, }, }, @@ -207,7 +224,7 @@ describe('DiffsStoreActions', () => { }; testAction( - actions.removeDiscussionsFromDiff, + removeDiscussionsFromDiff, singleDiscussion, state, [ @@ -251,8 +268,7 @@ describe('DiffsStoreActions', () => { }); }; - actions - .startRenderDiffsQueue({ state, commit: pseudoCommit }) + startRenderDiffsQueue({ state, commit: pseudoCommit }) .then(() => { expect(state.diffFiles[0].renderIt).toBeTruthy(); expect(state.diffFiles[1].renderIt).toBeTruthy(); @@ -268,7 +284,7 @@ describe('DiffsStoreActions', () => { describe('setInlineDiffViewType', () => { it('should set diff view type to inline and also set the cookie properly', done => { testAction( - actions.setInlineDiffViewType, + setInlineDiffViewType, null, {}, [{ type: types.SET_DIFF_VIEW_TYPE, payload: INLINE_DIFF_VIEW_TYPE }], @@ -286,7 +302,7 @@ describe('DiffsStoreActions', () => { describe('setParallelDiffViewType', () => { it('should set diff view type to parallel and also set the cookie properly', done => { testAction( - actions.setParallelDiffViewType, + setParallelDiffViewType, null, {}, [{ type: types.SET_DIFF_VIEW_TYPE, payload: PARALLEL_DIFF_VIEW_TYPE }], @@ -306,7 +322,7 @@ describe('DiffsStoreActions', () => { const payload = { lineCode: 'lineCode' }; testAction( - actions.showCommentForm, + showCommentForm, payload, {}, [{ type: types.ADD_COMMENT_FORM_LINE, payload }], @@ -321,7 +337,7 @@ describe('DiffsStoreActions', () => { const payload = { lineCode: 'lineCode' }; testAction( - actions.cancelCommentForm, + cancelCommentForm, payload, {}, [{ type: types.REMOVE_COMMENT_FORM_LINE, payload }], @@ -343,7 +359,7 @@ describe('DiffsStoreActions', () => { mock.onGet(endpoint).reply(200, contextLines); testAction( - actions.loadMoreLines, + loadMoreLines, options, {}, [ @@ -369,7 +385,7 @@ describe('DiffsStoreActions', () => { mock.onGet(file.loadCollapsedDiffUrl).reply(200, data); testAction( - actions.loadCollapsedDiff, + loadCollapsedDiff, file, {}, [ @@ -390,7 +406,7 @@ describe('DiffsStoreActions', () => { describe('expandAllFiles', () => { it('should change the collapsed prop from the diffFiles', done => { testAction( - actions.expandAllFiles, + expandAllFiles, null, {}, [ @@ -414,7 +430,7 @@ describe('DiffsStoreActions', () => { const dispatch = jasmine.createSpy('dispatch'); - actions.toggleFileDiscussions({ getters, dispatch }); + toggleFileDiscussions({ getters, dispatch }); expect(dispatch).toHaveBeenCalledWith( 'collapseDiscussion', @@ -432,7 +448,7 @@ describe('DiffsStoreActions', () => { const dispatch = jasmine.createSpy(); - actions.toggleFileDiscussions({ getters, dispatch }); + toggleFileDiscussions({ getters, dispatch }); expect(dispatch).toHaveBeenCalledWith( 'expandDiscussion', @@ -450,7 +466,7 @@ describe('DiffsStoreActions', () => { const dispatch = jasmine.createSpy(); - actions.toggleFileDiscussions({ getters, dispatch }); + toggleFileDiscussions({ getters, dispatch }); expect(dispatch).toHaveBeenCalledWith( 'expandDiscussion', @@ -459,4 +475,111 @@ describe('DiffsStoreActions', () => { ); }); }); + + describe('scrollToLineIfNeededInline', () => { + const lineMock = { + lineCode: 'ABC_123', + }; + + it('should not call handleLocationHash when there is not hash', () => { + window.location.hash = ''; + + const handleLocationHashSpy = spyOnDependency(actions, 'handleLocationHash').and.stub(); + + scrollToLineIfNeededInline({}, lineMock); + + expect(handleLocationHashSpy).not.toHaveBeenCalled(); + }); + + it('should not call handleLocationHash when the hash does not match any line', () => { + window.location.hash = 'XYZ_456'; + + const handleLocationHashSpy = spyOnDependency(actions, 'handleLocationHash').and.stub(); + + scrollToLineIfNeededInline({}, lineMock); + + expect(handleLocationHashSpy).not.toHaveBeenCalled(); + }); + + it('should call handleLocationHash only when the hash matches a line', () => { + window.location.hash = 'ABC_123'; + + const handleLocationHashSpy = spyOnDependency(actions, 'handleLocationHash').and.stub(); + + scrollToLineIfNeededInline( + {}, + { + lineCode: 'ABC_456', + }, + ); + scrollToLineIfNeededInline({}, lineMock); + scrollToLineIfNeededInline( + {}, + { + lineCode: 'XYZ_456', + }, + ); + + expect(handleLocationHashSpy).toHaveBeenCalled(); + expect(handleLocationHashSpy).toHaveBeenCalledTimes(1); + }); + }); + + describe('scrollToLineIfNeededParallel', () => { + const lineMock = { + left: null, + right: { + lineCode: 'ABC_123', + }, + }; + + it('should not call handleLocationHash when there is not hash', () => { + window.location.hash = ''; + + const handleLocationHashSpy = spyOnDependency(actions, 'handleLocationHash').and.stub(); + + scrollToLineIfNeededParallel({}, lineMock); + + expect(handleLocationHashSpy).not.toHaveBeenCalled(); + }); + + it('should not call handleLocationHash when the hash does not match any line', () => { + window.location.hash = 'XYZ_456'; + + const handleLocationHashSpy = spyOnDependency(actions, 'handleLocationHash').and.stub(); + + scrollToLineIfNeededParallel({}, lineMock); + + expect(handleLocationHashSpy).not.toHaveBeenCalled(); + }); + + it('should call handleLocationHash only when the hash matches a line', () => { + window.location.hash = 'ABC_123'; + + const handleLocationHashSpy = spyOnDependency(actions, 'handleLocationHash').and.stub(); + + scrollToLineIfNeededParallel( + {}, + { + left: null, + right: { + lineCode: 'ABC_456', + }, + }, + ); + scrollToLineIfNeededParallel({}, lineMock); + scrollToLineIfNeededParallel( + {}, + { + left: null, + right: { + lineCode: 'XYZ_456', + }, + }, + ); + + expect(handleLocationHashSpy).toHaveBeenCalled(); + expect(handleLocationHashSpy).toHaveBeenCalledTimes(1); + }); + }); }); diff --git a/spec/javascripts/diffs/store/mutations_spec.js b/spec/javascripts/diffs/store/mutations_spec.js index 7eeca6712cc..9a5d8dfbd15 100644 --- a/spec/javascripts/diffs/store/mutations_spec.js +++ b/spec/javascripts/diffs/store/mutations_spec.js @@ -162,6 +162,7 @@ describe('DiffsStoreMutations', () => { }; const state = { + latestDiff: true, diffFiles: [ { fileHash: 'ABC', @@ -229,6 +230,76 @@ describe('DiffsStoreMutations', () => { expect(state.diffFiles[0].highlightedDiffLines[0].discussions.length).toEqual(2); expect(state.diffFiles[0].highlightedDiffLines[0].discussions[1].id).toEqual(2); }); + + it('should add legacy discussions to the given line', () => { + const diffPosition = { + baseSha: 'ed13df29948c41ba367caa757ab3ec4892509910', + headSha: 'b921914f9a834ac47e6fd9420f78db0f83559130', + newLine: null, + newPath: '500-lines-4.txt', + oldLine: 5, + oldPath: '500-lines-4.txt', + startSha: 'ed13df29948c41ba367caa757ab3ec4892509910', + lineCode: 'ABC_1', + }; + + const state = { + latestDiff: true, + diffFiles: [ + { + fileHash: 'ABC', + parallelDiffLines: [ + { + left: { + lineCode: 'ABC_1', + discussions: [], + }, + right: { + lineCode: 'ABC_1', + discussions: [], + }, + }, + ], + highlightedDiffLines: [ + { + lineCode: 'ABC_1', + discussions: [], + }, + ], + }, + ], + }; + const discussions = [ + { + id: 1, + line_code: 'ABC_1', + diff_discussion: true, + active: true, + }, + { + id: 2, + line_code: 'ABC_1', + diff_discussion: true, + active: true, + }, + ]; + + const diffPositionByLineCode = { + ABC_1: diffPosition, + }; + + mutations[types.SET_LINE_DISCUSSIONS_FOR_FILE](state, { + fileHash: 'ABC', + discussions, + diffPositionByLineCode, + }); + + expect(state.diffFiles[0].parallelDiffLines[0].left.discussions.length).toEqual(2); + expect(state.diffFiles[0].parallelDiffLines[0].left.discussions[1].id).toEqual(2); + + expect(state.diffFiles[0].highlightedDiffLines[0].discussions.length).toEqual(2); + expect(state.diffFiles[0].highlightedDiffLines[0].discussions[1].id).toEqual(2); + }); }); describe('REMOVE_LINE_DISCUSSIONS', () => { diff --git a/spec/javascripts/diffs/store/utils_spec.js b/spec/javascripts/diffs/store/utils_spec.js index 4b5cf450c68..6138b9701f4 100644 --- a/spec/javascripts/diffs/store/utils_spec.js +++ b/spec/javascripts/diffs/store/utils_spec.js @@ -3,6 +3,7 @@ import { LINE_POSITION_LEFT, LINE_POSITION_RIGHT, TEXT_DIFF_POSITION_TYPE, + LEGACY_DIFF_NOTE_TYPE, DIFF_NOTE_TYPE, NEW_LINE_TYPE, OLD_LINE_TYPE, @@ -151,6 +152,64 @@ describe('DiffsStoreUtils', () => { data: postData, }); }); + + it('should create legacy note form data', () => { + const diffFile = getDiffFileMock(); + delete diffFile.diffRefs.startSha; + delete diffFile.diffRefs.headSha; + + noteableDataMock.targetType = MERGE_REQUEST_NOTEABLE_TYPE; + + const options = { + note: 'Hello world!', + noteableData: noteableDataMock, + noteableType: MERGE_REQUEST_NOTEABLE_TYPE, + diffFile, + noteTargetLine: { + lineCode: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_3', + metaData: null, + newLine: 3, + oldLine: 1, + }, + diffViewType: PARALLEL_DIFF_VIEW_TYPE, + linePosition: LINE_POSITION_LEFT, + }; + + const position = JSON.stringify({ + base_sha: diffFile.diffRefs.baseSha, + start_sha: undefined, + head_sha: undefined, + old_path: diffFile.oldPath, + new_path: diffFile.newPath, + position_type: TEXT_DIFF_POSITION_TYPE, + old_line: options.noteTargetLine.oldLine, + new_line: options.noteTargetLine.newLine, + }); + + const postData = { + view: options.diffViewType, + line_type: options.linePosition === LINE_POSITION_RIGHT ? NEW_LINE_TYPE : OLD_LINE_TYPE, + merge_request_diff_head_sha: undefined, + in_reply_to_discussion_id: '', + note_project_id: '', + target_type: options.noteableType, + target_id: options.noteableData.id, + note: { + noteable_type: options.noteableType, + noteable_id: options.noteableData.id, + commit_id: '', + type: LEGACY_DIFF_NOTE_TYPE, + line_code: options.noteTargetLine.lineCode, + note: options.note, + position, + }, + }; + + expect(utils.getNoteFormData(options)).toEqual({ + endpoint: options.noteableData.create_note_path, + data: postData, + }); + }); }); describe('addLineReferences', () => { @@ -291,13 +350,72 @@ describe('DiffsStoreUtils', () => { it('returns true when the discussion is up to date', () => { expect( - utils.isDiscussionApplicableToLine(discussions.upToDateDiscussion1, diffPosition), + utils.isDiscussionApplicableToLine({ + discussion: discussions.upToDateDiscussion1, + diffPosition, + latestDiff: true, + }), ).toBe(true); }); it('returns false when the discussion is not up to date', () => { expect( - utils.isDiscussionApplicableToLine(discussions.outDatedDiscussion1, diffPosition), + utils.isDiscussionApplicableToLine({ + discussion: discussions.outDatedDiscussion1, + diffPosition, + latestDiff: true, + }), + ).toBe(false); + }); + + it('returns true when line codes match and discussion does not contain position and is not active', () => { + const discussion = { ...discussions.outDatedDiscussion1, line_code: 'ABC_1', active: false }; + delete discussion.original_position; + delete discussion.position; + + expect( + utils.isDiscussionApplicableToLine({ + discussion, + diffPosition: { + ...diffPosition, + lineCode: 'ABC_1', + }, + latestDiff: true, + }), + ).toBe(false); + }); + + it('returns true when line codes match and discussion does not contain position and is active', () => { + const discussion = { ...discussions.outDatedDiscussion1, line_code: 'ABC_1', active: true }; + delete discussion.original_position; + delete discussion.position; + + expect( + utils.isDiscussionApplicableToLine({ + discussion, + diffPosition: { + ...diffPosition, + lineCode: 'ABC_1', + }, + latestDiff: true, + }), + ).toBe(true); + }); + + it('returns false when not latest diff', () => { + const discussion = { ...discussions.outDatedDiscussion1, line_code: 'ABC_1', active: true }; + delete discussion.original_position; + delete discussion.position; + + expect( + utils.isDiscussionApplicableToLine({ + discussion, + diffPosition: { + ...diffPosition, + lineCode: 'ABC_1', + }, + latestDiff: false, + }), ).toBe(false); }); }); diff --git a/spec/javascripts/issue_show/components/edit_actions_spec.js b/spec/javascripts/issue_show/components/edit_actions_spec.js index d779ab7bb31..a3772285527 100644 --- a/spec/javascripts/issue_show/components/edit_actions_spec.js +++ b/spec/javascripts/issue_show/components/edit_actions_spec.js @@ -54,7 +54,7 @@ describe('Edit Actions components', () => { Vue.nextTick(() => { expect( - vm.$el.querySelector('.btn-save').getAttribute('disabled'), + vm.$el.querySelector('.btn-success').getAttribute('disabled'), ).toBe('disabled'); done(); @@ -72,7 +72,7 @@ describe('Edit Actions components', () => { describe('updateIssuable', () => { it('sends update.issauble event when clicking save button', () => { - vm.$el.querySelector('.btn-save').click(); + vm.$el.querySelector('.btn-success').click(); expect( eventHub.$emit, @@ -80,11 +80,11 @@ describe('Edit Actions components', () => { }); it('shows loading icon after clicking save button', (done) => { - vm.$el.querySelector('.btn-save').click(); + vm.$el.querySelector('.btn-success').click(); Vue.nextTick(() => { expect( - vm.$el.querySelector('.btn-save .fa'), + vm.$el.querySelector('.btn-success .fa'), ).not.toBeNull(); done(); @@ -92,11 +92,11 @@ describe('Edit Actions components', () => { }); it('disabled button after clicking save button', (done) => { - vm.$el.querySelector('.btn-save').click(); + vm.$el.querySelector('.btn-success').click(); Vue.nextTick(() => { expect( - vm.$el.querySelector('.btn-save').getAttribute('disabled'), + vm.$el.querySelector('.btn-success').getAttribute('disabled'), ).toBe('disabled'); done(); diff --git a/spec/javascripts/shortcuts_dashboard_navigation_spec.js b/spec/javascripts/lib/utils/navigation_utility_spec.js index 7cb201e01d8..be620e4a27c 100644 --- a/spec/javascripts/shortcuts_dashboard_navigation_spec.js +++ b/spec/javascripts/lib/utils/navigation_utility_spec.js @@ -1,4 +1,4 @@ -import findAndFollowLink from '~/shortcuts_dashboard_navigation'; +import findAndFollowLink from '~/lib/utils/navigation_utility'; describe('findAndFollowLink', () => { it('visits a link when the selector exists', () => { diff --git a/spec/javascripts/notes/stores/mutation_spec.js b/spec/javascripts/notes/stores/mutation_spec.js index 6b7f61468d5..1ecfe914859 100644 --- a/spec/javascripts/notes/stores/mutation_spec.js +++ b/spec/javascripts/notes/stores/mutation_spec.js @@ -156,6 +156,41 @@ describe('Notes Store mutations', () => { expect(state.discussions[2].notes[0].note).toBe(legacyNote.notes[1].note); expect(state.discussions.length).toEqual(3); }); + + it('adds truncated_diff_lines if discussion is a diffFile', () => { + const state = { + discussions: [], + }; + + mutations.SET_INITIAL_DISCUSSIONS(state, [ + { + ...note, + diff_file: { + file_hash: 'a', + }, + truncated_diff_lines: ['a'], + }, + ]); + + expect(state.discussions[0].truncated_diff_lines).toEqual(['a']); + }); + + it('adds empty truncated_diff_lines when not in discussion', () => { + const state = { + discussions: [], + }; + + mutations.SET_INITIAL_DISCUSSIONS(state, [ + { + ...note, + diff_file: { + file_hash: 'a', + }, + }, + ]); + + expect(state.discussions[0].truncated_diff_lines).toEqual([]); + }); }); describe('SET_LAST_FETCHED_AT', () => { diff --git a/spec/javascripts/search_autocomplete_spec.js b/spec/javascripts/search_autocomplete_spec.js index 86c001678c5..646d843162c 100644 --- a/spec/javascripts/search_autocomplete_spec.js +++ b/spec/javascripts/search_autocomplete_spec.js @@ -2,7 +2,7 @@ import $ from 'jquery'; import '~/gl_dropdown'; -import SearchAutocomplete from '~/search_autocomplete'; +import initSearchAutocomplete from '~/search_autocomplete'; import '~/lib/utils/common_utils'; describe('Search autocomplete dropdown', () => { @@ -132,7 +132,7 @@ describe('Search autocomplete dropdown', () => { window.gon.current_user_id = userId; window.gon.current_username = userName; - return (widget = new SearchAutocomplete()); + return (widget = initSearchAutocomplete()); }); afterEach(function() { diff --git a/spec/javascripts/shortcuts_spec.js b/spec/javascripts/shortcuts_spec.js index 94cded7ee37..3ca6ecaa938 100644 --- a/spec/javascripts/shortcuts_spec.js +++ b/spec/javascripts/shortcuts_spec.js @@ -1,5 +1,5 @@ import $ from 'jquery'; -import Shortcuts from '~/shortcuts'; +import Shortcuts from '~/behaviors/shortcuts/shortcuts'; describe('Shortcuts', () => { const fixtureName = 'snippets/show.html.raw'; diff --git a/spec/lib/gitlab/database/subquery_spec.rb b/spec/lib/gitlab/database/subquery_spec.rb new file mode 100644 index 00000000000..70380e02f16 --- /dev/null +++ b/spec/lib/gitlab/database/subquery_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Database::Subquery do + describe '.self_join' do + set(:project) { create(:project) } + + it 'allows you to delete_all rows with WHERE and LIMIT' do + events = create_list(:event, 8, project: project) + + expect do + described_class.self_join(Event.where('id < ?', events[5]).recent.limit(2)).delete_all + end.to change { Event.count }.by(-2) + end + end +end diff --git a/spec/lib/gitlab/diff/file_collection/commit_spec.rb b/spec/lib/gitlab/diff/file_collection/commit_spec.rb new file mode 100644 index 00000000000..6d1b66deb6a --- /dev/null +++ b/spec/lib/gitlab/diff/file_collection/commit_spec.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Diff::FileCollection::Commit do + let(:project) { create(:project, :repository) } + + it_behaves_like 'diff statistics' do + let(:collection_default_args) do + { diff_options: {} } + end + let(:diffable) { project.commit } + let(:stub_path) { 'bar/branch-test.txt' } + end +end diff --git a/spec/lib/gitlab/diff/file_collection/compare_spec.rb b/spec/lib/gitlab/diff/file_collection/compare_spec.rb new file mode 100644 index 00000000000..f330f299ac1 --- /dev/null +++ b/spec/lib/gitlab/diff/file_collection/compare_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Diff::FileCollection::Compare do + include RepoHelpers + + let(:project) { create(:project, :repository) } + let(:commit) { project.commit } + let(:start_commit) { sample_image_commit } + let(:head_commit) { sample_commit } + let(:raw_compare) do + Gitlab::Git::Compare.new(project.repository.raw_repository, + start_commit.id, + head_commit.id) + end + + it_behaves_like 'diff statistics' do + let(:collection_default_args) do + { + project: diffable.project, + diff_options: {}, + diff_refs: diffable.diff_refs + } + end + let(:diffable) { Compare.new(raw_compare, project) } + let(:stub_path) { '.gitignore' } + end +end diff --git a/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb b/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb index 79287021981..4578da70bfc 100644 --- a/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb +++ b/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb @@ -29,6 +29,14 @@ describe Gitlab::Diff::FileCollection::MergeRequestDiff do expect(mr_diff.cache_key).not_to eq(key) end + it_behaves_like 'diff statistics' do + let(:collection_default_args) do + { diff_options: {} } + end + let(:diffable) { merge_request.merge_request_diff } + let(:stub_path) { '.gitignore' } + end + shared_examples 'initializes a DiffCollection' do it 'returns a valid instance of a DiffCollection' do expect(diff_files).to be_a(Gitlab::Git::DiffCollection) diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb index ebeb05d6e02..2f51642b58e 100644 --- a/spec/lib/gitlab/diff/file_spec.rb +++ b/spec/lib/gitlab/diff/file_spec.rb @@ -186,6 +186,70 @@ describe Gitlab::Diff::File do end end + context 'diff file stats' do + let(:diff_file) do + described_class.new(diff, + diff_refs: commit.diff_refs, + repository: project.repository, + stats: stats) + end + + let(:raw_diff) do + <<~EOS + --- a/files/ruby/popen.rb + +++ b/files/ruby/popen.rb + @@ -6,12 +6,18 @@ module Popen + + def popen(cmd, path=nil) + unless cmd.is_a?(Array) + - raise "System commands must be given as an array of strings" + + raise RuntimeError, "System commands must be given as an array of strings" + + # foobar + end + EOS + end + + describe '#added_lines' do + context 'when stats argument given' do + let(:stats) { double(Gitaly::DiffStats, additions: 10, deletions: 15) } + + it 'returns added lines from stats' do + expect(diff_file.added_lines).to eq(stats.additions) + end + end + + context 'when stats argument not given' do + let(:stats) { nil } + + it 'returns added lines by parsing raw diff' do + allow(diff_file).to receive(:raw_diff) { raw_diff } + + expect(diff_file.added_lines).to eq(2) + end + end + end + + describe '#removed_lines' do + context 'when stats argument given' do + let(:stats) { double(Gitaly::DiffStats, additions: 10, deletions: 15) } + + it 'returns removed lines from stats' do + expect(diff_file.removed_lines).to eq(stats.deletions) + end + end + + context 'when stats argument not given' do + let(:stats) { nil } + + it 'returns removed lines by parsing raw diff' do + allow(diff_file).to receive(:raw_diff) { raw_diff } + + expect(diff_file.removed_lines).to eq(1) + end + end + end + end + describe '#simple_viewer' do context 'when the file is not diffable' do before do diff --git a/spec/lib/gitlab/git/diff_stats_collection_spec.rb b/spec/lib/gitlab/git/diff_stats_collection_spec.rb new file mode 100644 index 00000000000..89927cbb3a6 --- /dev/null +++ b/spec/lib/gitlab/git/diff_stats_collection_spec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require "spec_helper" + +describe Gitlab::Git::DiffStatsCollection do + let(:stats_a) do + double(Gitaly::DiffStats, additions: 10, deletions: 15, path: 'foo') + end + + let(:stats_b) do + double(Gitaly::DiffStats, additions: 5, deletions: 1, path: 'bar') + end + + let(:diff_stats) { [stats_a, stats_b] } + let(:collection) { described_class.new(diff_stats) } + + describe '.find_by_path' do + it 'returns stats by path when found' do + expect(collection.find_by_path('foo')).to eq(stats_a) + end + + it 'returns nil when stats is not found by path' do + expect(collection.find_by_path('no-file')).to be_nil + end + end +end diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb index 58c260ee1f0..d02536a2fb4 100644 --- a/spec/lib/gitlab/git/repository_spec.rb +++ b/spec/lib/gitlab/git/repository_spec.rb @@ -1136,6 +1136,14 @@ describe Gitlab::Git::Repository, :seed_helper do expect(collection).to be_a(Enumerable) expect(collection.to_a).to be_empty end + + it 'returns no Gitaly::DiffStats when there is a nil SHA' do + collection = repository.diff_stats(nil, 'master') + + expect(collection).to be_a(Gitlab::Git::DiffStatsCollection) + expect(collection).to be_a(Enumerable) + expect(collection.to_a).to be_empty + end end describe "#ls_files" do diff --git a/spec/services/projects/container_repository/destroy_service_spec.rb b/spec/services/projects/container_repository/destroy_service_spec.rb index 307ccc88865..affcc66d2bb 100644 --- a/spec/services/projects/container_repository/destroy_service_spec.rb +++ b/spec/services/projects/container_repository/destroy_service_spec.rb @@ -33,6 +33,7 @@ describe Projects::ContainerRepository::DestroyService do end it 'deletes the repository' do + expect(repository).to receive(:delete_tags!).and_call_original expect { described_class.new(project, user).execute(repository) }.to change { ContainerRepository.all.count }.by(-1) end end diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb index e428808ab68..beff499f2be 100644 --- a/spec/services/projects/destroy_service_spec.rb +++ b/spec/services/projects/destroy_service_spec.rb @@ -204,7 +204,7 @@ describe Projects::DestroyService do context 'when image repository deletion fails' do it 'raises an exception' do expect_any_instance_of(ContainerRepository) - .to receive(:delete_tags!).and_return(false) + .to receive(:delete_tags!).and_raise(RuntimeError) expect(destroy_project(project, user)).to be false end diff --git a/spec/support/shared_examples/diff_file_collections.rb b/spec/support/shared_examples/diff_file_collections.rb new file mode 100644 index 00000000000..55ce160add0 --- /dev/null +++ b/spec/support/shared_examples/diff_file_collections.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +shared_examples 'diff statistics' do |test_include_stats_flag: true| + def stub_stats_find_by_path(path, stats_mock) + expect_next_instance_of(Gitlab::Git::DiffStatsCollection) do |collection| + allow(collection).to receive(:find_by_path).and_call_original + expect(collection).to receive(:find_by_path).with(path).and_return(stats_mock) + end + end + + context 'when should request diff stats' do + it 'Repository#diff_stats is called' do + subject = described_class.new(diffable, collection_default_args) + + expect(diffable.project.repository) + .to receive(:diff_stats) + .with(diffable.diff_refs.base_sha, diffable.diff_refs.head_sha) + .and_call_original + + subject.diff_files + end + + it 'Gitlab::Diff::File is initialized with diff stats' do + subject = described_class.new(diffable, collection_default_args) + + stats_mock = double(Gitaly::DiffStats, path: '.gitignore', additions: 758, deletions: 120) + stub_stats_find_by_path(stub_path, stats_mock) + + diff_file = subject.diff_files.find { |file| file.new_path == stub_path } + + expect(diff_file.added_lines).to eq(stats_mock.additions) + expect(diff_file.removed_lines).to eq(stats_mock.deletions) + end + end + + context 'when should not request diff stats' do + it 'Repository#diff_stats is not called' do + collection_default_args[:diff_options][:include_stats] = false + + subject = described_class.new(diffable, collection_default_args) + + expect(diffable.project.repository).not_to receive(:diff_stats) + + subject.diff_files + end + end +end diff --git a/spec/tasks/gitlab/db_rake_spec.rb b/spec/tasks/gitlab/db_rake_spec.rb index b81aea23306..5818892d56a 100644 --- a/spec/tasks/gitlab/db_rake_spec.rb +++ b/spec/tasks/gitlab/db_rake_spec.rb @@ -61,6 +61,39 @@ describe 'gitlab:db namespace rake task' do expect(Rake::Task['db:migrate']).not_to receive(:invoke) expect { run_rake_task('gitlab:db:configure') }.to raise_error(RuntimeError, 'error') end + + context 'SKIP_POST_DEPLOYMENT_MIGRATIONS environment variable set' do + let(:rails_paths) { { 'db' => ['db'], 'db/migrate' => ['db/migrate'] } } + + before do + allow(ENV).to receive(:[]).and_call_original + allow(ENV).to receive(:[]).with('SKIP_POST_DEPLOYMENT_MIGRATIONS').and_return true + + # Our environment has already been loaded, so we need to pretend like post_migrations were not + allow(Rails.application.config).to receive(:paths).and_return(rails_paths) + allow(ActiveRecord::Migrator).to receive(:migrations_paths).and_return(rails_paths['db/migrate'].dup) + end + + it 'adds post deployment migrations before schema load if the schema is not already loaded' do + allow(ActiveRecord::Base.connection).to receive(:tables).and_return([]) + expect(Gitlab::Database).to receive(:add_post_migrate_path_to_rails).and_call_original + expect(Rake::Task['db:schema:load']).to receive(:invoke) + expect(Rake::Task['db:seed_fu']).to receive(:invoke) + expect(Rake::Task['db:migrate']).not_to receive(:invoke) + expect { run_rake_task('gitlab:db:configure') }.not_to raise_error + expect(rails_paths['db/migrate'].include?(File.join(Rails.root, 'db', 'post_migrate'))).to be(true) + end + + it 'ignores post deployment migrations when schema has already been loaded' do + allow(ActiveRecord::Base.connection).to receive(:tables).and_return(%w[table1 table2]) + expect(Rake::Task['db:migrate']).to receive(:invoke) + expect(Gitlab::Database).not_to receive(:add_post_migrate_path_to_rails) + expect(Rake::Task['db:schema:load']).not_to receive(:invoke) + expect(Rake::Task['db:seed_fu']).not_to receive(:invoke) + expect { run_rake_task('gitlab:db:configure') }.not_to raise_error + expect(rails_paths['db/migrate'].include?(File.join(Rails.root, 'db', 'post_migrate'))).to be(false) + end + end end def run_rake_task(task_name) diff --git a/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml b/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml index a191f1f59bf..33ae9c6ad7e 100644 --- a/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml +++ b/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml @@ -635,8 +635,8 @@ rollout 100%: function install_dependencies() { apk add -U openssl curl tar gzip bash ca-certificates git - wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub - wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.28-r0/glibc-2.28-r0.apk + curl -L -o /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub + curl -L -O https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.28-r0/glibc-2.28-r0.apk apk add glibc-2.28-r0.apk rm glibc-2.28-r0.apk |