diff options
65 files changed, 643 insertions, 132 deletions
diff --git a/.gitlab/issue_templates/Security developer workflow.md b/.gitlab/issue_templates/Security developer workflow.md index c1f702e9385..64b54b171f7 100644 --- a/.gitlab/issue_templates/Security developer workflow.md +++ b/.gitlab/issue_templates/Security developer workflow.md @@ -12,7 +12,7 @@ Set the title to: `[Security] Description of the original issue` - [ ] Link to the original issue adding it to the [links section](#links) - [ ] Run `scripts/security-harness` in the CE, EE, and/or Omnibus to prevent pushing to any remote besides `dev.gitlab.org` - [ ] Create an MR targetting `org` `master`, prefixing your branch with `security-` -- [ ] Label your MR with the ~security label, prefix the title with `WIP: [master]` +- [ ] Label your MR with the ~security label, prefix the title with `WIP: [master]` - [ ] Add a link to the MR to the [links section](#links) - [ ] Add a link to an EE MR if required - [ ] Make sure the MR remains in-progress and gets approved after the review cycle, **but never merged**. @@ -22,13 +22,13 @@ Set the title to: `[Security] Description of the original issue` - [ ] Once the MR is ready to be merged, create MRs targetting the last 3 releases - [ ] At this point, it might be easy to squash the commits from the MR into one - - You can use the script `bin/secpick` instead of the following steps, to help you cherry-picking. See the [seckpick documentation] + - You can use the script `bin/secpick` instead of the following steps, to help you cherry-picking. See the [secpick documentation] - [ ] Create the branch `security-X-Y` from `X-Y-stable` if it doesn't exist (and make sure it's up to date with stable) - [ ] Create each MR targetting the security branch `security-X-Y` - [ ] Add the ~security label and prefix with the version `WIP: [X.Y]` the title of the MR - [ ] Make sure all MRs have a link in the [links section](#links) and are assigned to a Release Manager. -[seckpick documentation]: https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md#secpick-script +[secpick documentation]: https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md#secpick-script #### Documentation and final details @@ -68,4 +68,4 @@ Set the title to: `[Security] Description of the original issue` [security process for developers]: https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md [RM list]: https://about.gitlab.com/release-managers/ -/label ~security +/label ~security @@ -180,7 +180,7 @@ gem 'rufus-scheduler', '~> 3.4' gem 'httparty', '~> 0.13.3' # Colored output to console -gem 'rainbow', '~> 2.2' +gem 'rainbow', '~> 3.0' # Progress bar gem 'ruby-progressbar' diff --git a/Gemfile.lock b/Gemfile.lock index 62c3b28f386..b33dd75c278 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -691,8 +691,7 @@ GEM activesupport (= 4.2.10) rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) - rainbow (2.2.2) - rake + rainbow (3.0.0) raindrops (0.18.0) rake (12.3.1) rb-fsevent (0.10.2) @@ -1134,7 +1133,7 @@ DEPENDENCIES rails (= 4.2.10) rails-deprecated_sanitizer (~> 1.0.3) rails-i18n (~> 4.0.9) - rainbow (~> 2.2) + rainbow (~> 3.0) raindrops (~> 0.18) rblineprof (~> 0.3.6) rbtrace (~> 0.4) diff --git a/Gemfile.rails5.lock b/Gemfile.rails5.lock index 39305927c0f..af70e2c1939 100644 --- a/Gemfile.rails5.lock +++ b/Gemfile.rails5.lock @@ -701,8 +701,7 @@ GEM method_source rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) - rainbow (2.2.2) - rake + rainbow (3.0.0) raindrops (0.18.0) rake (12.3.1) rb-fsevent (0.10.2) @@ -1147,7 +1146,7 @@ DEPENDENCIES rails-controller-testing rails-deprecated_sanitizer (~> 1.0.3) rails-i18n (~> 5.1) - rainbow (~> 2.2) + rainbow (~> 3.0) raindrops (~> 0.18) rblineprof (~> 0.3.6) rbtrace (~> 0.4) diff --git a/app/assets/javascripts/commons/polyfills.js b/app/assets/javascripts/commons/polyfills.js index 589eeee9695..742cf490ad2 100644 --- a/app/assets/javascripts/commons/polyfills.js +++ b/app/assets/javascripts/commons/polyfills.js @@ -8,6 +8,7 @@ import 'core-js/fn/object/assign'; import 'core-js/fn/promise'; import 'core-js/fn/string/code-point-at'; import 'core-js/fn/string/from-code-point'; +import 'core-js/fn/string/includes'; import 'core-js/fn/symbol'; import 'core-js/es6/map'; import 'core-js/es6/weak-map'; diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue index 7cc4e6a2c3a..b5b05df4d34 100644 --- a/app/assets/javascripts/diffs/components/app.vue +++ b/app/assets/javascripts/diffs/components/app.vue @@ -114,11 +114,15 @@ export default { this.adjustView(); }, methods: { - ...mapActions('diffs', ['setBaseConfig', 'fetchDiffFiles']), + ...mapActions('diffs', ['setBaseConfig', 'fetchDiffFiles', 'startRenderDiffsQueue']), fetchData() { - this.fetchDiffFiles().catch(() => { - createFlash(__('Something went wrong on our end. Please try again!')); - }); + this.fetchDiffFiles() + .then(() => { + requestIdleCallback(this.startRenderDiffsQueue, { timeout: 1000 }); + }) + .catch(() => { + createFlash(__('Something went wrong on our end. Please try again!')); + }); if (!this.isNotesFetched) { eventHub.$emit('fetchNotesData'); diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue index 7e7058d8d08..59e9ba08b8b 100644 --- a/app/assets/javascripts/diffs/components/diff_file.vue +++ b/app/assets/javascripts/diffs/components/diff_file.vue @@ -46,16 +46,25 @@ export default { showExpandMessage() { return this.isCollapsed && !this.isLoadingCollapsedDiff && !this.file.tooLarge; }, + showLoadingIcon() { + return this.isLoadingCollapsedDiff || (!this.file.renderIt && !this.isCollapsed); + }, }, methods: { ...mapActions('diffs', ['loadCollapsedDiff']), handleToggle() { const { collapsed, highlightedDiffLines, parallelDiffLines } = this.file; - if (collapsed && !highlightedDiffLines && !parallelDiffLines.length) { + if ( + collapsed && + !highlightedDiffLines && + parallelDiffLines !== undefined && + !parallelDiffLines.length + ) { this.handleLoadCollapsedDiff(); } else { this.file.collapsed = !this.file.collapsed; + this.file.renderIt = true; } }, handleLoadCollapsedDiff() { @@ -65,6 +74,7 @@ export default { .then(() => { this.isLoadingCollapsedDiff = false; this.file.collapsed = false; + this.file.renderIt = true; }) .catch(() => { this.isLoadingCollapsedDiff = false; @@ -121,12 +131,12 @@ export default { </div> <diff-content - v-if="!isCollapsed" + v-if="!isCollapsed && file.renderIt" :class="{ hidden: isCollapsed || file.tooLarge }" :diff-file="file" /> <loading-icon - v-if="isLoadingCollapsedDiff" + v-else-if="showLoadingIcon" class="diff-content loading" /> <div diff --git a/app/assets/javascripts/diffs/constants.js b/app/assets/javascripts/diffs/constants.js index 2fa8367f528..f68afa44837 100644 --- a/app/assets/javascripts/diffs/constants.js +++ b/app/assets/javascripts/diffs/constants.js @@ -25,3 +25,6 @@ export const CONTEXT_LINE_CLASS_NAME = 'diff-expanded'; export const UNFOLD_COUNT = 20; export const COUNT_OF_AVATARS_IN_GUTTER = 3; export const LENGTH_OF_AVATAR_TOOLTIP = 17; + +export const LINES_TO_BE_RENDERED_DIRECTLY = 100; +export const MAX_LINES_TO_BE_RENDERED = 2000; diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js index 27001142257..4ab6ceb249a 100644 --- a/app/assets/javascripts/diffs/store/actions.js +++ b/app/assets/javascripts/diffs/store/actions.js @@ -29,6 +29,27 @@ export const fetchDiffFiles = ({ state, commit }) => { .then(handleLocationHash); }; +export const startRenderDiffsQueue = ({ state, commit }) => { + const checkItem = () => { + const nextFile = state.diffFiles.find( + file => !file.renderIt && (!file.collapsed || !file.text), + ); + if (nextFile) { + requestAnimationFrame(() => { + commit(types.RENDER_FILE, nextFile); + }); + requestIdleCallback( + () => { + checkItem(); + }, + { timeout: 1000 }, + ); + } + }; + + checkItem(); +}; + export const setInlineDiffViewType = ({ commit }) => { commit(types.SET_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE); diff --git a/app/assets/javascripts/diffs/store/mutation_types.js b/app/assets/javascripts/diffs/store/mutation_types.js index 2c8e1a1466f..c999d637d50 100644 --- a/app/assets/javascripts/diffs/store/mutation_types.js +++ b/app/assets/javascripts/diffs/store/mutation_types.js @@ -8,3 +8,4 @@ export const REMOVE_COMMENT_FORM_LINE = 'REMOVE_COMMENT_FORM_LINE'; export const ADD_CONTEXT_LINES = 'ADD_CONTEXT_LINES'; export const ADD_COLLAPSED_DIFFS = 'ADD_COLLAPSED_DIFFS'; export const EXPAND_ALL_FILES = 'EXPAND_ALL_FILES'; +export const RENDER_FILE = 'RENDER_FILE'; diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js index a98b2be89a3..0522e32c410 100644 --- a/app/assets/javascripts/diffs/store/mutations.js +++ b/app/assets/javascripts/diffs/store/mutations.js @@ -2,6 +2,7 @@ import Vue from 'vue'; import _ from 'underscore'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { findDiffFile, addLineReferences, removeMatchLine, addContextLines } from './utils'; +import { LINES_TO_BE_RENDERED_DIRECTLY, MAX_LINES_TO_BE_RENDERED } from '../constants'; import * as types from './mutation_types'; export default { @@ -15,8 +16,48 @@ export default { }, [types.SET_DIFF_DATA](state, data) { + const diffData = convertObjectPropsToCamelCase(data, { deep: true }); + let showingLines = 0; + const filesLength = diffData.diffFiles.length; + let i; + for (i = 0; i < filesLength; i += 1) { + const file = diffData.diffFiles[i]; + if (file.parallelDiffLines) { + const linesLength = file.parallelDiffLines.length; + let u = 0; + for (u = 0; u < linesLength; u += 1) { + const line = file.parallelDiffLines[u]; + if (line.left) delete line.left.text; + if (line.right) delete line.right.text; + } + } + + if (file.highlightedDiffLines) { + const linesLength = file.highlightedDiffLines.length; + let u; + for (u = 0; u < linesLength; u += 1) { + const line = file.highlightedDiffLines[u]; + delete line.text; + } + } + + if (file.highlightedDiffLines) { + showingLines += file.parallelDiffLines.length; + } + Object.assign(file, { + renderIt: showingLines < LINES_TO_BE_RENDERED_DIRECTLY, + collapsed: file.text && showingLines > MAX_LINES_TO_BE_RENDERED, + }); + } + Object.assign(state, { - ...convertObjectPropsToCamelCase(data, { deep: true }), + ...diffData, + }); + }, + + [types.RENDER_FILE](state, file) { + Object.assign(file, { + renderIt: true, }); }, diff --git a/app/assets/javascripts/jobs/components/artifacts_block.vue b/app/assets/javascripts/jobs/components/artifacts_block.vue new file mode 100644 index 00000000000..525c5eec91a --- /dev/null +++ b/app/assets/javascripts/jobs/components/artifacts_block.vue @@ -0,0 +1,98 @@ +<script> + import TimeagoTooltiop from '~/vue_shared/components/time_ago_tooltip.vue'; + + export default { + components: { + TimeagoTooltiop, + }, + props: { + // @build.artifacts_expired? + haveArtifactsExpired: { + type: Boolean, + required: true, + }, + // @build.has_expiring_artifacts? + willArtifactsExpire: { + type: Boolean, + required: true, + }, + expireAt: { + type: String, + required: false, + default: null, + }, + keepArtifactsPath: { + type: String, + required: false, + default: null, + }, + downloadArtifactsPath: { + type: String, + required: false, + default: null, + }, + browseArtifactsPath: { + type: String, + required: false, + default: null, + }, + }, + }; +</script> +<template> + <div class="block"> + <div class="title"> + {{ s__('Job|Job artifacts') }} + </div> + + <p + v-if="haveArtifactsExpired" + class="js-artifacts-removed build-detail-row" + > + {{ s__('Job|The artifacts were removed') }} + </p> + <p + v-else-if="willArtifactsExpire" + class="js-artifacts-will-be-removed build-detail-row" + > + {{ s__('Job|The artifacts will be removed') }} + </p> + + <timeago-tooltiop + v-if="expireAt" + :time="expireAt" + /> + + <div + class="btn-group d-flex" + role="group" + > + <a + v-if="keepArtifactsPath" + :href="keepArtifactsPath" + class="js-keep-artifacts btn btn-sm btn-default" + data-method="post" + > + {{ s__('Job|Keep') }} + </a> + + <a + v-if="downloadArtifactsPath" + :href="downloadArtifactsPath" + class="js-download-artifacts btn btn-sm btn-default" + download + rel="nofollow" + > + {{ s__('Job|Download') }} + </a> + + <a + v-if="browseArtifactsPath" + :href="browseArtifactsPath" + class="js-browse-artifacts btn btn-sm btn-default" + > + {{ s__('Job|Browse') }} + </a> + </div> + </div> +</template> diff --git a/app/assets/stylesheets/bootstrap_migration.scss b/app/assets/stylesheets/bootstrap_migration.scss index 056d4b7207a..e8e707cf90c 100644 --- a/app/assets/stylesheets/bootstrap_migration.scss +++ b/app/assets/stylesheets/bootstrap_migration.scss @@ -85,7 +85,7 @@ strong { } a { - color: $gl-link-color; + color: $blue-600; } hr { diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index ea4798fcefd..0dc7aa4ef68 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -434,7 +434,7 @@ &:hover, &:active, &:focus { - color: $gl-link-color; + color: $blue-600; text-decoration: none; } } @@ -445,7 +445,7 @@ &:hover, &:active, &:focus { - color: $gl-link-color; + color: $blue-600; text-decoration: none; } } diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index af17210f341..268e68dbb15 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -114,7 +114,7 @@ hr { .item-title { font-weight: $gl-font-weight-bold; } .author-link { - color: $gl-link-color; + color: $blue-600; } .back-link { diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss index 00eac1688f2..54882633fea 100644 --- a/app/assets/stylesheets/framework/files.scss +++ b/app/assets/stylesheets/framework/files.scss @@ -286,19 +286,19 @@ span.idiff { .new-file { a { - color: $gl-text-green; + color: $green-600; } } .renamed-file { a { - color: $gl-text-orange; + color: $orange-600; } } .deleted-file { a { - color: $gl-text-red; + color: $red-500; } } diff --git a/app/assets/stylesheets/framework/flash.scss b/app/assets/stylesheets/framework/flash.scss index e4bcb92876d..7a4c3914fb0 100644 --- a/app/assets/stylesheets/framework/flash.scss +++ b/app/assets/stylesheets/framework/flash.scss @@ -16,10 +16,10 @@ color: $gl-text-color; a { - color: $gl-link-color; + color: $blue-600; &:hover { - color: $gl-link-hover-color; + color: $blue-800; text-decoration: none; } } diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss index 437fcff5c62..a70eece8f68 100644 --- a/app/assets/stylesheets/framework/forms.scss +++ b/app/assets/stylesheets/framework/forms.scss @@ -170,7 +170,7 @@ label { } .form-control::-webkit-input-placeholder { - color: $placeholder-text-color; + color: $gl-text-color-tertiary; } .input-group { diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss index 7290a174668..d8391b59a8c 100644 --- a/app/assets/stylesheets/framework/markdown_area.scss +++ b/app/assets/stylesheets/framework/markdown_area.scss @@ -179,7 +179,7 @@ &:hover, &:focus { svg { - fill: $gl-link-color; + fill: $blue-600; } } } diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss index 473ca408c04..eccc814b747 100644 --- a/app/assets/stylesheets/framework/typography.scss +++ b/app/assets/stylesheets/framework/typography.scss @@ -180,7 +180,7 @@ } a > code { - color: $gl-link-color; + color: $blue-600; } dd { @@ -423,25 +423,25 @@ h4 { input, textarea { &::-webkit-input-placeholder { - color: $placeholder-text-color; + color: $gl-text-color-tertiary; } // support firefox 19+ vendor prefix &::-moz-placeholder { - color: $placeholder-text-color; + color: $gl-text-color-tertiary; opacity: 1; // FF defaults to 0.54 } // scss-lint:disable PseudoElement // support Edge vendor prefix &::-ms-input-placeholder { - color: $placeholder-text-color; + color: $gl-text-color-tertiary; } // scss-lint:disable PseudoElement // support IE vendor prefix &:-ms-input-placeholder { - color: $placeholder-text-color; + color: $gl-text-color-tertiary; } } diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index d2ea314f176..866cb88ba5b 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -195,19 +195,10 @@ $gl-text-color-quaternary: #d6d6d6; $gl-text-color-inverted: rgba(255, 255, 255, 1); $gl-text-color-secondary-inverted: rgba(255, 255, 255, 0.85); $gl-text-color-disabled: #919191; -$gl-text-green: $green-600; -$gl-text-green-hover: $green-700; -$gl-text-red: $red-500; -$gl-text-orange: $orange-600; -$gl-link-color: $blue-600; -$gl-link-hover-color: $blue-800; $gl-grayish-blue: #7f8fa4; -$gl-gray: $gl-text-color; $gl-gray-dark: #313236; $gl-gray-light: #5c5c5c; $gl-header-color: #4c4e54; -$gl-header-nav-hover-color: #434343; -$placeholder-text-color: $gl-text-color-tertiary; /* * Lists @@ -226,7 +217,7 @@ $list-warning-row-color: $orange-700; /* * Markdown */ -$md-link-color: $gl-link-color; +$md-link-color: $blue-600; $md-area-border: #ddd; /* @@ -583,8 +574,8 @@ $commit-message-text-area-bg: rgba(0, 0, 0, 0); $common-gray: $gl-text-color; $common-gray-light: #bbb; $common-gray-dark: #444; -$common-red: $gl-text-red; -$common-green: $gl-text-green; +$common-red: $red-500; +$common-green: $green-600; /* * Editor diff --git a/app/assets/stylesheets/framework/zen.scss b/app/assets/stylesheets/framework/zen.scss index dbd3144b9b4..f2d296fb875 100644 --- a/app/assets/stylesheets/framework/zen.scss +++ b/app/assets/stylesheets/framework/zen.scss @@ -44,7 +44,7 @@ color: $gl-text-color-secondary; &:hover { - color: $gl-link-color; + color: $blue-600; text-decoration: none; } } diff --git a/app/assets/stylesheets/page_bundles/ide.scss b/app/assets/stylesheets/page_bundles/ide.scss index 2b8163b8c68..af91497d0ea 100644 --- a/app/assets/stylesheets/page_bundles/ide.scss +++ b/app/assets/stylesheets/page_bundles/ide.scss @@ -1158,7 +1158,7 @@ $ide-tree-text-start: $ide-activity-bar-width + $ide-tree-padding; } a { - color: $gl-link-color; + color: $blue-600; } } diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss index a68b47b1d02..91f470ca709 100644 --- a/app/assets/stylesheets/pages/boards.scss +++ b/app/assets/stylesheets/pages/boards.scss @@ -225,7 +225,7 @@ outline: 0; &:hover { - color: $gl-link-color; + color: $blue-600; } } diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index e8158cd7f6b..1696d18584d 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -221,7 +221,7 @@ color: $gl-text-color; &:hover { - color: $gl-link-color; + color: $blue-600; text-decoration: none; } } diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss index bce83bf0dd0..10764e0f3df 100644 --- a/app/assets/stylesheets/pages/commits.scss +++ b/app/assets/stylesheets/pages/commits.scss @@ -279,7 +279,7 @@ } &.autodevops-link { - color: $gl-link-color; + color: $blue-600; } } @@ -321,7 +321,7 @@ } .commit-sha { - color: $gl-link-color; + color: $blue-600; } .commit-row-message { diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss index e2c0a7a6225..bba9f38d3dd 100644 --- a/app/assets/stylesheets/pages/cycle_analytics.scss +++ b/app/assets/stylesheets/pages/cycle_analytics.scss @@ -360,7 +360,7 @@ } .commit-sha { - color: $gl-link-color; + color: $blue-600; line-height: 1.3; vertical-align: top; font-weight: $gl-font-weight-normal; diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index 591e21243ed..47778110bae 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -511,13 +511,13 @@ padding: 0; background-color: transparent; border: 0; - color: $gl-link-color; + color: $blue-600; font-weight: $gl-font-weight-bold; &:hover, &:focus { outline: none; - color: $gl-link-hover-color; + color: $blue-800; } .caret-icon { diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss index 8a074017344..179c0964567 100644 --- a/app/assets/stylesheets/pages/environments.scss +++ b/app/assets/stylesheets/pages/environments.scss @@ -479,10 +479,10 @@ .deploy-info-text-link { font-family: $monospace-font; - fill: $gl-link-color; + fill: $blue-600; &:hover { - fill: $gl-link-hover-color; + fill: $blue-800; } } diff --git a/app/assets/stylesheets/pages/graph.scss b/app/assets/stylesheets/pages/graph.scss index 49d8a5d959b..22fce893fd7 100644 --- a/app/assets/stylesheets/pages/graph.scss +++ b/app/assets/stylesheets/pages/graph.scss @@ -24,11 +24,11 @@ } .graph-additions { - color: $gl-text-green; + color: $green-600; } .graph-deletions { - color: $gl-text-red; + color: $red-500; } } diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 8e78d9f65eb..d16a63d009a 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -141,7 +141,7 @@ color: inherit; &:hover { - color: $gl-link-hover-color; + color: $blue-800; .avatar { border-color: rgba($avatar-border, .2); @@ -241,7 +241,7 @@ &:hover { text-decoration: underline; - color: $gl-link-hover-color; + color: $blue-800; } } } @@ -329,7 +329,7 @@ } .btn-secondary-hover-link:hover { - color: $gl-link-color; + color: $blue-600; } .sidebar-collapsed-icon { @@ -448,8 +448,8 @@ } .todo-undone { - color: $gl-link-color; - fill: $gl-link-color; + color: $blue-600; + fill: $blue-600; } .author { diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss index 212e5979273..0f95fb911e1 100644 --- a/app/assets/stylesheets/pages/issues.scss +++ b/app/assets/stylesheets/pages/issues.scss @@ -157,7 +157,7 @@ ul.related-merge-requests > li { .issuable-email-modal-btn { padding: 0; - color: $gl-link-color; + color: $blue-600; background-color: transparent; border: 0; outline: 0; @@ -190,7 +190,7 @@ ul.related-merge-requests > li { .create-mr-dropdown-wrap { .ref::selection { - color: $placeholder-text-color; + color: $gl-text-color-tertiary; } .dropdown { diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss index b25dc4f419a..d32943fceec 100644 --- a/app/assets/stylesheets/pages/labels.scss +++ b/app/assets/stylesheets/pages/labels.scss @@ -114,7 +114,7 @@ } &:hover { - color: $gl-link-color; + color: $blue-600; &.remove-row { color: $gl-danger; @@ -343,10 +343,10 @@ &.remove-row { &:hover { - color: $gl-text-red; + color: $red-500; svg { - fill: $gl-text-red; + fill: $red-500; } } } diff --git a/app/assets/stylesheets/pages/milestone.scss b/app/assets/stylesheets/pages/milestone.scss index 46437ce5841..1e92582d6d9 100644 --- a/app/assets/stylesheets/pages/milestone.scss +++ b/app/assets/stylesheets/pages/milestone.scss @@ -30,7 +30,7 @@ .milestone-progress { a { - color: $gl-link-color; + color: $blue-600; } } diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss index 8acd64ca1a1..4f861d43f55 100644 --- a/app/assets/stylesheets/pages/note_form.scss +++ b/app/assets/stylesheets/pages/note_form.scss @@ -306,7 +306,7 @@ &:hover, &:focus { - color: $gl-link-color; + color: $blue-600; outline: 0; } @@ -424,7 +424,7 @@ .uploading-error-icon, .uploading-error-message { - color: $gl-text-red; + color: $red-500; } .uploading-error-message { @@ -443,7 +443,7 @@ .attach-new-file, .button-attach-file, .retry-uploading-link { - color: $gl-link-color; + color: $blue-600; padding: 0; background: none; border: 0; @@ -452,5 +452,5 @@ } .markdown-selector { - color: $gl-link-color; + color: $blue-600; } diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index c369d89d63c..8d28daac750 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -210,7 +210,7 @@ ul.notes { } a { - color: $gl-link-color; + color: $blue-600; } p { @@ -253,14 +253,14 @@ ul.notes { overflow: hidden; .system-note-commit-list-toggler { - color: $gl-link-color; + color: $blue-600; padding: 10px 0 0; cursor: pointer; position: relative; z-index: 2; &:hover { - color: $gl-link-color; + color: $blue-600; text-decoration: underline; } } @@ -390,7 +390,7 @@ ul.notes { color: inherit; &:hover { - color: $gl-link-color; + color: $blue-600; } &:focus, @@ -451,7 +451,7 @@ ul.notes { .discussion-headline-light { a { - color: $gl-link-color; + color: $blue-600; } } @@ -560,12 +560,12 @@ ul.notes { &:hover, &.is-active { .danger-highlight { - color: $gl-text-red; + color: $red-500; } .link-highlight { - color: $gl-link-color; - fill: $gl-link-color; + color: $blue-600; + fill: $blue-600; } .award-control-icon-neutral { @@ -597,13 +597,13 @@ ul.notes { transition: color 0.1s linear; &:hover { - color: $gl-link-color; + color: $blue-600; } &:focus { text-decoration: underline; outline: none; - color: $gl-link-color; + color: $blue-600; } .fa { @@ -673,7 +673,7 @@ ul.notes { } a { - color: $gl-link-color; + color: $blue-600; } } @@ -759,16 +759,16 @@ ul.notes { &:not(.is-disabled) { &:hover, &:focus { - color: $gl-text-green; + color: $green-600; } } &.is-active { - color: $gl-text-green; + color: $green-600; &:hover, &:focus { - color: $gl-text-green-hover; + color: $green-700; } } diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index b68c89c25d8..ad057ed3c83 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -175,7 +175,7 @@ } .commit-sha { - color: $gl-link-color; + color: $blue-600; } .badge { diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 6d9f415e869..fffb440027c 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -388,7 +388,7 @@ line-height: $gl-btn-line-height; &:hover { - color: $gl-link-color; + color: $blue-600; } } } @@ -961,7 +961,7 @@ pre.light-well { margin-left: 5px; &.is-done { - color: $gl-text-green; + color: $green-600; } } diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index c9405004c38..5b3a468cd1c 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -259,6 +259,6 @@ input[type='checkbox']:hover { &:hover, &:focus { - color: $gl-link-color; + color: $blue-600; } } diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb index 41084ec686f..a8a10c98d69 100644 --- a/app/helpers/icons_helper.rb +++ b/app/helpers/icons_helper.rb @@ -62,6 +62,8 @@ module IconsHelper names = "key" when "two-factor" names = "key" + when "google_oauth2" + names = "google" end options.include?(:base) ? fa_stacked_icon(names, options) : fa_icon(names, options) diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb index d7c5f29be96..17b7ee4f07e 100644 --- a/app/models/ci/job_artifact.rb +++ b/app/models/ci/job_artifact.rb @@ -33,7 +33,7 @@ module Ci where(file_type: types) end - delegate :exists?, :open, to: :file + delegate :filename, :exists?, :open, to: :file enum file_type: { archive: 1, diff --git a/app/views/search/results/_blob.html.haml b/app/views/search/results/_blob.html.haml index fdcd126e7a3..a8d4d4af93a 100644 --- a/app/views/search/results/_blob.html.haml +++ b/app/views/search/results/_blob.html.haml @@ -1,4 +1,6 @@ - project = find_project_for_result_blob(blob) +- return unless project + - file_name, blob = parse_search_result(blob) - blob_link = project_blob_path(project, tree_join(blob.ref, file_name)) diff --git a/app/views/shared/runners/_form.html.haml b/app/views/shared/runners/_form.html.haml index 0337680d79b..fa93307be31 100644 --- a/app/views/shared/runners/_form.html.haml +++ b/app/views/shared/runners/_form.html.haml @@ -1,56 +1,56 @@ = form_for runner, url: runner_form_url do |f| = form_errors(runner) .form-group.row - = label :active, "Active", class: 'col-form-label col-sm-2' + = label :active, _("Active"), class: 'col-form-label col-sm-2' .col-sm-10 .form-check = f.check_box :active, { class: 'form-check-input' } - %span.light Paused Runners don't accept new jobs + %label.light{ for: :runner_active }= _("Paused Runners don't accept new jobs") .form-group.row - = label :protected, "Protected", class: 'col-form-label col-sm-2' + = label :protected, _("Protected"), class: 'col-form-label col-sm-2' .col-sm-10 .form-check = f.check_box :access_level, { class: 'form-check-input' }, 'ref_protected', 'not_protected' - %span.light This runner will only run on pipelines triggered on protected branches + %label.light{ for: :runner_access_level }= _('This runner will only run on pipelines triggered on protected branches') .form-group.row - = label :run_untagged, 'Run untagged jobs', class: 'col-form-label col-sm-2' + = label :run_untagged, _('Run untagged jobs'), class: 'col-form-label col-sm-2' .col-sm-10 .form-check = f.check_box :run_untagged, { class: 'form-check-input' } - %span.light Indicates whether this runner can pick jobs without tags + %label.light{ for: :runner_run_untagged }= _('Indicates whether this runner can pick jobs without tags') - unless runner.group_type? .form-group.row = label :locked, _('Lock to current projects'), class: 'col-form-label col-sm-2' .col-sm-10 .form-check = f.check_box :locked, { class: 'form-check-input' } - %span.light= _('When a runner is locked, it cannot be assigned to other projects') + %label.light{ for: :runner_locked }= _('When a runner is locked, it cannot be assigned to other projects') .form-group.row = label_tag :token, class: 'col-form-label col-sm-2' do - Token + = _('Token') .col-sm-10 = f.text_field :token, class: 'form-control', readonly: true .form-group.row = label_tag :ip_address, class: 'col-form-label col-sm-2' do - IP Address + = _('IP Address') .col-sm-10 = f.text_field :ip_address, class: 'form-control', readonly: true .form-group.row = label_tag :description, class: 'col-form-label col-sm-2' do - Description + = _('Description') .col-sm-10 = f.text_field :description, class: 'form-control' .form-group.row = label_tag :maximum_timeout_human_readable, class: 'col-form-label col-sm-2' do - Maximum job timeout + = _('Maximum job timeout') .col-sm-10 = f.text_field :maximum_timeout_human_readable, class: 'form-control' - .form-text.text-muted This timeout will take precedence when lower than Project-defined timeout + .form-text.text-muted= _('This timeout will take precedence when lower than Project-defined timeout') .form-group.row = label_tag :tag_list, class: 'col-form-label col-sm-2' do - Tags + = _('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 setup jobs to only use Runners with specific tags. Separate tags with commas.') .form-actions - = f.submit 'Save changes', class: 'btn btn-save' + = f.submit _('Save changes'), class: 'btn btn-success' diff --git a/bin/secpick b/bin/secpick index 5029fe57cfe..5e30c8e72c5 100755 --- a/bin/secpick +++ b/bin/secpick @@ -35,7 +35,9 @@ parser.parse! abort("Missing options. Use #{$0} --help to see the list of options available".red) if options.values.include?(nil) abort("Wrong version format #{options[:version].bold}".red) unless options[:version] =~ /\A\d*\-\d*\Z/ -branch = [BRANCH_PREFIX, options[:branch], options[:version]].join('-').freeze +branch = "#{options[:branch]}-#{options[:version]}" +branch.prepend("#{BRANCH_PREFIX}-") unless branch.start_with?("#{BRANCH_PREFIX}-") +branch = branch.freeze stable_branch = "#{BRANCH_PREFIX}-#{options[:version]}".freeze command = "git fetch #{REMOTE} #{stable_branch} && git checkout #{stable_branch} && git pull #{REMOTE} #{stable_branch} && git checkout -B #{branch} && git cherry-pick #{options[:sha]} && git push #{REMOTE} #{branch}" diff --git a/changelogs/unreleased/49905-fix-checkboxes-runners.yml b/changelogs/unreleased/49905-fix-checkboxes-runners.yml new file mode 100644 index 00000000000..af40e5348b8 --- /dev/null +++ b/changelogs/unreleased/49905-fix-checkboxes-runners.yml @@ -0,0 +1,5 @@ +--- +title: Fix checkboxes on runner admin settings - The labels are now clickable +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/50101-aritfacts-block.yml b/changelogs/unreleased/50101-aritfacts-block.yml new file mode 100644 index 00000000000..435e9d9d486 --- /dev/null +++ b/changelogs/unreleased/50101-aritfacts-block.yml @@ -0,0 +1,5 @@ +--- +title: Creates Vue component for artifacts block on job page +merge_request: +author: +type: other diff --git a/changelogs/unreleased/50180-fa-icon-google-audit.yml b/changelogs/unreleased/50180-fa-icon-google-audit.yml new file mode 100644 index 00000000000..fb1771a7570 --- /dev/null +++ b/changelogs/unreleased/50180-fa-icon-google-audit.yml @@ -0,0 +1,5 @@ +--- +title: Show google icon in audit log +merge_request: 21207 +author: Jan Beckmann +type: fixed diff --git a/changelogs/unreleased/50281-js-pages-do-not-load-on-windows-8-ie-11.yml b/changelogs/unreleased/50281-js-pages-do-not-load-on-windows-8-ie-11.yml new file mode 100644 index 00000000000..eb20e34c466 --- /dev/null +++ b/changelogs/unreleased/50281-js-pages-do-not-load-on-windows-8-ie-11.yml @@ -0,0 +1,5 @@ +--- +title: Fix broken JavaScript in IE11 +merge_request: 21214 +author: +type: fixed diff --git a/changelogs/unreleased/auto-devops-gitlab-ci-glic-228.yml b/changelogs/unreleased/auto-devops-gitlab-ci-glic-228.yml new file mode 100644 index 00000000000..a1625193189 --- /dev/null +++ b/changelogs/unreleased/auto-devops-gitlab-ci-glic-228.yml @@ -0,0 +1,5 @@ +--- +title: 'Auto-DevOps.gitlab-ci.yml: update glibc package to 2.28' +merge_request: 21191 +author: sgerrand +type: fixed diff --git a/changelogs/unreleased/expose-all-artifacts-sizes-in-jobs-api.yml b/changelogs/unreleased/expose-all-artifacts-sizes-in-jobs-api.yml new file mode 100644 index 00000000000..1453d39934b --- /dev/null +++ b/changelogs/unreleased/expose-all-artifacts-sizes-in-jobs-api.yml @@ -0,0 +1,5 @@ +--- +title: Expose all artifacts sizes in jobs api +merge_request: 20821 +author: Peter Marko +type: added diff --git a/changelogs/unreleased/mk-bump-rainbow-gem.yml b/changelogs/unreleased/mk-bump-rainbow-gem.yml new file mode 100644 index 00000000000..31c003fb4d9 --- /dev/null +++ b/changelogs/unreleased/mk-bump-rainbow-gem.yml @@ -0,0 +1,5 @@ +--- +title: Fix bin/secpick error and security branch prefixing +merge_request: 21210 +author: +type: fixed diff --git a/changelogs/unreleased/tz-mr-incremental-rendering.yml b/changelogs/unreleased/tz-mr-incremental-rendering.yml new file mode 100644 index 00000000000..a35fa200363 --- /dev/null +++ b/changelogs/unreleased/tz-mr-incremental-rendering.yml @@ -0,0 +1,4 @@ +title: Incremental rendering with Vue on merge request page +merge_request: 21063 +author: +type: performance diff --git a/doc/api/jobs.md b/doc/api/jobs.md index 9a950097675..4bf65a8fafd 100644 --- a/doc/api/jobs.md +++ b/doc/api/jobs.md @@ -33,7 +33,6 @@ Example of response }, "coverage": null, "created_at": "2015-12-24T15:51:21.727Z", - "artifacts_file": null, "finished_at": "2015-12-24T17:54:24.921Z", "artifacts_expire_at": "2016-01-23T17:54:24.921Z", "id": 6, @@ -45,6 +44,7 @@ Example of response "status": "pending" }, "ref": "master", + "artifacts": [], "runner": null, "stage": "test", "started_at": "2015-12-24T17:54:24.729Z", @@ -82,6 +82,12 @@ Example of response "filename": "artifacts.zip", "size": 1000 }, + "artifacts": [ + {"file_type": "archive", "size": 1000, "filename": "artifacts.zip", "file_format": "zip"}, + {"file_type": "metadata", "size": 186, "filename": "metadata.gz", "file_format": "gzip"}, + {"file_type": "trace", "size": 1500, "filename": "job.log", "file_format": "raw"}, + {"file_type": "junit", "size": 750, "filename": "junit.xml.gz", "file_format": "gzip"} + ], "finished_at": "2015-12-24T17:54:27.895Z", "artifacts_expire_at": "2016-01-23T17:54:27.895Z", "id": 7, @@ -93,6 +99,7 @@ Example of response "status": "pending" }, "ref": "master", + "artifacts": [], "runner": null, "stage": "test", "started_at": "2015-12-24T17:54:27.722Z", @@ -151,7 +158,6 @@ Example of response }, "coverage": null, "created_at": "2015-12-24T15:51:21.727Z", - "artifacts_file": null, "finished_at": "2015-12-24T17:54:24.921Z", "artifacts_expire_at": "2016-01-23T17:54:24.921Z", "id": 6, @@ -163,6 +169,7 @@ Example of response "status": "pending" }, "ref": "master", + "artifacts": [], "runner": null, "stage": "test", "started_at": "2015-12-24T17:54:24.729Z", @@ -200,6 +207,12 @@ Example of response "filename": "artifacts.zip", "size": 1000 }, + "artifacts": [ + {"file_type": "archive", "size": 1000, "filename": "artifacts.zip", "file_format": "zip"}, + {"file_type": "metadata", "size": 186, "filename": "metadata.gz", "file_format": "gzip"}, + {"file_type": "trace", "size": 1500, "filename": "job.log", "file_format": "raw"}, + {"file_type": "junit", "size": 750, "filename": "junit.xml.gz", "file_format": "gzip"} + ], "finished_at": "2015-12-24T17:54:27.895Z", "artifacts_expire_at": "2016-01-23T17:54:27.895Z", "id": 7, @@ -211,6 +224,7 @@ Example of response "status": "pending" }, "ref": "master", + "artifacts": [], "runner": null, "stage": "test", "started_at": "2015-12-24T17:54:27.722Z", @@ -267,7 +281,6 @@ Example of response }, "coverage": null, "created_at": "2015-12-24T15:51:21.880Z", - "artifacts_file": null, "finished_at": "2015-12-24T17:54:31.198Z", "artifacts_expire_at": "2016-01-23T17:54:31.198Z", "id": 8, @@ -279,6 +292,7 @@ Example of response "status": "pending" }, "ref": "master", + "artifacts": [], "runner": null, "stage": "test", "started_at": "2015-12-24T17:54:30.733Z", @@ -458,11 +472,11 @@ Example of response }, "coverage": null, "created_at": "2016-01-11T10:13:33.506Z", - "artifacts_file": null, "finished_at": "2016-01-11T10:14:09.526Z", "id": 42, "name": "rubocop", "ref": "master", + "artifacts": [], "runner": null, "stage": "test", "started_at": null, @@ -505,11 +519,11 @@ Example of response }, "coverage": null, "created_at": "2016-01-11T10:13:33.506Z", - "artifacts_file": null, "finished_at": null, "id": 42, "name": "rubocop", "ref": "master", + "artifacts": [], "runner": null, "stage": "test", "started_at": null, @@ -559,6 +573,7 @@ Example of response "id": 42, "name": "rubocop", "ref": "master", + "artifacts": [], "runner": null, "stage": "test", "created_at": "2016-01-11T10:13:33.506Z", @@ -610,6 +625,7 @@ Example response: "id": 42, "name": "rubocop", "ref": "master", + "artifacts": [], "runner": null, "stage": "test", "created_at": "2016-01-11T10:13:33.506Z", @@ -654,11 +670,11 @@ Example of response }, "coverage": null, "created_at": "2016-01-11T10:13:33.506Z", - "artifacts_file": null, "finished_at": null, "id": 42, "name": "rubocop", "ref": "master", + "artifacts": [], "runner": null, "stage": "test", "started_at": null, diff --git a/doc/api/system_hooks.md b/doc/api/system_hooks.md index dd424470b67..7b8db6cfa8f 100644 --- a/doc/api/system_hooks.md +++ b/doc/api/system_hooks.md @@ -34,6 +34,7 @@ Example response: "push_events":true, "tag_push_events":false, "merge_requests_events": true, + "repository_update_events": true, "enable_ssl_verification":true } ] @@ -56,6 +57,7 @@ POST /hooks | `push_events` | boolean | no | When true, the hook will fire on push events | | `tag_push_events` | boolean | no | When true, the hook will fire on new tags being pushed | | `merge_requests_events` | boolean | no | Trigger hook on merge requests events | +| `repository_update_events` | boolean | no | Trigger hook on repository update events | | `enable_ssl_verification` | boolean | no | Do SSL verification when triggering the hook | Example request: @@ -75,6 +77,7 @@ Example response: "push_events":true, "tag_push_events":false, "merge_requests_events": true, + "repository_update_events": true, "enable_ssl_verification":true } ] @@ -127,4 +130,4 @@ Example request: ```bash curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/hooks/2 -``` +```
\ No newline at end of file diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 453ebb9c669..458ee320099 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -1080,6 +1080,10 @@ module API expose :filename, :size end + class JobArtifact < Grape::Entity + expose :file_type, :size, :filename, :file_format + end + class JobBasic < Grape::Entity expose :id, :status, :stage, :name, :ref, :tag, :coverage expose :created_at, :started_at, :finished_at @@ -1094,7 +1098,9 @@ module API end class Job < JobBasic + # artifacts_file is included in job_artifacts, but kept for backward compatibility (remove in api/v5) expose :artifacts_file, using: JobArtifactFile, if: -> (job, opts) { job.artifacts? } + expose :job_artifacts, as: :artifacts, using: JobArtifact expose :runner, with: Runner expose :artifacts_expire_at end diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb index 10c6e565f09..fc8c52085ab 100644 --- a/lib/api/jobs.rb +++ b/lib/api/jobs.rb @@ -38,7 +38,7 @@ module API builds = user_project.builds.order('id DESC') builds = filter_builds(builds, params[:scope]) - builds = builds.preload(:user, :job_artifacts_archive, :runner, pipeline: :project) + builds = builds.preload(:user, :job_artifacts_archive, :job_artifacts, :runner, pipeline: :project) present paginate(builds), with: Entities::Job end @@ -54,7 +54,7 @@ module API pipeline = user_project.pipelines.find(params[:pipeline_id]) builds = pipeline.builds builds = filter_builds(builds, params[:scope]) - builds = builds.preload(:job_artifacts_archive, project: [:namespace]) + builds = builds.preload(:job_artifacts_archive, :job_artifacts, project: [:namespace]) present paginate(builds), with: Entities::Job end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 8f3914c5f69..e5e818f57b9 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -2971,6 +2971,9 @@ msgstr "" msgid "IDE|Review" msgstr "" +msgid "IP Address" +msgstr "" + msgid "Identifier" msgstr "" @@ -3061,6 +3064,9 @@ msgstr "" msgid "Incompatible Project" msgstr "" +msgid "Indicates whether this runner can pick jobs without tags" +msgstr "" + msgid "Inline" msgstr "" @@ -3133,12 +3139,30 @@ msgstr "" msgid "Jobs" msgstr "" +msgid "Job|Browse" +msgstr "" + +msgid "Job|Download" +msgstr "" + +msgid "Job|Job artifacts" +msgstr "" + msgid "Job|Job has been erased" msgstr "" msgid "Job|Job has been erased by" msgstr "" +msgid "Job|Keep" +msgstr "" + +msgid "Job|The artifacts were removed" +msgstr "" + +msgid "Job|The artifacts will be removed" +msgstr "" + msgid "Jul" msgstr "" @@ -3390,6 +3414,9 @@ msgstr "" msgid "Maximum git storage failures" msgstr "" +msgid "Maximum job timeout" +msgstr "" + msgid "May" msgstr "" @@ -3932,6 +3959,9 @@ msgstr "" msgid "Pause" msgstr "" +msgid "Paused Runners don't accept new jobs" +msgstr "" + msgid "Pending" msgstr "" @@ -4424,6 +4454,9 @@ msgstr "" msgid "Promote to group label" msgstr "" +msgid "Protected" +msgstr "" + msgid "Protip:" msgstr "" @@ -4639,6 +4672,9 @@ msgstr "" msgid "Revoke" msgstr "" +msgid "Run untagged jobs" +msgstr "" + msgid "Runner token" msgstr "" @@ -5480,9 +5516,15 @@ msgstr "" msgid "This repository" msgstr "" +msgid "This runner will only run on pipelines triggered on protected branches" +msgstr "" + msgid "This source diff could not be displayed because it is too large." msgstr "" +msgid "This timeout will take precedence when lower than Project-defined timeout" +msgstr "" + msgid "This user has no identities" msgstr "" @@ -5724,6 +5766,9 @@ msgstr "" msgid "ToggleButton|Toggle Status: ON" msgstr "" +msgid "Token" +msgstr "" + msgid "Too many changes to show." msgstr "" @@ -6150,6 +6195,9 @@ 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." +msgstr "" + msgid "You cannot write to this read-only GitLab instance." msgstr "" diff --git a/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb b/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb index c1608be402a..fd4175d5227 100644 --- a/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb +++ b/spec/features/merge_request/user_sees_mr_with_deleted_source_branch_spec.rb @@ -28,7 +28,7 @@ describe 'Merge request > User sees MR with deleted source branch', :js do click_on 'Changes' wait_for_requests - expect(page).to have_selector('.diffs.tab-pane .nothing-here-block') + expect(page).to have_selector('.diffs.tab-pane .file-holder') expect(page).to have_content('Source branch does not exist.') end end diff --git a/spec/helpers/icons_helper_spec.rb b/spec/helpers/icons_helper_spec.rb index 82f588d1a08..4b40d523287 100644 --- a/spec/helpers/icons_helper_spec.rb +++ b/spec/helpers/icons_helper_spec.rb @@ -80,6 +80,26 @@ describe IconsHelper do end end + describe 'audit icon' do + it 'returns right icon name for standard auth' do + icon_name = 'standard' + expect(audit_icon(icon_name).to_s) + .to eq '<i class="fa fa-key"></i>' + end + + it 'returns right icon name for two-factor auth' do + icon_name = 'two-factor' + expect(audit_icon(icon_name).to_s) + .to eq '<i class="fa fa-key"></i>' + end + + it 'returns right icon name for google_oauth2 auth' do + icon_name = 'google_oauth2' + expect(audit_icon(icon_name).to_s) + .to eq '<i class="fa fa-google"></i>' + end + end + describe 'file_type_icon_class' do it 'returns folder class' do expect(file_type_icon_class('folder', 0, 'folder_name')).to eq 'folder' diff --git a/spec/javascripts/diffs/components/diff_file_spec.js b/spec/javascripts/diffs/components/diff_file_spec.js index 7a4616ec8eb..44a38f7ca82 100644 --- a/spec/javascripts/diffs/components/diff_file_spec.js +++ b/spec/javascripts/diffs/components/diff_file_spec.js @@ -22,11 +22,18 @@ describe('DiffFile', () => { expect(el.id).toEqual(fileHash); expect(el.classList.contains('diff-file')).toEqual(true); + expect(el.querySelectorAll('.diff-content.hidden').length).toEqual(0); expect(el.querySelector('.js-file-title')).toBeDefined(); expect(el.querySelector('.file-title-name').innerText.indexOf(filePath) > -1).toEqual(true); expect(el.querySelector('.js-syntax-highlight')).toBeDefined(); - expect(el.querySelectorAll('.line_content').length > 5).toEqual(true); + + expect(vm.file.renderIt).toEqual(false); + vm.file.renderIt = true; + + vm.$nextTick(() => { + expect(el.querySelectorAll('.line_content').length > 5).toEqual(true); + }); }); describe('collapsed', () => { @@ -34,6 +41,7 @@ describe('DiffFile', () => { expect(vm.$el.querySelectorAll('.diff-content').length).toEqual(1); expect(vm.file.collapsed).toEqual(false); vm.file.collapsed = true; + vm.file.renderIt = true; vm.$nextTick(() => { expect(vm.$el.querySelectorAll('.diff-content').length).toEqual(0); diff --git a/spec/javascripts/diffs/mock_data/diff_file.js b/spec/javascripts/diffs/mock_data/diff_file.js index d3bf9525924..cce36ecc91f 100644 --- a/spec/javascripts/diffs/mock_data/diff_file.js +++ b/spec/javascripts/diffs/mock_data/diff_file.js @@ -39,6 +39,7 @@ export default { viewPath: '/gitlab-org/gitlab-test/blob/spooky-stuff/CHANGELOG', replacedViewPath: null, collapsed: false, + renderIt: false, tooLarge: false, contextLinesPath: '/gitlab-org/gitlab-test/blob/c48ee0d1bf3b30453f5b32250ce03134beaa6d13/CHANGELOG/diff', diff --git a/spec/javascripts/diffs/store/mutations_spec.js b/spec/javascripts/diffs/store/mutations_spec.js index 1af49f4985c..8f89984c6e5 100644 --- a/spec/javascripts/diffs/store/mutations_spec.js +++ b/spec/javascripts/diffs/store/mutations_spec.js @@ -1,6 +1,7 @@ import mutations from '~/diffs/store/mutations'; import * as types from '~/diffs/store/mutation_types'; import { INLINE_DIFF_VIEW_TYPE } from '~/diffs/constants'; +import diffFileMockData from '../mock_data/diff_file'; describe('DiffsStoreMutations', () => { describe('SET_BASE_CONFIG', () => { @@ -24,6 +25,23 @@ describe('DiffsStoreMutations', () => { }); }); + describe('SET_DIFF_DATA', () => { + it('should set diff data type properly', () => { + const state = {}; + const diffMock = { + diff_files: [diffFileMockData], + }; + + mutations[types.SET_DIFF_DATA](state, diffMock); + + const firstLine = state.diffFiles[0].parallelDiffLines[0]; + + expect(firstLine.right.text).toBeUndefined(); + expect(state.diffFiles[0].renderIt).toEqual(true); + expect(state.diffFiles[0].collapsed).toEqual(false); + }); + }); + describe('SET_DIFF_VIEW_TYPE', () => { it('should set diff view type properly', () => { const state = {}; diff --git a/spec/javascripts/jobs/artifacts_block_spec.js b/spec/javascripts/jobs/artifacts_block_spec.js new file mode 100644 index 00000000000..c544c6f3e89 --- /dev/null +++ b/spec/javascripts/jobs/artifacts_block_spec.js @@ -0,0 +1,120 @@ +import Vue from 'vue'; +import { getTimeago } from '~/lib/utils/datetime_utility'; +import component from '~/jobs/components/artifacts_block.vue'; +import mountComponent from '../helpers/vue_mount_component_helper'; + +describe('Artifacts block', () => { + const Component = Vue.extend(component); + let vm; + + const expireAt = '2018-08-14T09:38:49.157Z'; + const timeago = getTimeago(); + const formatedDate = timeago.format(expireAt); + + afterEach(() => { + vm.$destroy(); + }); + + describe('with expired artifacts', () => { + it('renders expired artifact date and info', () => { + vm = mountComponent(Component, { + haveArtifactsExpired: true, + willArtifactsExpire: false, + expireAt, + }); + + expect(vm.$el.querySelector('.js-artifacts-removed')).not.toBeNull(); + expect(vm.$el.querySelector('.js-artifacts-will-be-removed')).toBeNull(); + expect(vm.$el.textContent).toContain(formatedDate); + }); + }); + + describe('with artifacts that will expire', () => { + it('renders will expire artifact date and info', () => { + vm = mountComponent(Component, { + haveArtifactsExpired: false, + willArtifactsExpire: true, + expireAt, + }); + + expect(vm.$el.querySelector('.js-artifacts-removed')).toBeNull(); + expect(vm.$el.querySelector('.js-artifacts-will-be-removed')).not.toBeNull(); + expect(vm.$el.textContent).toContain(formatedDate); + }); + }); + + describe('when the user can keep the artifacts', () => { + it('renders the keep button', () => { + vm = mountComponent(Component, { + haveArtifactsExpired: true, + willArtifactsExpire: false, + expireAt, + keepArtifactsPath: '/keep', + }); + + expect(vm.$el.querySelector('.js-keep-artifacts')).not.toBeNull(); + }); + }); + + describe('when the user can not keep the artifacts', () => { + it('does not render the keep button', () => { + vm = mountComponent(Component, { + haveArtifactsExpired: true, + willArtifactsExpire: false, + expireAt, + }); + + expect(vm.$el.querySelector('.js-keep-artifacts')).toBeNull(); + }); + }); + + describe('when the user can download the artifacts', () => { + it('renders the download button', () => { + vm = mountComponent(Component, { + haveArtifactsExpired: true, + willArtifactsExpire: false, + expireAt, + downloadArtifactsPath: '/download', + }); + + expect(vm.$el.querySelector('.js-download-artifacts')).not.toBeNull(); + }); + }); + + describe('when the user can not download the artifacts', () => { + it('does not render the keep button', () => { + vm = mountComponent(Component, { + haveArtifactsExpired: true, + willArtifactsExpire: false, + expireAt, + }); + + expect(vm.$el.querySelector('.js-download-artifacts')).toBeNull(); + }); + }); + + describe('when the user can browse the artifacts', () => { + it('does not render the browse button', () => { + vm = mountComponent(Component, { + haveArtifactsExpired: true, + willArtifactsExpire: false, + expireAt, + browseArtifactsPath: '/browse', + }); + + expect(vm.$el.querySelector('.js-browse-artifacts')).not.toBeNull(); + }); + }); + + describe('when the user can not browse the artifacts', () => { + it('does not render the browse button', () => { + vm = mountComponent(Component, { + haveArtifactsExpired: true, + willArtifactsExpire: false, + expireAt, + }); + + expect(vm.$el.querySelector('.js-browse-artifacts')).toBeNull(); + }); + }); +}); diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb index 5814d834572..6adbbb40489 100644 --- a/spec/requests/api/jobs_spec.rb +++ b/spec/requests/api/jobs_spec.rb @@ -3,6 +3,32 @@ require 'spec_helper' describe API::Jobs do include HttpIOHelpers + shared_examples 'a job with artifacts and trace' do |result_is_array: true| + context 'with artifacts and trace' do + let!(:second_job) { create(:ci_build, :trace_artifact, :artifacts, :test_reports, pipeline: pipeline) } + + it 'returns artifacts and trace data', :skip_before_request do + get api(api_endpoint, api_user) + json_job = result_is_array ? json_response.select { |job| job['id'] == second_job.id }.first : json_response + + expect(json_job['artifacts_file']).not_to be_nil + expect(json_job['artifacts_file']).not_to be_empty + expect(json_job['artifacts_file']['filename']).to eq(second_job.artifacts_file.filename) + expect(json_job['artifacts_file']['size']).to eq(second_job.artifacts_file.size) + expect(json_job['artifacts']).not_to be_nil + expect(json_job['artifacts']).to be_an Array + expect(json_job['artifacts'].size).to eq(second_job.job_artifacts.length) + json_job['artifacts'].each do |artifact| + expect(artifact).not_to be_nil + file_type = Ci::JobArtifact.file_types[artifact['file_type']] + expect(artifact['size']).to eq(second_job.job_artifacts.where(file_type: file_type).first.size) + expect(artifact['filename']).to eq(second_job.job_artifacts.where(file_type: file_type).first.filename) + expect(artifact['file_format']).to eq(second_job.job_artifacts.where(file_type: file_type).first.file_format) + end + end + end + end + set(:project) do create(:project, :repository, public_builds: false) end @@ -49,6 +75,20 @@ describe API::Jobs do expect(Time.parse(json_response.first['artifacts_expire_at'])).to be_like_time(job.artifacts_expire_at) end + context 'without artifacts and trace' do + it 'returns no artifacts nor trace data' do + json_job = json_response.first + + expect(json_job['artifacts_file']).to be_nil + expect(json_job['artifacts']).to be_an Array + expect(json_job['artifacts']).to be_empty + end + end + + it_behaves_like 'a job with artifacts and trace' do + let(:api_endpoint) { "/projects/#{project.id}/jobs" } + end + it 'returns pipeline data' do json_job = json_response.first @@ -60,7 +100,7 @@ describe API::Jobs do end it 'avoids N+1 queries', :skip_before_request do - first_build = create(:ci_build, :artifacts, pipeline: pipeline) + first_build = create(:ci_build, :trace_artifact, :artifacts, :test_reports, pipeline: pipeline) first_build.runner = create(:ci_runner) first_build.user = create(:user) first_build.save @@ -68,7 +108,7 @@ describe API::Jobs do control_count = ActiveRecord::QueryRecorder.new { go }.count second_pipeline = create(:ci_empty_pipeline, project: project, sha: project.commit.id, ref: project.default_branch) - second_build = create(:ci_build, :artifacts, pipeline: second_pipeline) + second_build = create(:ci_build, :trace_artifact, :artifacts, :test_reports, pipeline: second_pipeline) second_build.runner = create(:ci_runner) second_build.user = create(:user) second_build.save @@ -117,9 +157,11 @@ describe API::Jobs do describe 'GET /projects/:id/pipelines/:pipeline_id/jobs' do let(:query) { Hash.new } - before do - job - get api("/projects/#{project.id}/pipelines/#{pipeline.id}/jobs", api_user), query + before do |example| + unless example.metadata[:skip_before_request] + job + get api("/projects/#{project.id}/pipelines/#{pipeline.id}/jobs", api_user), query + end end context 'authorized user' do @@ -133,6 +175,13 @@ describe API::Jobs do expect(json_response).not_to be_empty expect(json_response.first['commit']['id']).to eq project.commit.id expect(Time.parse(json_response.first['artifacts_expire_at'])).to be_like_time(job.artifacts_expire_at) + expect(json_response.first['artifacts_file']).to be_nil + expect(json_response.first['artifacts']).to be_an Array + expect(json_response.first['artifacts']).to be_empty + end + + it_behaves_like 'a job with artifacts and trace' do + let(:api_endpoint) { "/projects/#{project.id}/pipelines/#{pipeline.id}/jobs" } end it 'returns pipeline data' do @@ -183,7 +232,7 @@ describe API::Jobs do get api("/projects/#{project.id}/pipelines/#{pipeline.id}/jobs", api_user), query end.count - 3.times { create(:ci_build, :artifacts, pipeline: pipeline) } + 3.times { create(:ci_build, :trace_artifact, :artifacts, :test_reports, pipeline: pipeline) } expect do get api("/projects/#{project.id}/pipelines/#{pipeline.id}/jobs", api_user), query @@ -201,8 +250,10 @@ describe API::Jobs do end describe 'GET /projects/:id/jobs/:job_id' do - before do - get api("/projects/#{project.id}/jobs/#{job.id}", api_user) + before do |example| + unless example.metadata[:skip_before_request] + get api("/projects/#{project.id}/jobs/#{job.id}", api_user) + end end context 'authorized user' do @@ -219,10 +270,17 @@ describe API::Jobs do expect(Time.parse(json_response['started_at'])).to be_like_time(job.started_at) expect(Time.parse(json_response['finished_at'])).to be_like_time(job.finished_at) expect(Time.parse(json_response['artifacts_expire_at'])).to be_like_time(job.artifacts_expire_at) + expect(json_response['artifacts_file']).to be_nil + expect(json_response['artifacts']).to be_an Array + expect(json_response['artifacts']).to be_empty expect(json_response['duration']).to eq(job.duration) expect(json_response['web_url']).to be_present end + it_behaves_like 'a job with artifacts and trace', result_is_array: false do + let(:api_endpoint) { "/projects/#{project.id}/jobs/#{second_job.id}" } + end + it 'returns pipeline data' do json_job = json_response diff --git a/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml b/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml index 39876805ffa..ffcf5648075 100644 --- a/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml +++ b/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml @@ -642,9 +642,9 @@ 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.23-r3/glibc-2.23-r3.apk - apk add glibc-2.23-r3.apk - rm glibc-2.23-r3.apk + wget 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 curl "https://kubernetes-helm.storage.googleapis.com/helm-v${HELM_VERSION}-linux-amd64.tar.gz" | tar zx mv linux-amd64/helm /usr/bin/ |