diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-11-19 11:27:35 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-11-19 11:27:35 +0300 |
commit | 7e9c479f7de77702622631cff2628a9c8dcbc627 (patch) | |
tree | c8f718a08e110ad7e1894510980d2155a6549197 /lib/gitlab/ci | |
parent | e852b0ae16db4052c1c567d9efa4facc81146e88 (diff) |
Add latest changes from gitlab-org/gitlab@13-6-stable-eev13.6.0-rc42
Diffstat (limited to 'lib/gitlab/ci')
34 files changed, 461 insertions, 151 deletions
diff --git a/lib/gitlab/ci/build/rules/rule/clause/changes.rb b/lib/gitlab/ci/build/rules/rule/clause/changes.rb index 728a66ca87f..cbecce57163 100644 --- a/lib/gitlab/ci/build/rules/rule/clause/changes.rb +++ b/lib/gitlab/ci/build/rules/rule/clause/changes.rb @@ -11,12 +11,22 @@ module Gitlab def satisfied_by?(pipeline, context) return true if pipeline.modified_paths.nil? + expanded_globs = expand_globs(pipeline, context) pipeline.modified_paths.any? do |path| - @globs.any? do |glob| + expanded_globs.any? do |glob| File.fnmatch?(glob, path, File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_EXTGLOB) end end end + + def expand_globs(pipeline, context) + return @globs unless ::Feature.enabled?(:ci_variable_expansion_in_rules_changes, pipeline.project, default_enabled: true) + return @globs unless context + + @globs.map do |glob| + ExpandVariables.expand_existing(glob, context.variables) + end + end end end end diff --git a/lib/gitlab/ci/charts.rb b/lib/gitlab/ci/charts.rb index 3fbfdffe277..25fb9c0ca97 100644 --- a/lib/gitlab/ci/charts.rb +++ b/lib/gitlab/ci/charts.rb @@ -3,38 +3,8 @@ module Gitlab module Ci module Charts - module DailyInterval - # rubocop: disable CodeReuse/ActiveRecord - def grouped_count(query) - query - .group("DATE(#{::Ci::Pipeline.table_name}.created_at)") - .count(:created_at) - .transform_keys { |date| date.strftime(@format) } # rubocop:disable Gitlab/ModuleWithInstanceVariables - end - # rubocop: enable CodeReuse/ActiveRecord - - def interval_step - @interval_step ||= 1.day - end - end - - module MonthlyInterval - # rubocop: disable CodeReuse/ActiveRecord - def grouped_count(query) - query - .group("to_char(#{::Ci::Pipeline.table_name}.created_at, '01 Month YYYY')") - .count(:created_at) - .transform_keys(&:squish) - end - # rubocop: enable CodeReuse/ActiveRecord - - def interval_step - @interval_step ||= 1.month - end - end - class Chart - attr_reader :labels, :total, :success, :project, :pipeline_times + attr_reader :from, :to, :labels, :total, :success, :project, :pipeline_times def initialize(project) @labels = [] @@ -46,48 +16,59 @@ module Gitlab collect end + private + + attr_reader :interval + # rubocop: disable CodeReuse/ActiveRecord def collect query = project.all_pipelines - .where("? > #{::Ci::Pipeline.table_name}.created_at AND #{::Ci::Pipeline.table_name}.created_at > ?", @to, @from) # rubocop:disable GitlabSecurity/SqlInjection + .where(::Ci::Pipeline.arel_table['created_at'].gteq(@from)) + .where(::Ci::Pipeline.arel_table['created_at'].lteq(@to)) totals_count = grouped_count(query) success_count = grouped_count(query.success) current = @from - while current < @to - label = current.strftime(@format) - - @labels << label - @total << (totals_count[label] || 0) - @success << (success_count[label] || 0) + while current <= @to + @labels << current.strftime(@format) + @total << (totals_count[current] || 0) + @success << (success_count[current] || 0) current += interval_step end end # rubocop: enable CodeReuse/ActiveRecord + + # rubocop: disable CodeReuse/ActiveRecord + def grouped_count(query) + query + .group("date_trunc('#{interval}', #{::Ci::Pipeline.table_name}.created_at)") + .count(:created_at) + end + # rubocop: enable CodeReuse/ActiveRecord + + def interval_step + @interval_step ||= 1.public_send(interval) # rubocop: disable GitlabSecurity/PublicSend + end end class YearChart < Chart - include MonthlyInterval - attr_reader :to, :from - def initialize(*) @to = Date.today.end_of_month.end_of_day - @from = @to.years_ago(1).beginning_of_month.beginning_of_day - @format = '%d %B %Y' + @from = (@to - 1.year).beginning_of_month.beginning_of_day + @interval = :month + @format = '%B %Y' super end end class MonthChart < Chart - include DailyInterval - attr_reader :to, :from - def initialize(*) @to = Date.today.end_of_day - @from = 1.month.ago.beginning_of_day + @from = (@to - 1.month).beginning_of_day + @interval = :day @format = '%d %B' super @@ -95,12 +76,10 @@ module Gitlab end class WeekChart < Chart - include DailyInterval - attr_reader :to, :from - def initialize(*) @to = Date.today.end_of_day - @from = 1.week.ago.beginning_of_day + @from = (@to - 1.week).beginning_of_day + @interval = :day @format = '%d %B' super diff --git a/lib/gitlab/ci/config/entry/bridge.rb b/lib/gitlab/ci/config/entry/bridge.rb index 1740032e5c7..70fcc1d586a 100644 --- a/lib/gitlab/ci/config/entry/bridge.rb +++ b/lib/gitlab/ci/config/entry/bridge.rb @@ -18,7 +18,6 @@ module Gitlab validates :config, allowed_keys: ALLOWED_KEYS + PROCESSABLE_ALLOWED_KEYS with_options allow_nil: true do - validates :allow_failure, boolean: true validates :when, inclusion: { in: ALLOWED_WHEN, message: "should be one of: #{ALLOWED_WHEN.join(', ')}" @@ -48,7 +47,7 @@ module Gitlab inherit: false, metadata: { allowed_needs: %i[job bridge] } - attributes :when, :allow_failure + attributes :when def self.matching?(name, config) !name.to_s.start_with?('.') && @@ -60,14 +59,6 @@ module Gitlab true end - def manual_action? - self.when == 'manual' - end - - def ignored? - allow_failure.nil? ? manual_action? : allow_failure - end - def value super.merge( trigger: (trigger_value if trigger_defined?), diff --git a/lib/gitlab/ci/config/entry/job.rb b/lib/gitlab/ci/config/entry/job.rb index ecc2c5cb729..1ce7060df22 100644 --- a/lib/gitlab/ci/config/entry/job.rb +++ b/lib/gitlab/ci/config/entry/job.rb @@ -24,7 +24,6 @@ module Gitlab validates :script, presence: true with_options allow_nil: true do - validates :allow_failure, boolean: true validates :when, inclusion: { in: ALLOWED_WHEN, message: "should be one of: #{ALLOWED_WHEN.join(', ')}" @@ -118,7 +117,7 @@ module Gitlab description: 'Parallel configuration for this job.', inherit: false - attributes :script, :tags, :allow_failure, :when, :dependencies, + attributes :script, :tags, :when, :dependencies, :needs, :retry, :parallel, :start_in, :interruptible, :timeout, :resource_group, :release @@ -141,18 +140,10 @@ module Gitlab end end - def manual_action? - self.when == 'manual' - end - def delayed? self.when == 'delayed' end - def ignored? - allow_failure.nil? ? manual_action? : allow_failure - end - def value super.merge( before_script: before_script_value, diff --git a/lib/gitlab/ci/config/entry/processable.rb b/lib/gitlab/ci/config/entry/processable.rb index f10c509d0cc..c0315e5f901 100644 --- a/lib/gitlab/ci/config/entry/processable.rb +++ b/lib/gitlab/ci/config/entry/processable.rb @@ -32,6 +32,7 @@ module Gitlab with_options allow_nil: true do validates :extends, array_of_strings_or_string: true validates :rules, array_of_hashes: true + validates :allow_failure, boolean: true end end @@ -64,7 +65,7 @@ module Gitlab inherit: false, default: {} - attributes :extends, :rules + attributes :extends, :rules, :allow_failure end def compose!(deps = nil) @@ -136,6 +137,14 @@ module Gitlab root_variables.merge(variables_value.to_h) end + + def manual_action? + self.when == 'manual' + end + + def ignored? + allow_failure.nil? ? manual_action? : allow_failure + end end end end diff --git a/lib/gitlab/ci/config/entry/product/variables.rb b/lib/gitlab/ci/config/entry/product/variables.rb index 2481989060e..aa34cfb3acc 100644 --- a/lib/gitlab/ci/config/entry/product/variables.rb +++ b/lib/gitlab/ci/config/entry/product/variables.rb @@ -14,7 +14,7 @@ module Gitlab validations do validates :config, variables: { array_values: true } validates :config, length: { - minimum: :minimum, + minimum: 1, too_short: 'requires at least %{count} items' } end @@ -28,10 +28,6 @@ module Gitlab .map { |key, value| [key.to_s, Array(value).map(&:to_s)] } .to_h end - - def minimum - ::Gitlab::Ci::Features.one_dimensional_matrix_enabled? ? 1 : 2 - end end end end diff --git a/lib/gitlab/ci/config/external/mapper.rb b/lib/gitlab/ci/config/external/mapper.rb index 97ae6c4ceba..90692eafc3f 100644 --- a/lib/gitlab/ci/config/external/mapper.rb +++ b/lib/gitlab/ci/config/external/mapper.rb @@ -33,6 +33,7 @@ module Gitlab locations .compact .map(&method(:normalize_location)) + .flat_map(&method(:expand_project_files)) .each(&method(:verify_duplicates!)) .map(&method(:select_first_matching)) end @@ -52,6 +53,15 @@ module Gitlab end end + def expand_project_files(location) + return location unless ::Feature.enabled?(:ci_include_multiple_files_from_project, context.project, default_enabled: true) + return location unless location[:project] + + Array.wrap(location[:file]).map do |file| + location.merge(file: file) + end + end + def normalize_location_string(location) if ::Gitlab::UrlSanitizer.valid?(location) { remote: location } diff --git a/lib/gitlab/ci/features.rb b/lib/gitlab/ci/features.rb index 1b58e3ec71a..661189eea50 100644 --- a/lib/gitlab/ci/features.rb +++ b/lib/gitlab/ci/features.rb @@ -32,16 +32,12 @@ module Gitlab end # NOTE: The feature flag `disallow_to_create_merge_request_pipelines_in_target_project` - # is a safe switch to disable the feature for a parituclar project when something went wrong, + # is a safe switch to disable the feature for a particular project when something went wrong, # therefore it's not supposed to be enabled by default. def self.disallow_to_create_merge_request_pipelines_in_target_project?(target_project) ::Feature.enabled?(:ci_disallow_to_create_merge_request_pipelines_in_target_project, target_project) end - def self.lint_creates_pipeline_with_dry_run?(project) - ::Feature.enabled?(:ci_lint_creates_pipeline_with_dry_run, project, default_enabled: true) - end - def self.project_transactionless_destroy?(project) Feature.enabled?(:project_transactionless_destroy, project, default_enabled: false) end @@ -59,13 +55,21 @@ module Gitlab ::Feature.enabled?(:ci_trace_log_invalid_chunks, project, type: :ops, default_enabled: false) end - def self.one_dimensional_matrix_enabled? - ::Feature.enabled?(:one_dimensional_matrix, default_enabled: true) - end - def self.manual_bridges_enabled?(project) ::Feature.enabled?(:ci_manual_bridges, project, default_enabled: true) end + + def self.auto_rollback_available?(project) + ::Feature.enabled?(:cd_auto_rollback, project) && project&.feature_available?(:auto_rollback) + end + + def self.seed_block_run_before_workflow_rules_enabled?(project) + ::Feature.enabled?(:ci_seed_block_run_before_workflow_rules, project, default_enabled: true) + end + + def self.ci_pipeline_editor_page_enabled?(project) + ::Feature.enabled?(:ci_pipeline_editor_page, project, default_enabled: false) + end end end end diff --git a/lib/gitlab/ci/jwt.rb b/lib/gitlab/ci/jwt.rb index 491facd0a43..a8943eadf4f 100644 --- a/lib/gitlab/ci/jwt.rb +++ b/lib/gitlab/ci/jwt.rb @@ -6,6 +6,8 @@ module Gitlab NOT_BEFORE_TIME = 5 DEFAULT_EXPIRE_TIME = 60 * 5 + NoSigningKeyError = Class.new(StandardError) + def self.for_build(build) self.new(build, ttl: build.metadata_timeout).encoded end @@ -27,7 +29,7 @@ module Gitlab private - attr_reader :build, :ttl, :key_data + attr_reader :build, :ttl def reserved_claims now = Time.now.to_i @@ -60,7 +62,17 @@ module Gitlab end def key - @key ||= OpenSSL::PKey::RSA.new(Rails.application.secrets.openid_connect_signing_key) + @key ||= begin + key_data = if Feature.enabled?(:ci_jwt_signing_key, build.project, default_enabled: true) + Gitlab::CurrentSettings.ci_jwt_signing_key + else + Rails.application.secrets.openid_connect_signing_key + end + + raise NoSigningKeyError unless key_data + + OpenSSL::PKey::RSA.new(key_data) + end end def public_key diff --git a/lib/gitlab/ci/lint.rb b/lib/gitlab/ci/lint.rb index 44f2ac23ce3..fb795152abe 100644 --- a/lib/gitlab/ci/lint.rb +++ b/lib/gitlab/ci/lint.rb @@ -24,7 +24,7 @@ module Gitlab end def validate(content, dry_run: false) - if dry_run && Gitlab::Ci::Features.lint_creates_pipeline_with_dry_run?(@project) + if dry_run simulate_pipeline_creation(content) else static_validation(content) diff --git a/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb b/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb index 468f3bc4689..a864c843dd8 100644 --- a/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb +++ b/lib/gitlab/ci/pipeline/chain/cancel_pending_pipelines.rb @@ -25,7 +25,7 @@ module Gitlab # rubocop: disable CodeReuse/ActiveRecord def auto_cancelable_pipelines - project.ci_pipelines + pipelines .where(ref: pipeline.ref) .where.not(id: pipeline.same_family_pipeline_ids) .where.not(sha: project.commit(pipeline.ref).try(:id)) @@ -33,6 +33,14 @@ module Gitlab .with_only_interruptible_builds end # rubocop: enable CodeReuse/ActiveRecord + + def pipelines + if ::Feature.enabled?(:ci_auto_cancel_all_pipelines, project, default_enabled: false) + project.all_pipelines.ci_and_parent_sources + else + project.ci_pipelines + end + end end end end diff --git a/lib/gitlab/ci/pipeline/chain/seed.rb b/lib/gitlab/ci/pipeline/chain/seed.rb index e10a0bc3718..ba86b08d209 100644 --- a/lib/gitlab/ci/pipeline/chain/seed.rb +++ b/lib/gitlab/ci/pipeline/chain/seed.rb @@ -19,10 +19,12 @@ module Gitlab # Build to prevent erroring out on ambiguous refs. pipeline.protected = @command.protected_ref? - ## - # Populate pipeline with block argument of CreatePipelineService#execute. - # - @command.seeds_block&.call(pipeline) + unless ::Gitlab::Ci::Features.seed_block_run_before_workflow_rules_enabled?(project) + ## + # Populate pipeline with block argument of CreatePipelineService#execute. + # + @command.seeds_block&.call(pipeline) + end ## # Gather all runtime build/stage errors diff --git a/lib/gitlab/ci/pipeline/chain/seed_block.rb b/lib/gitlab/ci/pipeline/chain/seed_block.rb new file mode 100644 index 00000000000..f8e62949bea --- /dev/null +++ b/lib/gitlab/ci/pipeline/chain/seed_block.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +module Gitlab + module Ci + module Pipeline + module Chain + class SeedBlock < Chain::Base + include Chain::Helpers + include Gitlab::Utils::StrongMemoize + + def perform! + return unless ::Gitlab::Ci::Features.seed_block_run_before_workflow_rules_enabled?(project) + + ## + # Populate pipeline with block argument of CreatePipelineService#execute. + # + @command.seeds_block&.call(pipeline) + + raise "Pipeline cannot be persisted by `seeds_block`" if pipeline.persisted? + end + + def break? + return false unless ::Gitlab::Ci::Features.seed_block_run_before_workflow_rules_enabled?(project) + + pipeline.errors.any? + end + end + end + end + end +end diff --git a/lib/gitlab/ci/pipeline/seed/environment.rb b/lib/gitlab/ci/pipeline/seed/environment.rb index 42e8c365824..b20dc383419 100644 --- a/lib/gitlab/ci/pipeline/seed/environment.rb +++ b/lib/gitlab/ci/pipeline/seed/environment.rb @@ -12,12 +12,23 @@ module Gitlab end def to_resource - job.project.environments - .safe_find_or_create_by(name: expanded_environment_name) + environments.safe_find_or_create_by(name: expanded_environment_name) do |environment| + environment.auto_stop_in = auto_stop_in + end end private + def environments + job.project.environments + end + + def auto_stop_in + if Feature.enabled?(:environment_auto_stop_start_on_create) + job.environment_auto_stop_in + end + end + def expanded_environment_name job.expanded_environment_name end diff --git a/lib/gitlab/ci/reports/test_case.rb b/lib/gitlab/ci/reports/test_case.rb index 8c70dbb6931..09121191047 100644 --- a/lib/gitlab/ci/reports/test_case.rb +++ b/lib/gitlab/ci/reports/test_case.rb @@ -10,7 +10,7 @@ module Gitlab STATUS_ERROR = 'error' STATUS_TYPES = [STATUS_ERROR, STATUS_FAILED, STATUS_SUCCESS, STATUS_SKIPPED].freeze - attr_reader :suite_name, :name, :classname, :execution_time, :status, :file, :system_output, :stack_trace, :key, :attachment, :job + attr_reader :suite_name, :name, :classname, :execution_time, :status, :file, :system_output, :stack_trace, :key, :attachment, :job, :recent_failures def initialize(params) @suite_name = params.fetch(:suite_name) @@ -24,9 +24,15 @@ module Gitlab @attachment = params.fetch(:attachment, nil) @job = params.fetch(:job, nil) + @recent_failures = nil + @key = hash_key("#{suite_name}_#{classname}_#{name}") end + def set_recent_failures(count, base_branch) + @recent_failures = { count: count, base_branch: base_branch } + end + def has_attachment? attachment.present? end diff --git a/lib/gitlab/ci/reports/test_failure_history.rb b/lib/gitlab/ci/reports/test_failure_history.rb new file mode 100644 index 00000000000..beceac5423a --- /dev/null +++ b/lib/gitlab/ci/reports/test_failure_history.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module Gitlab + module Ci + module Reports + class TestFailureHistory + include Gitlab::Utils::StrongMemoize + + def initialize(failed_test_cases, project) + @failed_test_cases = build_map(failed_test_cases) + @project = project + end + + def load! + return unless Feature.enabled?(:test_failure_history, project) + + recent_failures_count.each do |key_hash, count| + failed_test_cases[key_hash].set_recent_failures(count, project.default_branch_or_master) + end + end + + private + + attr_reader :report, :project, :failed_test_cases + + def recent_failures_count + ::Ci::TestCaseFailure.recent_failures_count( + project: project, + test_case_keys: failed_test_cases.keys + ) + end + + def build_map(test_cases) + {}.tap do |hash| + test_cases.each do |test_case| + hash[test_case.key] = test_case + end + end + end + end + end + end +end diff --git a/lib/gitlab/ci/reports/test_suite_comparer.rb b/lib/gitlab/ci/reports/test_suite_comparer.rb index a58de43e55e..239fc3b15e7 100644 --- a/lib/gitlab/ci/reports/test_suite_comparer.rb +++ b/lib/gitlab/ci/reports/test_suite_comparer.rb @@ -6,6 +6,9 @@ module Gitlab class TestSuiteComparer include Gitlab::Utils::StrongMemoize + DEFAULT_MAX_TESTS = 100 + DEFAULT_MIN_TESTS = 10 + attr_reader :name, :base_suite, :head_suite def initialize(name, base_suite, head_suite) @@ -81,6 +84,29 @@ module Gitlab def error_count new_errors.count + existing_errors.count end + + # This is used to limit the presented test cases but does not affect + # total count of tests in the summary + def limited_tests + strong_memoize(:limited_tests) do + # rubocop: disable CodeReuse/ActiveRecord + OpenStruct.new( + new_failures: new_failures.take(max_tests), + existing_failures: existing_failures.take(max_tests(new_failures)), + resolved_failures: resolved_failures.take(max_tests(new_failures, existing_failures)), + new_errors: new_errors.take(max_tests), + existing_errors: existing_errors.take(max_tests(new_errors)), + resolved_errors: resolved_errors.take(max_tests(new_errors, existing_errors)) + ) + # rubocop: enable CodeReuse/ActiveRecord + end + end + + private + + def max_tests(*used) + [DEFAULT_MAX_TESTS - used.map(&:count).sum, DEFAULT_MIN_TESTS].max + end end end end diff --git a/lib/gitlab/ci/runner_instructions.rb b/lib/gitlab/ci/runner_instructions.rb index 2171637687f..dd0bfa768a8 100644 --- a/lib/gitlab/ci/runner_instructions.rb +++ b/lib/gitlab/ci/runner_instructions.rb @@ -106,7 +106,7 @@ module Gitlab end def get_file(path) - File.read(path) + File.read(Rails.root.join(path).to_s) end def registration_token diff --git a/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml b/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml index 82b2f5c035e..453803a6f7e 100644 --- a/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/AWS/Deploy-ECS.gitlab-ci.yml @@ -4,6 +4,7 @@ stages: - review - deploy - production + - cleanup variables: AUTO_DEVOPS_PLATFORM_TARGET: ECS diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml index cba13f374f4..a13f2046291 100644 --- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml @@ -160,9 +160,10 @@ include: - template: Jobs/Build.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml - template: Jobs/Test.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Test.gitlab-ci.yml - template: Jobs/Code-Quality.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml - - template: Jobs/Code-Intelligence.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Code-Intelligence.gitlab-ci.yml + - template: Jobs/Code-Intelligence.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Code-Intelligence.gitlab-ci.yml - template: Jobs/Deploy.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml - - template: Jobs/Deploy/ECS.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml + - template: Jobs/Deploy/ECS.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml + - template: Jobs/Deploy/EC2.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Deploy/EC2.gitlab-ci.yml - template: Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/DAST-Default-Branch-Deploy.gitlab-ci.yml - template: Jobs/Browser-Performance-Testing.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/Browser-Performance-Testing.gitlab-ci.yml - template: Security/DAST.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/DAST.gitlab-ci.yml diff --git a/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml index 0c3598a61a7..1c25d9d583b 100644 --- a/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Jobs/Build.gitlab-ci.yml @@ -16,4 +16,14 @@ build: fi - /build/build.sh rules: + - if: '$AUTO_DEVOPS_PLATFORM_TARGET == "EC2"' + when: never - if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH' + +build_artifact: + stage: build + script: + - printf "To build your project, please create a build_artifact job into your .gitlab-ci.yml file.\nMore information at https://docs.gitlab.com/ee/ci/cloud_deployment\n" + - exit 1 + rules: + - if: '$AUTO_DEVOPS_PLATFORM_TARGET == "EC2"' diff --git a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml index ec33020205b..fe23641802b 100644 --- a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml @@ -7,7 +7,7 @@ code_quality: variables: DOCKER_DRIVER: overlay2 DOCKER_TLS_CERTDIR: "" - CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.85.10-gitlab.1" + CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.85.18" needs: [] script: - export SOURCE_CODE=$PWD @@ -34,6 +34,7 @@ code_quality: CODECLIMATE_DEBUG \ CODECLIMATE_DEV \ REPORT_STDOUT \ + REPORT_FORMAT \ ENGINE_MEMORY_LIMIT_BYTES \ ) \ --volume "$PWD":/code \ diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml index 33d77e39bc9..c4e194bd658 100644 --- a/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml @@ -186,7 +186,7 @@ production_manual: when: never - if: '$CI_COMMIT_BRANCH != "master"' when: never - # $INCREMENTAL_ROLLOUT_ENABLED is for compamtibilty with pre-GitLab 11.4 syntax + # $INCREMENTAL_ROLLOUT_ENABLED is for compatibility with pre-GitLab 11.4 syntax - if: '$INCREMENTAL_ROLLOUT_MODE == "manual" || $INCREMENTAL_ROLLOUT_ENABLED' when: manual diff --git a/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml index 8b921305c11..385959389de 100644 --- a/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml @@ -183,7 +183,7 @@ production_manual: when: never - if: '$CI_COMMIT_BRANCH != "master"' when: never - # $INCREMENTAL_ROLLOUT_ENABLED is for compamtibilty with pre-GitLab 11.4 syntax + # $INCREMENTAL_ROLLOUT_ENABLED is for compatibility with pre-GitLab 11.4 syntax - if: '$INCREMENTAL_ROLLOUT_MODE == "manual" || $INCREMENTAL_ROLLOUT_ENABLED' when: manual diff --git a/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml index 317e8bfab0e..0289ba1c473 100644 --- a/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Jobs/Deploy/ECS.gitlab-ci.yml @@ -8,8 +8,11 @@ # # More about including CI templates: https://docs.gitlab.com/ee/ci/yaml/#includetemplate -.deploy_to_ecs: +.ecs_image: image: 'registry.gitlab.com/gitlab-org/cloud-deploy/aws-ecs:latest' + +.deploy_to_ecs: + extends: .ecs_image dependencies: [] script: - ecs update-task-definition @@ -17,8 +20,6 @@ .review_ecs_base: stage: review extends: .deploy_to_ecs - environment: - name: review/$CI_COMMIT_REF_NAME .production_ecs_base: stage: production @@ -26,8 +27,18 @@ environment: name: production +.stop_review_ecs_base: + extends: .ecs_image + stage: cleanup + allow_failure: true + script: + - ecs stop-task + review_ecs: extends: .review_ecs_base + environment: + name: review/$CI_COMMIT_REF_NAME + on_stop: stop_review_ecs rules: - if: '$AUTO_DEVOPS_PLATFORM_TARGET != "ECS"' when: never @@ -39,8 +50,46 @@ review_ecs: when: never - if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH' +stop_review_ecs: + extends: .stop_review_ecs_base + environment: + name: review/$CI_COMMIT_REF_NAME + action: stop + rules: + - if: '$AUTO_DEVOPS_PLATFORM_TARGET != "ECS"' + when: never + - if: '$CI_KUBERNETES_ACTIVE' + when: never + - if: '$REVIEW_DISABLED' + when: never + - if: '$CI_COMMIT_BRANCH == "master"' + when: never + - if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH' + when: manual + review_fargate: extends: .review_ecs_base + environment: + name: review/$CI_COMMIT_REF_NAME + on_stop: stop_review_fargate + script: + - ecs update-task-definition + rules: + - if: '$AUTO_DEVOPS_PLATFORM_TARGET != "FARGATE"' + when: never + - if: '$CI_KUBERNETES_ACTIVE' + when: never + - if: '$REVIEW_DISABLED' + when: never + - if: '$CI_COMMIT_BRANCH == "master"' + when: never + - if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH' + +stop_review_fargate: + extends: .stop_review_ecs_base + environment: + name: review/$CI_COMMIT_REF_NAME + action: stop rules: - if: '$AUTO_DEVOPS_PLATFORM_TARGET != "FARGATE"' when: never @@ -51,6 +100,7 @@ review_fargate: - if: '$CI_COMMIT_BRANCH == "master"' when: never - if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH' + when: manual production_ecs: extends: .production_ecs_base diff --git a/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml b/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml index a9638f564f3..3f62d92ad13 100644 --- a/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml @@ -1,6 +1,6 @@ apply: stage: deploy - image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.33.0" + image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.34.1" environment: name: production variables: diff --git a/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml index c3a92b67a8b..0ae8fd833c4 100644 --- a/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml @@ -1,3 +1,9 @@ +# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/api_fuzzing/ + +# Configure the scanning tool through the environment variables. +# List of the variables: https://docs.gitlab.com/ee/user/application_security/api_fuzzing/#available-variables +# How to set: https://docs.gitlab.com/ee/ci/yaml/#variables + stages: - build - test @@ -7,7 +13,7 @@ stages: variables: FUZZAPI_PROFILE: Quick FUZZAPI_VERSION: latest - FUZZAPI_CONFIG: "/app/.gitlab-api-fuzzing.yml" + FUZZAPI_CONFIG: .gitlab-api-fuzzing.yml FUZZAPI_TIMEOUT: 30 FUZZAPI_REPORT: gl-api-fuzzing-report.xml # @@ -17,9 +23,70 @@ variables: # available (non 500 response to HTTP(s)) FUZZAPI_SERVICE_START_TIMEOUT: "300" # + FUZZAPI_IMAGE: registry.gitlab.com/gitlab-org/security-products/analyzers/api-fuzzing:${FUZZAPI_VERSION}-engine + # + +apifuzzer_fuzz_unlicensed: + stage: fuzz + allow_failure: true + rules: + - if: '$GITLAB_FEATURES !~ /\bapi_fuzzing\b/ && $API_FUZZING_DISABLED == null' + - when: never + script: + - | + echo "Error: Your GitLab project is not licensed for API Fuzzing." + - exit 1 apifuzzer_fuzz: stage: fuzz + image: + name: $FUZZAPI_IMAGE + entrypoint: ["/bin/bash", "-l", "-c"] + variables: + FUZZAPI_PROJECT: $CI_PROJECT_PATH + FUZZAPI_API: http://apifuzzer:80 + TZ: America/Los_Angeles + services: + - name: $FUZZAPI_IMAGE + alias: apifuzzer + entrypoint: ["dotnet", "/peach/Peach.Web.dll"] + allow_failure: true + rules: + - if: $FUZZAPI_D_TARGET_IMAGE + when: never + - if: $FUZZAPI_D_WORKER_IMAGE + when: never + - if: $API_FUZZING_DISABLED + when: never + - if: $API_FUZZING_DISABLED_FOR_DEFAULT_BRANCH && + $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME + when: never + - if: $GITLAB_FEATURES =~ /\bapi_fuzzing\b/ + script: + # + # Validate options + - | + if [ "$FUZZAPI_HAR$FUZZAPI_OPENAPI$FUZZAPI_POSTMAN_COLLECTION" == "" ]; then \ + echo "Error: One of FUZZAPI_HAR, FUZZAPI_OPENAPI, or FUZZAPI_POSTMAN_COLLECTION must be provided."; \ + echo "See https://docs.gitlab.com/ee/user/application_security/api_fuzzing/ for information on how to configure API Fuzzing."; \ + exit 1; \ + fi + # + # Run user provided pre-script + - sh -c "$FUZZAPI_PRE_SCRIPT" + # + # Start scanning + - worker-entry + # + # Run user provided post-script + - sh -c "$FUZZAPI_POST_SCRIPT" + # + artifacts: + reports: + junit: $FUZZAPI_REPORT + +apifuzzer_fuzz_dnd: + stage: fuzz image: docker:19.03.12 variables: DOCKER_DRIVER: overlay2 @@ -28,20 +95,19 @@ apifuzzer_fuzz: FUZZAPI_API: http://apifuzzer:80 allow_failure: true rules: + - if: $FUZZAPI_D_TARGET_IMAGE == null && $FUZZAPI_D_WORKER_IMAGE == null + when: never - if: $API_FUZZING_DISABLED when: never - if: $API_FUZZING_DISABLED_FOR_DEFAULT_BRANCH && - $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME - when: never - - if: $FUZZAPI_HAR == null && - $FUZZAPI_OPENAPI == null && - $FUZZAPI_D_WORKER_IMAGE == null + $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME when: never - if: $GITLAB_FEATURES =~ /\bapi_fuzzing\b/ services: - docker:19.03.12-dind script: # + # - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY # - docker network create --driver bridge $FUZZAPI_D_NETWORK @@ -56,30 +122,13 @@ apifuzzer_fuzz: --network $FUZZAPI_D_NETWORK \ -e Proxy:Port=8000 \ -e TZ=America/Los_Angeles \ - -e FUZZAPI_API=http://127.0.0.1:80 \ - -e FUZZAPI_PROJECT \ - -e FUZZAPI_PROFILE \ - -e FUZZAPI_CONFIG \ - -e FUZZAPI_REPORT \ - -e FUZZAPI_HAR \ - -e FUZZAPI_OPENAPI \ - -e FUZZAPI_TARGET_URL \ - -e FUZZAPI_OVERRIDES_FILE \ - -e FUZZAPI_OVERRIDES_ENV \ - -e FUZZAPI_OVERRIDES_CMD \ - -e FUZZAPI_OVERRIDES_INTERVAL \ - -e FUZZAPI_TIMEOUT \ - -e FUZZAPI_VERBOSE \ - -e FUZZAPI_SERVICE_START_TIMEOUT \ - -e FUZZAPI_HTTP_USERNAME \ - -e FUZZAPI_HTTP_PASSWORD \ -e GITLAB_FEATURES \ - -v $CI_PROJECT_DIR:/app \ -p 80:80 \ -p 8000:8000 \ -p 514:514 \ --restart=no \ - registry.gitlab.com/gitlab-org/security-products/analyzers/api-fuzzing:${FUZZAPI_VERSION}-engine + $FUZZAPI_IMAGE \ + dotnet /peach/Peach.Web.dll # # Start target container - | @@ -94,19 +143,31 @@ apifuzzer_fuzz: $FUZZAPI_D_TARGET_IMAGE \ ; fi # - # Start worker container + # Start worker container if provided - | if [ "$FUZZAPI_D_WORKER_IMAGE" != "" ]; then \ - echo "Starting worker image $FUZZAPI_D_WORKER_IMAGE" \ + echo "Starting worker image $FUZZAPI_D_WORKER_IMAGE"; \ docker run \ --name worker \ --network $FUZZAPI_D_NETWORK \ -e FUZZAPI_API=http://apifuzzer:80 \ -e FUZZAPI_PROJECT \ -e FUZZAPI_PROFILE \ - -e FUZZAPI_AUTOMATION_CMD \ -e FUZZAPI_CONFIG \ -e FUZZAPI_REPORT \ + -e FUZZAPI_HAR \ + -e FUZZAPI_OPENAPI \ + -e FUZZAPI_POSTMAN_COLLECTION \ + -e FUZZAPI_TARGET_URL \ + -e FUZZAPI_OVERRIDES_FILE \ + -e FUZZAPI_OVERRIDES_ENV \ + -e FUZZAPI_OVERRIDES_CMD \ + -e FUZZAPI_OVERRIDES_INTERVAL \ + -e FUZZAPI_TIMEOUT \ + -e FUZZAPI_VERBOSE \ + -e FUZZAPI_SERVICE_START_TIMEOUT \ + -e FUZZAPI_HTTP_USERNAME \ + -e FUZZAPI_HTTP_PASSWORD \ -e CI_COMMIT_BRANCH=${CI_COMMIT_BRANCH} \ $FUZZAPI_D_WORKER_ENV \ $FUZZAPI_D_WORKER_PORTS \ @@ -115,13 +176,49 @@ apifuzzer_fuzz: $FUZZAPI_D_WORKER_IMAGE \ ; fi # - # Wait for testing to complete if api fuzzer is scanning - - if [ "$FUZZAPI_HAR$FUZZAPI_OPENAPI" != "" ]; then echo "Waiting for API Fuzzer to exit"; docker wait apifuzzer; fi + # Start API Fuzzing provided worker if no other worker present + - | + if [ "$FUZZAPI_D_WORKER_IMAGE" == "" ]; then \ + if [ "$FUZZAPI_HAR$FUZZAPI_OPENAPI$FUZZAPI_POSTMAN_COLLECTION" == "" ]; then \ + echo "Error: One of FUZZAPI_HAR, FUZZAPI_OPENAPI, or FUZZAPI_POSTMAN_COLLECTION must be provided."; \ + echo "See https://docs.gitlab.com/ee/user/application_security/api_fuzzing/ for information on how to configure API Fuzzing."; \ + exit 1; \ + fi; \ + docker run \ + --name worker \ + --network $FUZZAPI_D_NETWORK \ + -e TZ=America/Los_Angeles \ + -e FUZZAPI_API=http://apifuzzer:80 \ + -e FUZZAPI_PROJECT \ + -e FUZZAPI_PROFILE \ + -e FUZZAPI_CONFIG \ + -e FUZZAPI_REPORT \ + -e FUZZAPI_HAR \ + -e FUZZAPI_OPENAPI \ + -e FUZZAPI_POSTMAN_COLLECTION \ + -e FUZZAPI_TARGET_URL \ + -e FUZZAPI_OVERRIDES_FILE \ + -e FUZZAPI_OVERRIDES_ENV \ + -e FUZZAPI_OVERRIDES_CMD \ + -e FUZZAPI_OVERRIDES_INTERVAL \ + -e FUZZAPI_TIMEOUT \ + -e FUZZAPI_VERBOSE \ + -e FUZZAPI_SERVICE_START_TIMEOUT \ + -e FUZZAPI_HTTP_USERNAME \ + -e FUZZAPI_HTTP_PASSWORD \ + -v $CI_PROJECT_DIR:/app \ + -p 81:80 \ + -p 8001:8000 \ + -p 515:514 \ + --restart=no \ + $FUZZAPI_IMAGE \ + worker-entry \ + ; fi # - # Propagate exit code from api fuzzer (if any) - - if [[ $(docker inspect apifuzzer --format='{{.State.ExitCode}}') != "0" ]]; then echo "API Fuzzing exited with an error. Logs are available as job artifacts."; docker logs apifuzzer; exit 1; fi + # Propagate exit code from api fuzzing scanner (if any) + - if [[ $(docker inspect apifuzzer --format='{{.State.ExitCode}}') != "0" ]]; then echo "API Fuzzing scanner exited with an error. Logs are available as job artifacts."; exit 1; fi # - # Run user provided pre-script + # Run user provided post-script - sh -c "$FUZZAPI_POST_SCRIPT" # after_script: @@ -129,13 +226,13 @@ apifuzzer_fuzz: # Shutdown all containers - echo "Stopping all containers" - if [ "$FUZZAPI_D_TARGET_IMAGE" != "" ]; then docker stop target; fi - - if [ "$FUZZAPI_D_WORKER_IMAGE" != "" ]; then docker stop worker; fi + - docker stop worker - docker stop apifuzzer # # Save docker logs - docker logs apifuzzer &> gl-api_fuzzing-logs.log - if [ "$FUZZAPI_D_TARGET_IMAGE" != "" ]; then docker logs target &> gl-api_fuzzing-target-logs.log; fi - - if [ "$FUZZAPI_D_WORKER_IMAGE" != "" ]; then docker logs worker &> gl-api_fuzzing-worker-logs.log; fi + - docker logs worker &> gl-api_fuzzing-worker-logs.log # artifacts: when: always diff --git a/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml index 21bcdd8d9b5..3cbde9d30c8 100644 --- a/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml @@ -4,8 +4,7 @@ variables: # Setting this variable will affect all Security templates # (SAST, Dependency Scanning, ...) SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers" - - CS_MAJOR_VERSION: 2 + CS_MAJOR_VERSION: 3 container_scanning: stage: test diff --git a/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml index e268b48d133..a1b6dc2cc1b 100644 --- a/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Security/Coverage-Fuzzing.gitlab-ci.yml @@ -11,6 +11,14 @@ variables: COVFUZZ_URL_PREFIX: "https://gitlab.com/gitlab-org/security-products/analyzers/gitlab-cov-fuzz/-/raw" +coverage_fuzzing_unlicensed: + stage: test + allow_failure: true + rules: + - if: $GITLAB_FEATURES !~ /\bcoverage_fuzzing\b/ && $COVFUZZ_DISABLED == null + script: + - echo "ERROR Your GitLab project is missing licensing for Coverage Fuzzing" && exit 1 + .fuzz_base: stage: fuzz allow_failure: true diff --git a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml index 4418ff18d73..a51cb61da6d 100644 --- a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml @@ -134,6 +134,7 @@ mobsf-android-sast: name: "$SAST_ANALYZER_IMAGE" variables: SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/mobsf:$SAST_ANALYZER_IMAGE_TAG" + MOBSF_API_KEY: key rules: - if: $SAST_DISABLED when: never @@ -152,6 +153,7 @@ mobsf-ios-sast: name: "$SAST_ANALYZER_IMAGE" variables: SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/mobsf:$SAST_ANALYZER_IMAGE_TAG" + MOBSF_API_KEY: key rules: - if: $SAST_DISABLED when: never diff --git a/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml index 2d2e0859373..232c320562b 100644 --- a/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Security/Secure-Binaries.gitlab-ci.yml @@ -131,6 +131,8 @@ secrets: variables: - $SECURE_BINARIES_DOWNLOAD_IMAGES == "true" && $SECURE_BINARIES_ANALYZERS =~ /\bsecrets\b/ + variables: + SECURE_BINARIES_ANALYZER_VERSION: "3" sobelow: extends: .download_images @@ -162,6 +164,8 @@ klar: variables: - $SECURE_BINARIES_DOWNLOAD_IMAGES == "true" && $SECURE_BINARIES_ANALYZERS =~ /\bklar\b/ + variables: + SECURE_BINARIES_ANALYZER_VERSION: "3" clair-vulnerabilities-db: extends: .download_images diff --git a/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml index b08ccf18b58..5963d7138c5 100644 --- a/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml @@ -1,11 +1,12 @@ include: - - template: Terraform/Base.latest.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Terraform/Base.gitlab-ci.yml + - template: Terraform/Base.latest.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml stages: - init - validate - build - deploy + - cleanup init: extends: .init diff --git a/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml index 000a1a7f580..e455bfac9de 100644 --- a/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml @@ -12,9 +12,6 @@ image: name: registry.gitlab.com/gitlab-org/terraform-images/stable:latest -before_script: - - cd ${TF_ROOT} - variables: TF_ROOT: ${CI_PROJECT_DIR} @@ -26,16 +23,19 @@ cache: .init: &init stage: init script: + - cd ${TF_ROOT} - gitlab-terraform init .validate: &validate stage: validate script: + - cd ${TF_ROOT} - gitlab-terraform validate .build: &build stage: build script: + - cd ${TF_ROOT} - gitlab-terraform plan - gitlab-terraform plan-json artifacts: @@ -47,7 +47,14 @@ cache: .deploy: &deploy stage: deploy script: + - cd ${TF_ROOT} - gitlab-terraform apply when: manual only: - master + +.destroy: &destroy + stage: cleanup + script: + - gitlab-terraform destroy + when: manual diff --git a/lib/gitlab/ci/trace/chunked_io.rb b/lib/gitlab/ci/trace/chunked_io.rb index e99889f4a25..6f3e4ccf48d 100644 --- a/lib/gitlab/ci/trace/chunked_io.rb +++ b/lib/gitlab/ci/trace/chunked_io.rb @@ -75,7 +75,7 @@ module Gitlab until length <= 0 || eof? data = chunk_slice_from_offset - raise FailedToGetChunkError if data.empty? + raise FailedToGetChunkError if data.to_s.empty? chunk_bytes = [CHUNK_SIZE - chunk_offset, length].min chunk_data_slice = data.byteslice(0, chunk_bytes) @@ -100,7 +100,7 @@ module Gitlab until eof? data = chunk_slice_from_offset - raise FailedToGetChunkError if data.empty? + raise FailedToGetChunkError if data.to_s.empty? new_line = data.index("\n") |