Commit 9615f7cb authored by Achilleas Pipinellis's avatar Achilleas Pipinellis

Merge branch 'ce-to-ee-2018-08-15' into 'master'

CE upstream - 2018-08-15 15:21 UTC

Closes gitlab-ce#49953

See merge request gitlab-org/gitlab-ee!6905
parents 071d60bb 681b0db6
......@@ -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
......
......@@ -190,7 +190,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'
......
......@@ -720,8 +720,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)
......@@ -1171,7 +1170,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)
......
......@@ -730,8 +730,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)
......@@ -1184,7 +1183,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)
......
......@@ -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';
......
......@@ -114,9 +114,13 @@ export default {
this.adjustView();
},
methods: {
...mapActions('diffs', ['setBaseConfig', 'fetchDiffFiles']),
...mapActions('diffs', ['setBaseConfig', 'fetchDiffFiles', 'startRenderDiffsQueue']),
fetchData() {
this.fetchDiffFiles().catch(() => {
this.fetchDiffFiles()
.then(() => {
requestIdleCallback(this.startRenderDiffsQueue, { timeout: 1000 });
})
.catch(() => {
createFlash(__('Something went wrong on our end. Please try again!'));
});
......
......@@ -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
......
......@@ -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;
......@@ -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);
......
......@@ -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';
......@@ -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,
});
},
......
<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>
......@@ -255,6 +255,7 @@ module ApplicationSettingsHelper
:usage_ping_enabled,
:instance_statistics_visibility_private,
:user_default_external,
:user_show_add_ssh_key_message,
:user_oauth_applications,
:version_check_enabled,
:web_ide_clientside_preview_enabled
......
......@@ -74,7 +74,11 @@ module ButtonHelper
end
def ssh_clone_button(project, append_link: true)
dropdown_description = _("You won't be able to pull or push project code via SSH until you add an SSH key to your profile") if current_user.try(:require_ssh_key?)
if Gitlab::CurrentSettings.user_show_add_ssh_key_message? &&
current_user.try(:require_ssh_key?)
dropdown_description = _("You won't be able to pull or push project code via SSH until you add an SSH key to your profile")
end
append_url = project.ssh_url_to_repo if append_link
geo_url = geo_primary_ssh_url_to_repo(project) if Gitlab::Geo.secondary?
......
......@@ -194,7 +194,10 @@ module ProjectsHelper
end
def show_no_ssh_key_message?
cookies[:hide_no_ssh_message].blank? && !current_user.hide_no_ssh_key && current_user.require_ssh_key?
Gitlab::CurrentSettings.user_show_add_ssh_key_message? &&
cookies[:hide_no_ssh_message].blank? &&
!current_user.hide_no_ssh_key &&
current_user.require_ssh_key?
end
def show_no_password_message?
......
......@@ -299,7 +299,8 @@ class ApplicationSetting < ActiveRecord::Base
unique_ips_limit_time_window: 3600,
usage_ping_enabled: Settings.gitlab['usage_ping_enabled'],
instance_statistics_visibility_private: false,
user_default_external: false
user_default_external: false,
user_show_add_ssh_key_message: true
}
end
......
......@@ -32,6 +32,12 @@
= f.check_box :user_default_external, class: 'form-check-input'
= f.label :user_default_external, class: 'form-check-label' do
Newly registered users will by default be external
.form-group
= f.label :user_show_add_ssh_key_message, 'Prompt users to upload SSH keys', class: 'label-bold'
.form-check
= f.check_box :user_show_add_ssh_key_message, class: 'form-check-input'
= f.label :user_show_add_ssh_key_message, class: 'form-check-label' do
Inform users without uploaded SSH keys that they can't push over SSH until one is added
- if ::Gitlab.dev_env_or_com?
.form-group
......
= 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'
......@@ -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}"
......
---
title: Fix checkboxes on runner admin settings - The labels are now clickable
merge_request:
author:
type: fixed
---
title: Add ability to suppress the global "You won't be able to use SSH" message
merge_request: 21027
author: Ævar Arnfjörð Bjarmason
type: added
---
title: Creates Vue component for artifacts block on job page
merge_request:
author:
type: other
---
title: Fix broken JavaScript in IE11
merge_request: 21214
author:
type: fixed
---
title: 'Auto-DevOps.gitlab-ci.yml: update glibc package to 2.28'
merge_request: 21191
author: sgerrand
type: fixed
---
title: Add Czech as an available language.
merge_request: 21201
author:
type: added
---
title: Fix bin/secpick error and security branch prefixing
merge_request: 21210
author:
type: fixed
title: Incremental rendering with Vue on merge request page
merge_request: 21063
author:
type: performance
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddUserShowAddSshKeyMessageToApplicationSettings < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
disable_ddl_transaction!
def up
add_column_with_default :application_settings, :user_show_add_ssh_key_message, :boolean, default: true, allow_null: false
end
def down
remove_column :application_settings, :user_show_add_ssh_key_message
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20180807153545) do
ActiveRecord::Schema.define(version: 20180808162000) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
......@@ -215,6 +215,7 @@ ActiveRecord::Schema.define(version: 20180807153545) do
t.string "snowplow_cookie_domain"
t.boolean "instance_statistics_visibility_private", default: false, null: false
t.boolean "web_ide_clientside_preview_enabled", default: false, null: false
t.boolean "user_show_add_ssh_key_message", default: true, null: false
t.integer "custom_project_templates_group_id"
end
......
......@@ -163,3 +163,20 @@ Such a restriction can currently be hacked in by e.g. providing a
custom `AuthorizedKeysCommand` which checks if the discovered key-ID
returned from `gitlab-shell-authorized-keys-check` is a deploy key or
not (all non-deploy keys should be refused).
## Disabling the global warning about users lacking SSH keys
By default GitLab will show a "You won't be able to pull or push
project code via SSH" warning to users who have not uploaded an SSH
key to their profile.
This is counterproductive when using SSH certificates, since users
aren't expected to upload their own keys.
To disable this warning globally, go to "Application settings ->
Account and limit settings" and disable the "Show user add SSH key
message" setting.
This setting was added specifically for use with SSH certificates, but
can be turned off without using them if you'd like to hide the warning
for some other reason.
......@@ -57,6 +57,7 @@ Example response:
"terms": "Hello world!",
"performance_bar_allowed_group_id": 42,
"instance_statistics_visibility_private": false,
"user_show_add_ssh_key_message": true
"file_template_project_id": 1
}
```
......@@ -189,6 +190,8 @@ PUT /application/settings
| `enforce_terms` | boolean | no | Enforce application ToS to all users |
| `terms` | text | yes (if `enforce_terms` is true) | Markdown content for the ToS |
| `instance_statistics_visibility_private` | boolean | no | When set to `true` Instance statistics will only be available to admins |
| `user_show_add_ssh_key_message` | boolean | no | When set to `false` disable the "You won't be able to pull or push
+project code via SSH" warning shown to users with no uploaded SSH key |
```bash
curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/application/settings?signup_enabled=false&default_project_visibility=internal
......@@ -239,6 +242,7 @@ Example response:
"terms": "Hello world!",
"performance_bar_allowed_group_id": 42,
"instance_statistics_visibility_private": false,
"user_show_add_ssh_key_message": true
"file_template_project_id": 1
}
```
......@@ -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
}
]
......
......@@ -22,7 +22,8 @@ module Gitlab
'tr_TR' => 'Türkçe',
'id_ID' => 'Bahasa Indonesia',
'fil_PH' => 'Filipino',
'pl_PL' => 'Polski'
'pl_PL' => 'Polski',
'cs_CZ' => 'Čeština'
}.freeze
def available_locales
......
......@@ -3864,6 +3864,9 @@ msgstr ""
msgid "IDE|Review"
msgstr ""
msgid "IP Address"
msgstr ""
msgid "Identifier"
msgstr ""
......@@ -3978,6 +3981,9 @@ msgstr ""
msgid "Incompatible Project"
msgstr ""
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
msgid "Inline"
msgstr ""
......@@ -4067,12 +4073,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 "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
msgstr ""
......@@ -4413,6 +4437,9 @@ msgstr ""
msgid "Maximum git storage failures"
msgstr ""
msgid "Maximum job timeout"
msgstr ""
msgid "May"
msgstr ""
......@@ -5134,6 +5161,9 @@ msgstr ""
msgid "Pause"
msgstr ""
msgid "Paused Runners don't accept new jobs"
msgstr ""
msgid "Pending"
msgstr ""
......@@ -5752,6 +5782,9 @@ msgstr ""
msgid "Promotions|Upgrade plan"
msgstr ""
msgid "Protected"
msgstr ""
msgid "Protected Environments"
msgstr ""
......@@ -6068,6 +6101,9 @@ msgstr ""
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
msgid "Run untagged jobs"
msgstr ""
msgid "Runner token"
msgstr ""
......@@ -7115,9 +7151,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 ""
......@@ -7392,6 +7434,9 @@ msgstr ""
msgid "ToggleButton|Toggle Status: ON"
msgstr ""
msgid "Token"
msgstr ""
msgid "Too many changes to show."
msgstr ""
......@@ -7896,6 +7941,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 a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
......
......@@ -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
......@@ -79,6 +79,18 @@ describe ButtonHelper do
end
end
context 'without an ssh key on the user and user_show_add_ssh_key_message unset' do
before do
stub_application_setting(user_show_add_ssh_key_message: false)
end
it 'there is no warning on the dropdown description' do
description = element.search('.dropdown-menu-inner-content').first
expect(description).to be_nil
end
end
context 'with an ssh key on the user' do
before do
create(:key, user: user)
......
......@@ -22,18 +22,26 @@ 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(vm.file.renderIt).toEqual(false);
vm.file.renderIt = true;
vm.$nextTick(() => {
expect(el.querySelectorAll('.line_content').length > 5).toEqual(true);
});
});
describe('collapsed', () => {
it('should not have file content', done => {
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);
......
......@@ -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',
......
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 = {};
......
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();
});
});
});
......@@ -30,7 +30,7 @@ describe InternalId do
context 'with existing issues' do
before do
rand(1..10).times { create(:issue, project: project) }
create_list(:issue, 2, project: project)
described_class.delete_all
end
......@@ -54,7 +54,7 @@ describe InternalId do
end
it 'generates a strictly monotone, gapless sequence' do
seq = (0..rand(100)).map do
seq = Array.new(10).map do
described_class.generate_next(issue, scope, usage, init)
end
normalized = seq.map { |i| i - seq.min }
......
......@@ -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/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment