gitlab-qa 15.2.0 → 15.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 793b59a3d3817c1e3fa0794cfceaf8f80bc7a193e46e9ce3704ce8b8301e9143
4
- data.tar.gz: 299f7ce902fd8b9603cda51c2f5f018ff5c7a230b01944ca99c0eea9168ccc0a
3
+ metadata.gz: 4bc0f25e1bbf4c9d82910a6b8a2da29df78bbe683d620d82cb0d36e28a906dcb
4
+ data.tar.gz: '0283a7bc128cc2e86f1e4aa1a7c0c0020be2a6c62c543019c1879e73bf5b9e2f'
5
5
  SHA512:
6
- metadata.gz: 253cc2d2d41a94030bcb6c0b5a0225ff46ff9019677b8b1486104ee556fb219ecda07bbe724c51ed822699c0e2c2ccc0273795b122e810971bc956aa16af14ee
7
- data.tar.gz: eb4f3be8907209202af1aa51f9c1b8c70523645f31afdda60a294bbe7972ec769c1199fb8ca7075b46c862ad3161b1e3d5bd2369a2fe587a929bc2052f7ee208
6
+ metadata.gz: 0a14c2e7949b7cbe2b031e13ad5c12488160025c256d831e6bda9158890fc311277f31d10279b1a1b184fbef463b95bac2767b80103fa41a6d011d42ffc2be71
7
+ data.tar.gz: e4180225aa649c4796a85c4c016651adc8200cf6b8e2c69e451b8f64e26a32caf7f71bfd28159d026bcd1d6355b541631f6c8ae6f8c28fef38e94929b4216d87
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab-qa (15.2.0)
4
+ gitlab-qa (15.3.0)
5
5
  activesupport (>= 6.1, < 7.2)
6
6
  ffi (~> 1.17)
7
7
  gitlab (~> 4.19)
@@ -299,11 +299,11 @@ $ gitlab-qa Test::Omnibus::Upgrade CE
299
299
  $ gitlab-qa Test::Omnibus::Upgrade gitlab/gitlab-ce:my-custom-tag
300
300
  ```
301
301
 
302
- ### `Test::Omnibus::UpdateFromPrevious <full image address> <current_version> <major|minor> <from_edition>`
302
+ ### `Test::Omnibus::UpdateFromPrevious <full image address> <current_version> <major|minor|patch> <from_edition>`
303
303
 
304
- Scenario verifies upgrade from previous (major|minor) version to current release.
304
+ Scenario verifies upgrade from previous (major|minor|patch) version to current release.
305
305
 
306
- - Deploys previous (major|minor) version and runs Smoke test suite
306
+ - Deploys previous (major|minor|patch) version and runs Health Check test suite (Smoke test suite if below 17.1.0)
307
307
  to populate data in database before upgrade
308
308
  - Generates upgrade path following current GitLab recommendations
309
309
  from ['gitlab.com/gitlab-org/gitlab'](https://gitlab.com/gitlab-org/gitlab/-/raw/master/config/upgrade_path.yml) project
@@ -318,6 +318,27 @@ $ gitlab-qa Test::Omnibus::UpdateFromPrevious gitlab-ee:dev-tag 15.6.0-pre minor
318
318
 
319
319
  # Major upgrade - will perform upgrades 14.10.x -> 15.0.x -> 15.4.x -> gitlab-ee:dev-tag (15.6.0-pre)
320
320
  $ gitlab-qa Test::Omnibus::UpdateFromPrevious gitlab-ee:dev-tag 15.6.0-pre major
321
+
322
+ # Patch upgrade - will perform upgrade from 17.8.1 -> gitlab-ee:dev-tag (17.8.2-pre)
323
+ $ gitlab-qa Test::Omnibus::UpdateFromPrevious gitlab-ee:dev-tag 17.8.2-pre patch
324
+ ```
325
+
326
+ ### `Test::Omnibus::UpdateToNext <full image address> <current_version> <from_edition>`
327
+
328
+ Scenario verifies upgrade from current development version to next available stable release.
329
+
330
+ - Deploys development version and runs Health Check test suite to populate data in database (Smoke test suite if below 17.1.0)
331
+ - Finds next available stable version
332
+ - Upgrades GitLab instance from development version to next stable and runs tests against it
333
+ - Skips if either current version or next version is not yet released
334
+
335
+ Note: `from_edition` setting is optional, can be set to `ee` or `ce`.
336
+
337
+ Example:
338
+
339
+ ```shell
340
+ # Will perform upgrade from gitlab-ee:dev-tag (17.8.2-pre) -> 17.9.2
341
+ $ gitlab-qa Test::Omnibus::UpdateToNext gitlab-ee:dev-tag 17.8.2-pre
321
342
  ```
322
343
 
323
344
  ### `Test::Integration::Geo EE|<full image address>`
@@ -1049,6 +1070,29 @@ This orchestrated scenario runs tests from the test suite against a GitLab insta
1049
1070
 
1050
1071
  These variables are available at 1Password QA Vault.
1051
1072
 
1073
+ ----
1074
+
1075
+ #### `Test::Instance::SecureVersion EE|<full image address>`
1076
+
1077
+ Used for testing that a project with Secure scanner functionality functions correctly against the specified version.
1078
+ As this is Secure functionality, an EE license is required.
1079
+ Can be used for running older instances of GitLab, this skips the Security version modal on login.
1080
+
1081
+ The script applies the license, imports the project, kicks off a pipeline, and checks that the pipeline was successful.
1082
+
1083
+ **Required environment variables:**
1084
+
1085
+ - `EE_LICENSE`: A valid EE license for testing.
1086
+ - `PROJECT_URL`: The URL of the project to test.
1087
+ - `PROJECT_NAME`: The name of the project to test, when imported to the instance.
1088
+
1089
+ Example:
1090
+
1091
+ ```shell
1092
+ $ export EE_LICENSE=$(cat /path/to/gitlab_license)
1093
+ $ PROJECT_URL='https://gitlab.com/gitlab-org/quality/ci/secure-testing/secure-matrix-test.git' PROJECT_NAME='secure-matrix-test' gitlab-qa Test::Instance::SecureVersion gitlab/gitlab-ee:16.5.0-ee.0
1094
+ ```
1095
+
1052
1096
  ### `Test::Integration::RegistryTLS EE`
1053
1097
 
1054
1098
  It uses GitLab's TLS certificate found in the [`tls_certificates`](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/tls_certificates/gitlab/gitlab.test.crt) folder.
@@ -1236,4 +1280,16 @@ $ gitlab-qa Test::Integration::AiGatewayNoLicense EE
1236
1280
 
1237
1281
  ----
1238
1282
 
1283
+ #### Troubleshooting `AiGateway` Tests
1284
+
1285
+ The following logs are available for troubleshooting `AiGateway` tests in the `e2e-test-on-omnibus` pipelines.
1286
+
1287
+ | Component | Log Location | Additional Info |
1288
+ |----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|
1289
+ | CustomersDot Staging | [Kibana](https://nonprod-log.gitlab.net/) (`pubsub-rails-inf-stgsub*`), [Sentry](https://new-sentry.gitlab.net/organizations/gitlab/issues/?environment=stg&project=8) | See [CustomersDot Logging](https://gitlab.com/gitlab-org/customers-gitlab-com/blob/main/doc/architecture/logging.md#customersdot-logging) for details |
1290
+ | GitLab Omnibus | Job artifacts: `gitlab/logs` | See the GitLab [Log system](https://docs.gitlab.com/ee/administration/logs/) docs for more details |
1291
+ | AI Gateway | Job artifacts: `ai-gateway/logs/modelgateway_debug.log` | See the AI Gateway's [README](https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist#gitlab-ai-gateway) for more details |
1292
+
1293
+ ----
1294
+
1239
1295
  [Back to README.md](../README.md)
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module Component
6
+ class LicenseOps < Base
7
+ LicenseError = Class.new(StandardError)
8
+ require 'shellwords'
9
+
10
+ def add_license(gitlab)
11
+ license_key = fetch_license_key
12
+ command = build_license_command(license_key)
13
+ apply_license(gitlab, command, license_key)
14
+ end
15
+
16
+ private
17
+
18
+ def fetch_license_key
19
+ license_key = ENV.fetch('EE_LICENSE', '')
20
+ raise LicenseError, "EE_LICENSE environment variable is not set or is empty" if license_key.empty?
21
+
22
+ Shellwords.shellwords(license_key).join
23
+ end
24
+
25
+ def build_license_command(license_key)
26
+ script = <<~RUBY
27
+ key = ENV['EE_LICENSE']
28
+ license = License.new(data: key)
29
+ if license.save
30
+ puts "License applied successfully"
31
+ else
32
+ STDERR.puts "Failed to apply license"
33
+ end
34
+ RUBY
35
+ "EE_LICENSE='#{license_key}' gitlab-rails runner $'#{script.gsub("'", "\\\\'").gsub("\n", '\\n')}'"
36
+ end
37
+
38
+ def apply_license(gitlab, command, license_key)
39
+ result = gitlab.docker.exec(gitlab.name, command, mask_secrets: license_key)
40
+ verify_license_application(result)
41
+ end
42
+
43
+ def verify_license_application(result)
44
+ return if result.include?("License applied successfully")
45
+
46
+ raise LicenseError, "Failed to apply license."
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module Component
6
+ class PipelineOps < Base
7
+ def start(gitlab, project_name)
8
+ create_and_execute_pipeline_script(gitlab, project_name)
9
+ end
10
+
11
+ def check_status(gitlab)
12
+ pipeline_status = gitlab.docker.exec(
13
+ gitlab.name, wait_for_pipeline)
14
+
15
+ case pipeline_status
16
+ when 'success'
17
+ puts "Pipeline succeeded!"
18
+ nil
19
+ when 'failed'
20
+ raise StandardError, "Pipeline failed."
21
+ else
22
+ puts "Pipeline is currently #{pipeline_status}"
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def create_and_execute_pipeline_script(gitlab, project_name)
29
+ setup_src_path = File.expand_path('../../../../support/pipeline', __dir__)
30
+ setup_dest_path = '/tmp/setup-scripts'
31
+
32
+ gitlab.docker.copy(gitlab.name, setup_src_path, setup_dest_path)
33
+
34
+ gitlab.docker.exec(
35
+ gitlab.name,
36
+ "PROJECT_NAME='#{project_name}' gitlab-rails runner #{setup_dest_path}/create_for_projectname.rb"
37
+ )
38
+ end
39
+
40
+ def wait_for_pipeline
41
+ <<~SHELL
42
+ gitlab-rails runner "
43
+ latest_pipeline = Ci::Pipeline.last
44
+ # wait for the pipeline to complete
45
+ loop do
46
+ latest_pipeline.reload
47
+ break if latest_pipeline.complete?
48
+ sleep 1
49
+ end
50
+ puts latest_pipeline.status
51
+ "
52
+ SHELL
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module Component
6
+ class ProjectImporter < Base
7
+ IMPORT_TIMEOUT = 300 # 5 minutes
8
+
9
+ def initialize(project_url, project_name, project_path: project_name)
10
+ @project_name = project_name
11
+ @project_url = project_url
12
+ @project_path = project_path
13
+ end
14
+
15
+ def import_project(gitlab)
16
+ import_command = build_import_command(create_import_script, @project_url, @project_name, @project_path)
17
+ puts gitlab.docker.exec(gitlab.name, import_command)
18
+ end
19
+
20
+ private
21
+
22
+ def create_import_script
23
+ <<~'RUBY'
24
+ require 'timeout'
25
+
26
+ project_url = ENV.fetch('PROJECT_URL')
27
+ project_name = ENV.fetch('PROJECT_NAME')
28
+ project_path = ENV.fetch('PROJECT_PATH')
29
+
30
+ root_user = User.find_by_username('root')
31
+
32
+ project = Projects::CreateService.new(root_user,
33
+ { name: project_name, path: project_path, import_url: project_url }).execute
34
+
35
+ if project.persisted?
36
+ # Wait for import to complete
37
+ begin
38
+ Timeout.timeout(300) do # 5 minutes timeout
39
+ until ['finished', 'failed'].include?(project.import_status)
40
+ sleep 5
41
+ project.reload
42
+ end
43
+ end
44
+ rescue Timeout::Error
45
+ puts "Import process timed out after 5 minutes"
46
+ end
47
+ else
48
+ puts "Failed to create project: #{project.errors.full_messages.join(', ')}"
49
+ end
50
+
51
+ # Always print import state for debugging
52
+ puts "Import state: #{project.import_state.attributes}" if project.respond_to?(:import_state)
53
+ RUBY
54
+ end
55
+
56
+ def build_import_command(script, project_url, project_name, project_path)
57
+ escaped_script = script.gsub("'", "\\\\'").gsub("\n", "\\n")
58
+ "PROJECT_URL='#{project_url}' PROJECT_NAME='#{project_name}' PROJECT_PATH='#{project_path}' gitlab-rails runner $'#{escaped_script}'"
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module Component
6
+ class RunnerOps < Base
7
+ include Support::Shellout
8
+
9
+ RUNNER_DESCRIPTION = "QA Runner"
10
+ DOCKER_IMAGE = "registry.gitlab.com/gitlab-org/gitlab-runner:alpine"
11
+ BUILD_IMAGE = "registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine-ruby-2.7"
12
+
13
+ def setup_runner(gitlab)
14
+ token = SecureRandom.hex(15)
15
+ add_runner_to_gitlab(gitlab, token)
16
+ register_docker_runner(gitlab, token)
17
+ end
18
+
19
+ private
20
+
21
+ def add_runner_to_gitlab(gitlab, token)
22
+ gitlab.docker.exec(
23
+ gitlab.name,
24
+ create_runner_command(token),
25
+ mask_secrets: token
26
+ )
27
+ end
28
+
29
+ def create_runner_command(token)
30
+ <<~RUBY.strip.gsub(/\s+/, ' ')
31
+ gitlab-rails runner '
32
+ Ci::Runner.create!(
33
+ description: "#{RUNNER_DESCRIPTION}",
34
+ run_untagged: true,
35
+ active: true,
36
+ token: "#{token}",
37
+ runner_type: :instance_type
38
+ );
39
+ puts "Runner created"
40
+ '
41
+ RUBY
42
+ end
43
+
44
+ def register_docker_runner(gitlab, token)
45
+ runner_name = generate_runner_name
46
+ docker_command = build_docker_command(
47
+ runner_name: runner_name,
48
+ network: gitlab.network,
49
+ address: gitlab.address,
50
+ token: token
51
+ )
52
+
53
+ shell(docker_command, mask_secrets: [token])
54
+ end
55
+
56
+ def generate_runner_name
57
+ "test-runner-#{SecureRandom.hex(4)}"
58
+ end
59
+
60
+ def build_docker_command(runner_name:, network:, address:, token:)
61
+ <<~CMD.tr("\n", ' ')
62
+ docker run -d --rm --network #{network} --name #{runner_name}
63
+ -v /var/run/docker.sock:/var/run/docker.sock
64
+ --privileged
65
+ #{DOCKER_IMAGE}
66
+ && docker exec --detach #{runner_name} sh -c "#{register_command(runner_name, address, token, network)}"
67
+ CMD
68
+ end
69
+
70
+ def runner_config
71
+ <<~CONFIG
72
+ concurrent = 1
73
+ check_interval = 0
74
+
75
+ [session_server]
76
+ session_timeout = 1800
77
+ CONFIG
78
+ end
79
+
80
+ def register_command(name, address, token, network)
81
+ registration_args = build_registration_args(
82
+ name: name,
83
+ address: address,
84
+ token: token,
85
+ network: network
86
+ )
87
+
88
+ <<~CMD.strip
89
+ echo "#{runner_config}" > /etc/gitlab-runner/config.toml &&
90
+ gitlab-runner register #{registration_args} &&
91
+ gitlab-runner run
92
+ CMD
93
+ end
94
+
95
+ def build_registration_args(name:, address:, token:, network:)
96
+ [
97
+ '--non-interactive',
98
+ "--name #{name}",
99
+ "--url #{address}",
100
+ "--token #{token}",
101
+ '--run-untagged=true',
102
+ '--executor docker',
103
+ "--docker-image #{BUILD_IMAGE}",
104
+ '--docker-tlsverify=false',
105
+ '--docker-privileged=true',
106
+ "--docker-network-mode=#{network}",
107
+ '--docker-volumes=/certs/client'
108
+ ].join(' ')
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -81,6 +81,18 @@ module Gitlab
81
81
  ), mask_secrets: mask_secrets)
82
82
  end
83
83
 
84
+ # Executes a command inside a running Docker container.
85
+ #
86
+ # @param name [String] The name or ID of the container to execute the command in.
87
+ # @param command [String] The command to be executed inside the container.
88
+ # @param mask_secrets [Boolean, nil] Whether to mask sensitive information in logs. Defaults to nil.
89
+ # @param shell [String] The shell to use for executing the command. Defaults to "bash".
90
+ #
91
+ # @return [String] The output of the executed command.
92
+ #
93
+ # @example
94
+ # exec("my-container", "echo 'hello world'")
95
+ # # => "hello world\n"
84
96
  def exec(name, command, mask_secrets: nil, shell: "bash")
85
97
  cmd = ['exec']
86
98
  cmd << '--privileged' if privileged_command?(command)
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module Scenario
6
+ module Test
7
+ module Instance
8
+ class SecureVersion < Scenario::Template
9
+ include Support::Shellout
10
+
11
+ attr_writer :volumes, :seed_admin_token
12
+
13
+ def initialize
14
+ @volumes = {}
15
+ @seed_admin_token = true
16
+ @pipeline_ops = Component::PipelineOps.new
17
+ @runner_ops = Component::RunnerOps.new
18
+ @importer = Component::ProjectImporter.new(
19
+ ENV.fetch('PROJECT_URL', nil),
20
+ ENV.fetch('PROJECT_NAME', nil))
21
+ @license_ops = Component::LicenseOps.new
22
+ end
23
+
24
+ def perform(release, *_rspec_args)
25
+ Component::Gitlab.perform do |gitlab|
26
+ setup_gitlab(gitlab, release)
27
+ execute_gitlab_operations(gitlab)
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def setup_gitlab(gitlab, release)
34
+ gitlab.release = release
35
+ gitlab.volumes = @volumes
36
+ gitlab.network = Runtime::Env.docker_network
37
+ gitlab.name = Runtime::Env.qa_gitlab_hostname
38
+ gitlab.seed_admin_token = @seed_admin_token
39
+ gitlab.tls = Runtime::Env.qa_gitlab_use_tls?
40
+ # gitlab.exec_commands = foo
41
+ end
42
+
43
+ def execute_gitlab_operations(gitlab)
44
+ gitlab.instance do
45
+ @license_ops.add_license(gitlab)
46
+ @runner_ops.setup_runner(gitlab)
47
+ @importer.import_project(gitlab)
48
+ @pipeline_ops.start(gitlab, 'secure-matrix-test')
49
+ @pipeline_ops.check_status(gitlab)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module Scenario
6
+ module Test
7
+ module Omnibus
8
+ class UpdateToNext < UpdateFromPrevious
9
+ using Rainbow
10
+ # Test upgrade from development version to next stable release
11
+ #
12
+ # @example
13
+ # perform(gitlab-ee:dev-tag, 17.8.2-pre)
14
+ # => will perform upgrade gitlab-ee:dev-tag -> 17.9.2
15
+ #
16
+ # @param [String] release current release docker image with development changes
17
+ # @param [String] current_version current gitlab version associated with docker image
18
+ # @param [String] from_edition gitlab edition to update from
19
+ # @param [Array] *rspec_args rspec arguments
20
+ # @return [void]
21
+ def perform(release, current_version, from_edition = nil, *rspec_args)
22
+ # When from_edition isn't actually passed but RSpec args arg passed with `-- rspec_args...`,
23
+ # from_edition is wrongly set to `--`, so we fix that here.
24
+ if from_edition == "--"
25
+ rspec_args.prepend('--')
26
+ from_edition = nil
27
+ end
28
+
29
+ @current_release = QA::Release.new(release)
30
+ @upgrade_path = Support::GitlabUpgradePath.new(
31
+ current_version,
32
+ 'from_patch',
33
+ from_edition || @current_release.edition
34
+ ).fetch
35
+ @rspec_args = rspec_args
36
+
37
+ # Key difference to UpdateFromPrevious: current_release comes first in the upgrade path
38
+ upgrade_info = "(#{current_version}) #{[current_release, *upgrade_path].join(' => ')}".bright
39
+ Runtime::Logger.info("Performing gitlab update: #{upgrade_info}")
40
+
41
+ update(rspec_args)
42
+ end
43
+
44
+ private
45
+
46
+ # Override to run specs in reverse order - first on development version, then on target version
47
+ #
48
+ # @param [Array] rspec_args
49
+ # @return [void]
50
+ def update(rspec_args)
51
+ Docker::Volumes.new.with_temporary_volumes do |volumes|
52
+ # deploy development release and run specs to populate db
53
+ Runtime::Logger.info("Running the development release: #{current_release}")
54
+ run_gitlab(current_release, volumes, seeding_suite_args, seeding_run: true)
55
+
56
+ # deploy target release and run tests
57
+ upgrade_path.each do |release|
58
+ Runtime::Logger.info("Upgrading GitLab to target release: #{release}")
59
+ run_gitlab(release, volumes, rspec_args, skip_setup: true)
60
+ end
61
+ end
62
+ end
63
+
64
+ # Override to run specs on development release and final target
65
+ #
66
+ # @param [Gitlab::QA::Release] release
67
+ # @return [Boolean]
68
+ def run_specs?(release)
69
+ [current_release, upgrade_path.last].any?(release)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -13,11 +13,17 @@ module Gitlab
13
13
  # @param [String] semver_component version number component for previous version detection - major|minor|patch
14
14
  # @param [String] edition GitLab edition - ee or ce
15
15
  def initialize(current_version, semver_component, edition)
16
+ @logger = Runtime::Logger.logger
17
+
18
+ unless current_version.match?(GitlabVersionInfo::VERSION_PATTERN)
19
+ logger.error("Invalid 'current_version' format: #{current_version}. Expected format: MAJOR.MINOR.PATCH (e.g., 17.8.2)")
20
+ exit 1
21
+ end
22
+
16
23
  @version_info = GitlabVersionInfo.new(current_version, edition)
17
- @current_version = Gem::Version.new(current_version)
24
+ @current_version = Gem::Version.new(current_version.match(GitlabVersionInfo::VERSION_PATTERN)[:version]) # Extract version without postfixes like pre or ee
18
25
  @semver_component = semver_component
19
26
  @edition = edition
20
- @logger = Runtime::Logger.logger
21
27
  end
22
28
 
23
29
  # Get upgrade path between releases
@@ -26,9 +32,18 @@ module Gitlab
26
32
  #
27
33
  # @return [Array<QA::Release>]
28
34
  def fetch
29
- return minor_upgrade_path unless major_upgrade?
30
-
31
- major_upgrade_path
35
+ case semver_component
36
+ when "patch"
37
+ patch_upgrade_path
38
+ when "minor"
39
+ minor_upgrade_path
40
+ when "major"
41
+ major_upgrade_path
42
+ when "from_patch"
43
+ from_patch_upgrade_path
44
+ else
45
+ raise ArgumentError, "Unknown semver component: #{semver_component}"
46
+ end
32
47
  rescue GitlabVersionInfo::VersionNotFoundError
33
48
  logger.error("Failed to construct gitlab upgrade path")
34
49
  raise
@@ -40,6 +55,17 @@ module Gitlab
40
55
 
41
56
  attr_reader :version_info, :current_version, :semver_component, :edition, :logger
42
57
 
58
+ # Upgrade path for patch version update
59
+ # Returns array with current version as we're testing upgrade from
60
+ # latest stable patch to development version
61
+ #
62
+ # @return [Array]
63
+ def patch_upgrade_path
64
+ verify_current_version_exists
65
+
66
+ [release(latest_patch(current_version))]
67
+ end
68
+
43
69
  # Upgrade path from previous minor version
44
70
  #
45
71
  # @return [Array]
@@ -63,11 +89,21 @@ module Gitlab
63
89
  end
64
90
  end
65
91
 
66
- # Upgrade from previous major
92
+ # Upgrade path from current version to next stable version
93
+ # Checks if current version exists in releases
94
+ # Gets next available major.minor version and its latest patch
67
95
  #
68
- # @return [Boolean]
69
- def major_upgrade?
70
- semver_component == "major"
96
+ # @return [Array] Array with next version's latest patch release or exits with message
97
+ def from_patch_upgrade_path
98
+ verify_current_version_exists
99
+ next_version = version_info.next_version(current_version.to_s)
100
+
101
+ unless next_version
102
+ logger.info("Skipping upgrade test as next version after #{current_version} is not yet available")
103
+ exit 0
104
+ end
105
+
106
+ [release(latest_patch(next_version))]
71
107
  end
72
108
 
73
109
  # Docker release image
@@ -85,6 +121,17 @@ module Gitlab
85
121
  @previous_version ||= version_info.previous_version(semver_component)
86
122
  end
87
123
 
124
+ # Verify if current version exists in GitLab releases
125
+ # Exit with message if version is not yet released
126
+ #
127
+ # @return [void]
128
+ def verify_current_version_exists
129
+ return if version_info.version_exists?(current_version.to_s)
130
+
131
+ logger.info("Skipping upgrade test as version #{current_version} is not yet released")
132
+ exit 0
133
+ end
134
+
88
135
  # Gitlab upgrade path
89
136
  #
90
137
  # @return [Array<Gem::Version>]
@@ -36,6 +36,18 @@ module Gitlab
36
36
  end
37
37
  end
38
38
 
39
+ # Check if specific version exists in GitLab releases
40
+ #
41
+ # @example
42
+ # version_exists?("17.10.5") => true
43
+ # version_exists?("17.10.28") => false
44
+ #
45
+ # @param [String] version Version to check
46
+ # @return [Boolean] true if version exists in GitLab releases, false otherwise
47
+ def version_exists?(version)
48
+ !!versions.find { |ver| ver.to_s == version }
49
+ end
50
+
39
51
  # Get latest patch for specific version number
40
52
  #
41
53
  # @example
@@ -53,6 +65,27 @@ module Gitlab
53
65
  end
54
66
  end
55
67
 
68
+ # Get next version major.minor from available releases
69
+ #
70
+ # @example
71
+ # next_version("17.7.4") => "17.8"
72
+ # next_version("17.12.5") => "18.0"
73
+ # next_version("18.0.3") => nil # when no next version exists
74
+ #
75
+ # @param [String] version Current version
76
+ # @return [String, nil] Next version in major.minor format or nil if no next version exists
77
+ def next_version(version)
78
+ current_ver = Gem::Version.new(version)
79
+
80
+ # Since versions are already sorted in descending order (newest first),
81
+ # we need to reverse them to find the next version after current
82
+ next_ver = versions.reverse.find { |ver| ver > current_ver }
83
+
84
+ return nil unless next_ver
85
+
86
+ [next_ver.segments[0], next_ver.segments[1]].join('.') # major.minor
87
+ end
88
+
56
89
  private
57
90
 
58
91
  MAX_TAGS_HTTP_REQUESTS = 50
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Gitlab
4
4
  module QA
5
- VERSION = '15.2.0'
5
+ VERSION = '15.3.0'
6
6
  end
7
7
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateForProjectname
4
+ class << self
5
+ def create_pipeline
6
+ project_name = ENV.fetch('PROJECT_NAME', nil)
7
+ root_user = User.find_by_username('root')
8
+ project = Project.find_by_path(project_name)
9
+
10
+ if project
11
+ pipeline_service = Ci::CreatePipelineService.new(project, root_user, ref: project.default_branch_or_main)
12
+ pipeline = pipeline_service.execute(:api)
13
+
14
+ if pipeline
15
+ puts "Pipeline created successfully. Pipeline ID: \#{pipeline.payload.id}"
16
+ else
17
+ puts "Failed to create pipeline"
18
+ exit 1
19
+ end
20
+ else
21
+ puts "Project not found: \#{project_name}"
22
+ exit 1
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ CreateForProjectname.create_pipeline
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-qa
3
3
  version: !ruby/object:Gem::Version
4
- version: 15.2.0
4
+ version: 15.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab Quality
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-01-26 00:00:00.000000000 Z
11
+ date: 2025-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control
@@ -407,15 +407,19 @@ files:
407
407
  - lib/gitlab/qa/component/gitlab.rb
408
408
  - lib/gitlab/qa/component/jira.rb
409
409
  - lib/gitlab/qa/component/ldap.rb
410
+ - lib/gitlab/qa/component/license_ops.rb
410
411
  - lib/gitlab/qa/component/mail_hog.rb
411
412
  - lib/gitlab/qa/component/minio.rb
412
413
  - lib/gitlab/qa/component/mock_server.rb
413
414
  - lib/gitlab/qa/component/opensearch.rb
415
+ - lib/gitlab/qa/component/pipeline_ops.rb
414
416
  - lib/gitlab/qa/component/postgresql.rb
415
417
  - lib/gitlab/qa/component/praefect.rb
416
418
  - lib/gitlab/qa/component/preprod.rb
417
419
  - lib/gitlab/qa/component/production.rb
420
+ - lib/gitlab/qa/component/project_importer.rb
418
421
  - lib/gitlab/qa/component/release.rb
422
+ - lib/gitlab/qa/component/runner_ops.rb
419
423
  - lib/gitlab/qa/component/saml.rb
420
424
  - lib/gitlab/qa/component/selenoid.rb
421
425
  - lib/gitlab/qa/component/specs.rb
@@ -452,6 +456,7 @@ files:
452
456
  - lib/gitlab/qa/scenario/test/instance/relative_url.rb
453
457
  - lib/gitlab/qa/scenario/test/instance/release.rb
454
458
  - lib/gitlab/qa/scenario/test/instance/repository_storage.rb
459
+ - lib/gitlab/qa/scenario/test/instance/secure_version.rb
455
460
  - lib/gitlab/qa/scenario/test/instance/smoke.rb
456
461
  - lib/gitlab/qa/scenario/test/instance/staging.rb
457
462
  - lib/gitlab/qa/scenario/test/instance/staging_ref.rb
@@ -493,6 +498,7 @@ files:
493
498
  - lib/gitlab/qa/scenario/test/omnibus/image.rb
494
499
  - lib/gitlab/qa/scenario/test/omnibus/update_from_previous.rb
495
500
  - lib/gitlab/qa/scenario/test/omnibus/update_from_previous_ai.rb
501
+ - lib/gitlab/qa/scenario/test/omnibus/update_to_next.rb
496
502
  - lib/gitlab/qa/scenario/test/omnibus/upgrade.rb
497
503
  - lib/gitlab/qa/service/cluster_provider/base.rb
498
504
  - lib/gitlab/qa/service/cluster_provider/k3d.rb
@@ -516,6 +522,7 @@ files:
516
522
  - support/manifests/suggested_reviewer/pubsub.yaml
517
523
  - support/manifests/suggested_reviewer/recommender-bot.yaml
518
524
  - support/manifests/suggested_reviewer/recommender.yaml
525
+ - support/pipeline/create_for_projectname.rb
519
526
  - support/setup/gitlab_duo_setup.rb
520
527
  - tls_certificates/authority/ca.crt
521
528
  - tls_certificates/authority/ca.key