Commit cb3e6b9c authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent dee93158
......@@ -54,11 +54,12 @@ export default {
showLoadingIcon() {
return this.isLoadingCollapsedDiff || (!this.file.renderIt && !this.isCollapsed);
},
hasDiffLines() {
hasDiff() {
return (
this.file.highlighted_diff_lines &&
(this.file.highlighted_diff_lines &&
this.file.parallel_diff_lines &&
this.file.parallel_diff_lines.length > 0
this.file.parallel_diff_lines.length > 0) ||
!this.file.blob.readable_text
);
},
isFileTooLarge() {
......@@ -82,7 +83,7 @@ export default {
},
watch: {
isCollapsed: function fileCollapsedWatch(newVal, oldVal) {
if (!newVal && oldVal && !this.hasDiffLines) {
if (!newVal && oldVal && !this.hasDiff) {
this.handleLoadCollapsedDiff();
}
......@@ -103,7 +104,7 @@ export default {
'setFileCollapsed',
]),
handleToggle() {
if (!this.hasDiffLines) {
if (!this.hasDiff) {
this.handleLoadCollapsedDiff();
} else {
this.isCollapsed = !this.isCollapsed;
......
---
title: 'fixed #27164 Image cannot be collapsed on merge request changes tab'
merge_request: 18917
author: Jannik Lehmann
type: fixed
---
title: Reduce the allocated IP for Cluster and Services
merge_request: 18341
author:
type: changed
---
title: Let ANSI \r code replace the current job log line
merge_request: 18933
author:
type: fixed
---
title: Add support for YAML anchors in CI scripts.
merge_request: 18849
author:
type: changed
......@@ -181,6 +181,25 @@ that the YAML parser knows to interpret the whole thing as a string rather than
a "key: value" pair. Be careful when using special characters:
`:`, `{`, `}`, `[`, `]`, `,`, `&`, `*`, `#`, `?`, `|`, `-`, `<`, `>`, `=`, `!`, `%`, `@`, `` ` ``.
#### YAML anchors for `script`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/23005) in GitLab 12.5.
You can use [YAML anchors](#anchors) with scripts, which makes it possible to
include a predefined list of commands in multiple jobs.
Example:
```yaml
.something: &something
- echo 'something'
job_name:
script:
- *something
- echo 'this is the script'
```
### `image`
Used to specify [a Docker image](../docker/using_docker_images.md#what-is-an-image) to use for the job.
......@@ -284,6 +303,33 @@ job:
- execute this after my script
```
#### YAML anchors for `before_script` and `after_script`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/23005) in GitLab 12.5.
You can use [YAML anchors](#anchors) with `before_script` and `after_script`,
which makes it possible to include a predefined list of commands in multiple
jobs.
Example:
```yaml
.something_before: &something_before
- echo 'something before'
.something_after: &something_after
- echo 'something after'
job_name:
before_script:
- *something_before
script:
- echo 'this is the script'
after_script:
- *something_after
```
### `stages`
`stages` is used to define stages that can be used by jobs and is defined
......
......@@ -175,6 +175,9 @@ NOTE: **Note:**
Starting from [GitLab 12.1](https://gitlab.com/gitlab-org/gitlab-foss/issues/55902), all GKE clusters
created by GitLab are RBAC-enabled. Take a look at the [RBAC section](#rbac-cluster-resources) for more information.
NOTE: **Note:**
Starting from [GitLab 12.5](https://gitlab.com/gitlab-org/gitlab/merge_requests/18341), the cluster's pod address IP range will be set to /16 instead of the regular /14. (/16 is a CIDR notation)
### Cloud Run on GKE
> [Introduced](https://gitlab.com/gitlab-org/gitlab/merge_requests/16566) in GitLab 12.4.
......
......@@ -22,11 +22,11 @@ module Gitlab
start_offset = @state.offset
@state.set_current_line!(style: Style.new(@state.inherited_style))
@state.new_line!(
style: Style.new(@state.inherited_style))
stream.each_line do |line|
s = StringScanner.new(line)
convert_line(s)
consume_line(line)
end
# This must be assigned before flushing the current line
......@@ -52,26 +52,43 @@ module Gitlab
private
def convert_line(scanner)
until scanner.eos?
def consume_line(line)
scanner = StringScanner.new(line)
if scanner.scan(Gitlab::Regex.build_trace_section_regex)
consume_token(scanner) until scanner.eos?
end
def consume_token(scanner)
if scan_token(scanner, Gitlab::Regex.build_trace_section_regex, consume: false)
handle_section(scanner)
elsif scanner.scan(/\e([@-_])(.*?)([@-~])/)
elsif scan_token(scanner, /\e([@-_])(.*?)([@-~])/)
handle_sequence(scanner)
elsif scanner.scan(/\e(([@-_])(.*?)?)?$/)
break
elsif scanner.scan(/</)
elsif scan_token(scanner, /\e(([@-_])(.*?)?)?$/)
# stop scanning
scanner.terminate
elsif scan_token(scanner, /</)
@state.current_line << '&lt;'
elsif scanner.scan(/\r?\n/)
# we advance the offset of the next current line
# so it does not start from \n
flush_current_line(advance_offset: scanner.matched_size)
elsif scan_token(scanner, /\r?\n/)
flush_current_line
elsif scan_token(scanner, /\r/)
# drop last line
@state.current_line.clear!
elsif scan_token(scanner, /.[^\e<\r\ns]*/m)
# this is a join from all previous tokens and first letters
# it always matches at least one character `.`
# it matches everything that is not start of:
# `\e`, `<`, `\r`, `\n`, `s` (for section_start)
@state.current_line << scanner[0]
else
@state.current_line << scanner.scan(/./m)
raise 'invalid parser state'
end
end
@state.offset += scanner.matched_size
def scan_token(scanner, match, consume: true)
scanner.scan(match).tap do |result|
# we need to move offset as soon
# as we match the token
@state.offset += scanner.matched_size if consume && result
end
end
......@@ -96,32 +113,50 @@ module Gitlab
section_name = sanitize_section_name(section)
if action == "start"
handle_section_start(section_name, timestamp)
handle_section_start(scanner, section_name, timestamp)
elsif action == "end"
handle_section_end(section_name, timestamp)
handle_section_end(scanner, section_name, timestamp)
else
raise 'unsupported action'
end
end
def handle_section_start(section, timestamp)
flush_current_line unless @state.current_line.empty?
def handle_section_start(scanner, section, timestamp)
# We make a new line for new section
flush_current_line
@state.open_section(section, timestamp)
# we need to consume match after handling
# the open of section, as we want the section
# marker to be refresh on incremental update
@state.offset += scanner.matched_size
end
def handle_section_end(section, timestamp)
def handle_section_end(scanner, section, timestamp)
return unless @state.section_open?(section)
flush_current_line unless @state.current_line.empty?
# We flush the content to make the end
# of section to be a new line
flush_current_line
@state.close_section(section, timestamp)
# ensure that section end is detached from the last
# line in the section
# we need to consume match before handling
# as we want the section close marker
# not to be refreshed on incremental update
@state.offset += scanner.matched_size
# this flushes an empty line with `section_duration`
flush_current_line
end
def flush_current_line(advance_offset: 0)
def flush_current_line
unless @state.current_line.empty?
@lines << @state.current_line.to_h
end
@state.set_current_line!(advance_offset: advance_offset)
@state.new_line!
end
def sanitize_section_name(section)
......
......@@ -47,12 +47,17 @@ module Gitlab
@current_segment.text << data
end
def clear!
@segments.clear
@current_segment = Segment.new(style: style)
end
def style
@current_segment.style
end
def empty?
@segments.empty? && @current_segment.empty?
@segments.empty? && @current_segment.empty? && @section_duration.nil?
end
def update_style(ansi_commands)
......
......@@ -46,9 +46,9 @@ module Gitlab
@open_sections.key?(section)
end
def set_current_line!(style: nil, advance_offset: 0)
def new_line!(style: nil)
new_line = Line.new(
offset: @offset + advance_offset,
offset: @offset,
style: style || @current_line.style,
sections: @open_sections.keys
)
......
......@@ -11,11 +11,11 @@ module Gitlab
include ::Gitlab::Config::Entry::Validatable
validations do
validates :config, array_of_strings_or_string: true
validates :config, string_or_nested_array_of_strings: true
end
def value
Array(@config)
Array(@config).flatten(1)
end
end
end
......
......@@ -11,7 +11,11 @@ module Gitlab
include ::Gitlab::Config::Entry::Validatable
validations do
validates :config, array_of_strings: true
validates :config, nested_array_of_strings: true
end
def value
config.flatten(1)
end
end
end
......
......@@ -228,6 +228,34 @@ module Gitlab
end
end
class NestedArrayOfStringsValidator < ArrayOfStringsOrStringValidator
def validate_each(record, attribute, value)
unless validate_nested_array_of_strings(value)
record.errors.add(attribute, 'should be an array containing strings and arrays of strings')
end
end
private
def validate_nested_array_of_strings(values)
values.is_a?(Array) && values.all? { |element| validate_array_of_strings_or_string(element) }
end
end
class StringOrNestedArrayOfStringsValidator < NestedArrayOfStringsValidator
def validate_each(record, attribute, value)
unless validate_string_or_nested_array_of_strings(value)
record.errors.add(attribute, 'should be a string or an array containing strings and arrays of strings')
end
end
private
def validate_string_or_nested_array_of_strings(values)
validate_string(values) || validate_nested_array_of_strings(values)
end
end
class TypeValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
type = options[:with]
......
......@@ -12,6 +12,7 @@ module GoogleApi
SCOPE = 'https://www.googleapis.com/auth/cloud-platform'
LEAST_TOKEN_LIFE_TIME = 10.minutes
CLUSTER_MASTER_AUTH_USERNAME = 'admin'
CLUSTER_IPV4_CIDR_BLOCK = '/16'
class << self
def session_key_for_token
......@@ -97,7 +98,8 @@ module GoogleApi
enabled: legacy_abac
},
ip_allocation_policy: {
use_ip_aliases: true
use_ip_aliases: true,
cluster_ipv4_cidr_block: CLUSTER_IPV4_CIDR_BLOCK
},
addons_config: enable_addons.each_with_object({}) do |addon, hash|
hash[addon] = { disabled: false }
......
......@@ -3,14 +3,15 @@ import DiffFileComponent from '~/diffs/components/diff_file.vue';
import { diffViewerModes, diffViewerErrors } from '~/ide/constants';
import { createStore } from 'ee_else_ce/mr_notes/stores';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import diffFileMockData from '../mock_data/diff_file';
import diffFileMockDataReadable from '../mock_data/diff_file';
import diffFileMockDataUnreadable from '../mock_data/diff_file_unreadable';
describe('DiffFile', () => {
let vm;
beforeEach(() => {
vm = createComponentWithStore(Vue.extend(DiffFileComponent), createStore(), {
file: JSON.parse(JSON.stringify(diffFileMockData)),
file: JSON.parse(JSON.stringify(diffFileMockDataReadable)),
canCurrentUserFork: false,
}).$mount();
});
......@@ -81,6 +82,24 @@ describe('DiffFile', () => {
});
});
it('should be collapsable for unreadable files', done => {
vm.$destroy();
vm = createComponentWithStore(Vue.extend(DiffFileComponent), createStore(), {
file: JSON.parse(JSON.stringify(diffFileMockDataUnreadable)),
canCurrentUserFork: false,
}).$mount();
vm.renderIt = false;
vm.isCollapsed = true;
vm.$nextTick(() => {
expect(vm.$el.innerText).toContain('This diff is collapsed');
expect(vm.$el.querySelectorAll('.js-click-to-expand').length).toEqual(1);
done();
});
});
it('should be collapsed for renamed files', done => {
vm.renderIt = true;
vm.isCollapsed = false;
......@@ -184,5 +203,31 @@ describe('DiffFile', () => {
.then(done)
.catch(done.fail);
});
it('does not call handleLoadCollapsedDiff if collapsed changed & file is unreadable', done => {
vm.$destroy();
vm = createComponentWithStore(Vue.extend(DiffFileComponent), createStore(), {
file: JSON.parse(JSON.stringify(diffFileMockDataUnreadable)),
canCurrentUserFork: false,
}).$mount();
spyOn(vm, 'handleLoadCollapsedDiff');
vm.file.highlighted_diff_lines = undefined;
vm.file.parallel_diff_lines = [];
vm.isCollapsed = true;
vm.$nextTick()
.then(() => {
vm.isCollapsed = false;
return vm.$nextTick();
})
.then(() => {
expect(vm.handleLoadCollapsedDiff).not.toHaveBeenCalled();
})
.then(done)
.catch(done.fail);
});
});
});
export default {
submodule: false,
submodule_link: null,
blob: {
id: '9e10516ca50788acf18c518a231914a21e5f16f7',
path: 'CHANGELOG',
name: 'CHANGELOG',
mode: '100644',
readable_text: false,
icon: 'file-text-o',
},
blob_path: 'CHANGELOG',
blob_name: 'CHANGELOG',
blob_icon: '<i aria-hidden="true" data-hidden="true" class="fa fa-file-text-o fa-fw"></i>',
file_hash: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a',
file_path: 'CHANGELOG',
new_file: false,
deleted_file: false,
renamed_file: false,
old_path: 'CHANGELOG',
new_path: 'CHANGELOG',
mode_changed: false,
a_mode: '100644',
b_mode: '100644',
text: true,
viewer: {
name: 'text',
error: null,
collapsed: false,
},
added_lines: 0,
removed_lines: 0,
diff_refs: {
base_sha: 'e63f41fe459e62e1228fcef60d7189127aeba95a',
start_sha: 'd9eaefe5a676b820c57ff18cf5b68316025f7962',
head_sha: 'c48ee0d1bf3b30453f5b32250ce03134beaa6d13',
},
content_sha: 'c48ee0d1bf3b30453f5b32250ce03134beaa6d13',
stored_externally: null,
external_storage: null,
old_path_html: 'CHANGELOG',
new_path_html: 'CHANGELOG',
edit_path: '/gitlab-org/gitlab-test/edit/spooky-stuff/CHANGELOG',
view_path: '/gitlab-org/gitlab-test/blob/spooky-stuff/CHANGELOG',
replaced_view_path: null,
collapsed: false,
renderIt: false,
too_large: false,
context_lines_path:
'/gitlab-org/gitlab-test/blob/c48ee0d1bf3b30453f5b32250ce03134beaa6d13/CHANGELOG/diff',
highlighted_diff_lines: [
{
line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_1',
type: 'new',
old_line: null,
new_line: 1,
discussions: [],
text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
rich_text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
meta_data: null,
},
{
line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_2',
type: 'new',
old_line: null,
new_line: 2,
discussions: [],
text: '+<span id="LC2" class="line" lang="plaintext"></span>\n',
rich_text: '+<span id="LC2" class="line" lang="plaintext"></span>\n',
meta_data: null,
},
{
line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_3',
type: null,
old_line: 1,
new_line: 3,
discussions: [],
text: ' <span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
rich_text: ' <span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
meta_data: null,
},
{
line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_2_4',
type: null,
old_line: 2,
new_line: 4,
discussions: [],
text: ' <span id="LC4" class="line" lang="plaintext"></span>\n',
rich_text: ' <span id="LC4" class="line" lang="plaintext"></span>\n',
meta_data: null,
},
{
line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_3_5',
type: null,
old_line: 3,
new_line: 5,
discussions: [],
text: ' <span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
rich_text: ' <span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
meta_data: null,
},
{
line_code: null,
type: 'match',
old_line: null,
new_line: null,
discussions: [],
text: '',
rich_text: '',
meta_data: {
old_pos: 3,
new_pos: 5,
},
},
],
parallel_diff_lines: [
{
left: {
type: 'empty-cell',
},
right: {
line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_1',
type: 'new',
old_line: null,
new_line: 1,
discussions: [],
text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
rich_text: '<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
meta_data: null,
},
},
{
left: {
type: 'empty-cell',
},
right: {
line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_2',
type: 'new',
old_line: null,
new_line: 2,
discussions: [],
text: '+<span id="LC2" class="line" lang="plaintext"></span>\n',
rich_text: '<span id="LC2" class="line" lang="plaintext"></span>\n',
meta_data: null,
},
},
{
left: {
line_Code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_3',
type: null,
old_line: 1,
new_line: 3,
discussions: [],
text: ' <span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
rich_text: '<span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
meta_data: null,
},
right: {
line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_3',
type: null,
old_line: 1,
new_line: 3,
discussions: [],
text: ' <span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
rich_text: '<span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
meta_data: null,
},
},
{
left: {
line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_2_4',
type: null,
old_line: 2,
new_line: 4,
discussions: [],
text: ' <span id="LC4" class="line" lang="plaintext"></span>\n',
rich_text: '<span id="LC4" class="line" lang="plaintext"></span>\n',
meta_data: null,
},
right: {
line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_2_4',
type: null,
old_line: 2,
new_line: 4,
discussions: [],
text: ' <span id="LC4" class="line" lang="plaintext"></span>\n',
rich_text: '<span id="LC4" class="line" lang="plaintext"></span>\n',
meta_data: null,
},
},
{
left: {
line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_3_5',
type: null,
old_line: 3,
new_line: 5,
discussions: [],
text: ' <span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
rich_text: '<span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
meta_data: null,
},
right: {
line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_3_5',
type: null,
old_line: 3,
new_line: 5,
discussions: [],
text: ' <span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
rich_text: '<span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
meta_data: null,
},
},
{
left: {
line_code: null,
type: 'match',
old_line: null,
new_line: null,
discussions: [],
text: '',
rich_text: '',
meta_data: {
old_pos: 3,
new_pos: 5,
},
},
right: {
line_code: null,
type: 'match',
old_line: null,
new_line: null,
discussions: [],
text: '',
rich_text: '',
meta_data: {
old_pos: 3,
new_pos: 5,
},
},
},
],
discussions: [],
renderingLines: false,
};
......@@ -12,13 +12,28 @@ describe Gitlab::Ci::Ansi2json do
])
end
it 'adds new line in a separate element' do
context 'new lines' do
it 'adds new line when encountering \n' do
expect(convert_json("Hello\nworld")).to eq([
{ offset: 0, content: [{ text: 'Hello' }] },
{ offset: 6, content: [{ text: 'world' }] }
])
end
it 'adds new line when encountering \r\n' do
expect(convert_json("Hello\r\nworld")).to eq([
{ offset: 0, content: [{ text: 'Hello' }] },
{ offset: 7, content: [{ text: 'world' }] }
])
end
it 'replace the current line when encountering \r' do
expect(convert_json("Hello\rworld")).to eq([
{ offset: 0, content: [{ text: 'world' }] }
])
end
end
it 'recognizes color changing ANSI sequences' do
expect(convert_json("\e[31mHello\e[0m")).to eq([
{ offset: 0, content: [{ text: 'Hello', style: 'term-fg-red' }] }
......@@ -113,10 +128,6 @@ describe Gitlab::Ci::Ansi2json do
content: [],
section_duration: '01:03',
section: 'prepare-script'
},
{
offset: 63,
content: []
}
])
end
......@@ -134,10 +145,6 @@ describe Gitlab::Ci::Ansi2json do
content: [],
section: 'prepare-script',
section_duration: '01:03'
},
{
offset: 56,
content: []
}
])
end
......@@ -157,7 +164,7 @@ describe Gitlab::Ci::Ansi2json do
section_duration: '01:03'
},
{
offset: 49,
offset: 91,
content: [{ text: 'world' }]
}
])
......@@ -198,7 +205,7 @@ describe Gitlab::Ci::Ansi2json do
expect(convert_json("#{section_start}hello")).to eq([
{
offset: 0,
content: [{ text: "#{section_start.gsub("\033[0K", '')}hello" }]
content: [{ text: 'hello' }]
}
])
end
......@@ -211,7 +218,7 @@ describe Gitlab::Ci::Ansi2json do
expect(convert_json("#{section_start}hello")).to eq([
{
offset: 0,
content: [{ text: "#{section_start.gsub("\033[0K", '').gsub('<', '&lt;')}hello" }]
content: [{ text: 'hello' }]
}
])
end
......@@ -231,10 +238,6 @@ describe Gitlab::Ci::Ansi2json do
content: [],
section: 'prepare-script',
section_duration: '01:03'
},
{
offset: 95,
content: []
}
])
end
......@@ -274,7 +277,7 @@ describe Gitlab::Ci::Ansi2json do
section_duration: '00:02'
},
{
offset: 106,
offset: 155,
content: [{ text: 'baz' }],
section: 'prepare-script'
},
......@@ -285,7 +288,7 @@ describe Gitlab::Ci::Ansi2json do
section_duration: '01:03'
},
{
offset: 158,
offset: 200,
content: [{ text: 'world' }]
}
])
......@@ -318,14 +321,10 @@ describe Gitlab::Ci::Ansi2json do
section_duration: '00:02'
},
{
offset: 115,
offset: 164,
content: [],
section: 'prepare-script',
section_duration: '01:03'
},
{
offset: 164,
content: []
}
])
end
......@@ -380,7 +379,7 @@ describe Gitlab::Ci::Ansi2json do
]
end
it 'returns the full line' do
it 'returns the line since last partially processed line' do
expect(pass2.lines).to eq(lines)
expect(pass2.append).to be_truthy
end
......@@ -399,7 +398,7 @@ describe Gitlab::Ci::Ansi2json do
]
end
it 'returns the full line' do
it 'returns the line since last partially processed line' do
expect(pass2.lines).to eq(lines)
expect(pass2.append).to be_falsey
end
......@@ -416,7 +415,7 @@ describe Gitlab::Ci::Ansi2json do
]
end
it 'returns the full line' do
it 'returns a blank line and the next line' do
expect(pass2.lines).to eq(lines)
expect(pass2.append).to be_falsey
end
......@@ -502,10 +501,6 @@ describe Gitlab::Ci::Ansi2json do
content: [],
section: 'prepare-script',
section_duration: '01:03'
},
{
offset: 77,
content: []
}
]
end
......
......@@ -5,7 +5,7 @@ require 'spec_helper'
describe Gitlab::Ci::Config::Entry::Commands do
let(:entry) { described_class.new(config) }
context 'when entry config value is an array' do
context 'when entry config value is an array of strings' do
let(:config) { %w(ls pwd) }
describe '#value' do
......@@ -37,13 +37,74 @@ describe Gitlab::Ci::Config::Entry::Commands do
end
end
context 'when entry value is not valid' do
context 'when entry config value is array of arrays of strings' do
let(:config) { [['ls'], ['pwd', 'echo 1']] }
describe '#value' do
it 'returns array of strings' do
expect(entry.value).to eq ['ls', 'pwd', 'echo 1']
end
end
describe '#errors' do
it 'does not append errors' do
expect(entry.errors).to be_empty
end
end
describe '#valid?' do
it 'is valid' do
expect(entry).to be_valid
end
end
end
context 'when entry config value is array of strings and arrays of strings' do
let(:config) { ['ls', ['pwd', 'echo 1']] }
describe '#value' do
it 'returns array of strings' do
expect(entry.value).to eq ['ls', 'pwd', 'echo 1']
end
end
describe '#errors' do
it 'does not append errors' do
expect(entry.errors).to be_empty
end
end
describe '#valid?' do
it 'is valid' do
expect(entry).to be_valid
end
end
end
context 'when entry value is integer' do
let(:config) { 1 }
describe '#errors' do
it 'saves errors' do
expect(entry.errors)
.to include 'commands config should be an array of strings or a string'
.to include 'commands config should be a string or an array containing strings and arrays of strings'
end
end
end
context 'when entry value is multi-level nested array' do
let(:config) { [['ls', ['echo 1']], 'pwd'] }
describe '#errors' do
it 'saves errors' do
expect(entry.errors)
.to include 'commands config should be a string or an array containing strings and arrays of strings'
end
end
describe '#valid?' do
it 'is not valid' do
expect(entry).not_to be_valid
end
end
end
......
......@@ -298,7 +298,7 @@ describe Gitlab::Ci::Config::Entry::Root do
describe '#errors' do
it 'reports errors from child nodes' do
expect(root.errors)
.to include 'before_script config should be an array of strings'
.to include 'before_script config should be an array containing strings and arrays of strings'
end
end
end
......
......@@ -6,7 +6,7 @@ describe Gitlab::Ci::Config::Entry::Script do
let(:entry) { described_class.new(config) }
describe 'validations' do
context 'when entry config value is correct' do
context 'when entry config value is array of strings' do
let(:config) { %w(ls pwd) }
describe '#value' do
......@@ -28,13 +28,74 @@ describe Gitlab::Ci::Config::Entry::Script do
end
end
context 'when entry value is not correct' do
context 'when entry config value is array of arrays of strings' do
let(:config) { [['ls'], ['pwd', 'echo 1']] }
describe '#value' do
it 'returns array of strings' do
expect(entry.value).to eq ['ls', 'pwd', 'echo 1']
end
end
describe '#errors' do
it 'does not append errors' do
expect(entry.errors).to be_empty
end
end
describe '#valid?' do
it 'is valid' do
expect(entry).to be_valid
end
end
end
context 'when entry config value is array containing strings and arrays of strings' do
let(:config) { ['ls', ['pwd', 'echo 1']] }
describe '#value' do
it 'returns array of strings' do
expect(entry.value).to eq ['ls', 'pwd', 'echo 1']
end
end
describe '#errors' do
it 'does not append errors' do
expect(entry.errors).to be_empty
end
end
describe '#valid?' do
it 'is valid' do
expect(entry).to be_valid
end
end
end
context 'when entry value is string' do
let(:config) { 'ls' }
describe '#errors' do
it 'saves errors' do
expect(entry.errors)
.to include 'script config should be an array of strings'
.to include 'script config should be an array containing strings and arrays of strings'
end
end
describe '#valid?' do
it 'is not valid' do
expect(entry).not_to be_valid
end
end
end
context 'when entry value is multi-level nested array' do
let(:config) { [['ls', ['echo 1']], 'pwd'] }
describe '#errors' do
it 'saves errors' do
expect(entry.errors)
.to include 'script config should be an array containing strings and arrays of strings'
end
end
......
......@@ -94,7 +94,7 @@ describe Gitlab::Ci::Pipeline::Chain::Validate::Config do
it 'appends configuration validation errors to pipeline errors' do
expect(pipeline.errors.to_a)
.to include "jobs:rspec:before_script config should be an array of strings"
.to include "jobs:rspec:before_script config should be an array containing strings and arrays of strings"
end
it 'breaks the chain' do
......
......@@ -330,7 +330,7 @@ module Gitlab
}
end
it "return commands with scripts concencaced" do
it "return commands with scripts concatenated" do
expect(subject[:options][:before_script]).to eq(["global script"])
end
end
......@@ -343,7 +343,7 @@ module Gitlab
}
end
it "return commands with scripts concencaced" do
it "return commands with scripts concatenated" do
expect(subject[:options][:before_script]).to eq(["global script"])
end
end
......@@ -356,24 +356,51 @@ module Gitlab
}
end
it "return commands with scripts concencaced" do
it "return commands with scripts concatenated" do
expect(subject[:options][:before_script]).to eq(["local script"])
end
end
context 'when script is array of arrays of strings' do
let(:config) do
{
before_script: [["global script", "echo 1"], ["ls"], "pwd"],
test: { script: ["script"] }
}
end
it "return commands with scripts concatenated" do
expect(subject[:options][:before_script]).to eq(["global script", "echo 1", "ls", "pwd"])
end
end
end
describe "script" do
context 'when script is array of strings' do
let(:config) do
{
test: { script: ["script"] }
}
end
it "return commands with scripts concencaced" do
it "return commands with scripts concatenated" do
expect(subject[:options][:script]).to eq(["script"])
end
end
context 'when script is array of arrays of strings' do
let(:config) do
{
test: { script: [["script"], ["echo 1"], "ls"] }
}
end
it "return commands with scripts concatenated" do
expect(subject[:options][:script]).to eq(["script", "echo 1", "ls"])
end
end
end
describe "after_script" do
context "in global context" do
let(:config) do
......@@ -413,6 +440,19 @@ module Gitlab
expect(subject[:options][:after_script]).to eq(["local after_script"])
end
end
context 'when script is array of arrays of strings' do
let(:config) do
{
after_script: [["global script", "echo 1"], ["ls"], "pwd"],
test: { script: ["script"] }
}
end
it "return after_script in options" do
expect(subject[:options][:after_script]).to eq(["global script", "echo 1", "ls", "pwd"])
end
end
end
end
......@@ -1536,28 +1576,42 @@ module Gitlab
config = YAML.dump({ before_script: "bundle update", rspec: { script: "test" } })
expect do
Gitlab::Ci::YamlProcessor.new(config)
end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "before_script config should be an array of strings")
end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "before_script config should be an array containing strings and arrays of strings")
end
it "returns errors if job before_script parameter is not an array of strings" do
config = YAML.dump({ rspec: { script: "test", before_script: [10, "test"] } })
expect do
Gitlab::Ci::YamlProcessor.new(config)
end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:before_script config should be an array of strings")
end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:before_script config should be an array containing strings and arrays of strings")
end
it "returns errors if job before_script parameter is multi-level nested array of strings" do
config = YAML.dump({ rspec: { script: "test", before_script: [["ls", ["pwd"]], "test"] } })
expect do
Gitlab::Ci::YamlProcessor.new(config)
end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:before_script config should be an array containing strings and arrays of strings")
end
it "returns errors if after_script parameter is invalid" do
config = YAML.dump({ after_script: "bundle update", rspec: { script: "test" } })
expect do
Gitlab::Ci::YamlProcessor.new(config)
end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "after_script config should be an array of strings")
end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "after_script config should be an array containing strings and arrays of strings")
end
it "returns errors if job after_script parameter is not an array of strings" do
config = YAML.dump({ rspec: { script: "test", after_script: [10, "test"] } })
expect do
Gitlab::Ci::YamlProcessor.new(config)
end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:after_script config should be an array of strings")
end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:after_script config should be an array containing strings and arrays of strings")
end
it "returns errors if job after_script parameter is multi-level nested array of strings" do
config = YAML.dump({ rspec: { script: "test", after_script: [["ls", ["pwd"]], "test"] } })
expect do
Gitlab::Ci::YamlProcessor.new(config)
end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec:after_script config should be an array containing strings and arrays of strings")
end
it "returns errors if image parameter is invalid" do
......
......@@ -104,7 +104,8 @@ describe GoogleApi::CloudPlatform::Client do
enabled: legacy_abac
},
ip_allocation_policy: {
use_ip_aliases: true
use_ip_aliases: true,
cluster_ipv4_cidr_block: '/16'
},
addons_config: addons_config
}
......
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