gitlab-qa 15.7.2 → 15.8.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: e2f5e12b0e4b1d6949c3bf2ac7b988ab0f4b42a1c9e039828da20d0611f0e284
4
- data.tar.gz: c41f28650cf5a9da55dbe1e97b6c9d4d04f08457e8d19f57982ecf193879603a
3
+ metadata.gz: 2f712be690928e97a469fb1845b7032a8064df288ea7110c98aa782a01c84a41
4
+ data.tar.gz: df0a1fc951cacee6d314fcbdc9e02b1b7e7628d8ae489807a42a1b8713bbb3b4
5
5
  SHA512:
6
- metadata.gz: afdb8a6544dd8aa320f1b076d16ce0aa6dc453e014f3bf8b7b30fd1b29a2abd0d1d99df34755ae4812e9bc1c83da7d154a7bfdc7a68894a1d2ef71b8bfacc17a
7
- data.tar.gz: 6ddd0641fe2d3cf5e5f63915854bea06b4fac93ec18d2f6651f85dbd581621aa952741d35575f4ee56b91709c383c2c12318825e8250345857ff16c4930f086a
6
+ metadata.gz: 057716e20ffafc661fdb6489dc7f23cdb57252f097b8b9c6cf55f62dadcf326140d3725010418c3121f403771779b9ebd8b7f4df290030dd6a906b372df05dc7
7
+ data.tar.gz: 660b043282d0d028ea8790c52ec10f0696c1236a15533e469b7514355bfba98f1870144c08b682b40a720464cc1153b5d0a69ca5f75a4f3651920454aabcda81
data/.rubocop_todo.yml CHANGED
@@ -45,7 +45,6 @@ Metrics/AbcSize:
45
45
  - 'lib/gitlab/qa/scenario/test/integration/gitlab_pages.rb'
46
46
  - 'lib/gitlab/qa/scenario/test/integration/integrations.rb'
47
47
  - 'lib/gitlab/qa/scenario/test/integration/jira.rb'
48
- - 'lib/gitlab/qa/scenario/test/integration/mattermost.rb'
49
48
  - 'lib/gitlab/qa/scenario/test/integration/metrics.rb'
50
49
  - 'lib/gitlab/qa/scenario/test/integration/mtls.rb'
51
50
  - 'lib/gitlab/qa/scenario/test/integration/oauth.rb'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab-qa (15.7.2)
4
+ gitlab-qa (15.8.0)
5
5
  activesupport (>= 6.1, < 8)
6
6
  ffi (~> 1.17)
7
7
  gitlab (~> 4.19)
@@ -640,34 +640,6 @@ $ export EE_LICENSE=$(cat /path/to/gitlab_license)
640
640
  $ gitlab-qa Test::Integration::OAuth EE
641
641
  ```
642
642
 
643
- ### `Test::Integration::Mattermost CE|EE|<full image address>`
644
-
645
- This tests that a GitLab instance works as expected when enabling the embedded
646
- Mattermost server (see `Test::Instance::Image` above).
647
-
648
- To run tests against the GitLab container, a GitLab QA (`gitlab/gitlab-qa`)
649
- container is spun up and tests are run from it by running the
650
- `Test::Integration::Mattermost` scenario (located under
651
- [`gitlab-org/gitlab/qa/qa/scenario/test/integration/mattermost.rb`][test-integration-mattermost]
652
- in the GitLab project).
653
-
654
- **Required environment variables:**
655
-
656
- - [For EE only] `EE_LICENSE`: A valid EE license.
657
-
658
- Example:
659
-
660
- ```shell
661
- $ gitlab-qa Test::Integration::Mattermost CE
662
-
663
- # For EE
664
- $ export EE_LICENSE=$(cat /path/to/Geo.gitlab_license)
665
-
666
- $ gitlab-qa Test::Integration::Mattermost EE
667
- ```
668
-
669
- [test-integration-mattermost]: https://gitlab.com/gitlab-org/gitlab/blob/master/qa/qa/scenario/test/integration/mattermost.rb
670
-
671
643
  ### `Test::Integration::Packages CE|EE|<full image address>`
672
644
 
673
645
  **Note: This Scenario no longer exists. See https://gitlab.com/gitlab-org/gitlab-qa/-/merge_requests/662**
@@ -1239,6 +1211,7 @@ $ export GITLAB_LICENSE_MODE="test"
1239
1211
 
1240
1212
  - Runs tests tagged with `:ai_gateway`
1241
1213
  - GitLab instance has a cloud license with either a Duo Pro add-on or Duo Enterprise add-on, and a seat is assigned to the admin user. Choose Duo Enterprise over Duo Pro when available.
1214
+ - Serves the Duo Chat and Code Suggestions feature areas. It does not boot the Duo Workflow Service (DWS); the Duo Agent Platform foundational flow runs under the dedicated `Test::Integration::DuoAgentPlatform` scenario (below).
1242
1215
 
1243
1216
  Example:
1244
1217
 
@@ -1248,6 +1221,21 @@ $ gitlab-qa Test::Integration::AiGateway EE
1248
1221
 
1249
1222
  ----
1250
1223
 
1224
+ #### `Test::Integration::DuoAgentPlatform EE|<full image address>`
1225
+
1226
+ - Runs tests tagged with `:duo_agent_platform`
1227
+ - Subclass of `Test::Integration::AiGateway`, so it inherits the same setup (cloud license + Duo add-on + assigned seat, plus the mock AI Gateway).
1228
+ - In addition, this scenario boots a mock Duo Workflow Service (DWS) container in agentic-mock mode (`duo-workflow-service`, from the same `model-gateway` image switched to the DWS gRPC server) and points GitLab at it via the `GITLAB_DUO_WORKFLOW_SERVICE_URL` / `GITLAB_DUO_WORKFLOW_SECURE` environment variables. This lets the Duo Agent Platform foundational-flow spec drive a flow end-to-end without a real LLM.
1229
+ - DWS container logs are captured to the job artifacts (`duo-workflow-service/logs/duo-workflow-service.log`) on teardown.
1230
+
1231
+ Example:
1232
+
1233
+ ```shell
1234
+ $ gitlab-qa Test::Integration::DuoAgentPlatform EE
1235
+ ```
1236
+
1237
+ ----
1238
+
1251
1239
  #### `Test::Integration::AiGatewayNoSeatAssigned EE|<full image address>`
1252
1240
 
1253
1241
  - Runs tests tagged with `:ai_gateway_no_seat_assigned`
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+
5
+ module Gitlab
6
+ module QA
7
+ module Component
8
+ # Boots the Duo Workflow Service (DWS) gRPC server in agentic-mock mode for Duo Agent
9
+ # Platform foundational-flow E2E tests. DWS ships inside the same model-gateway image as
10
+ # the AI Gateway; we reuse that image and switch the container to the DWS server via
11
+ # ENABLE_DUO_WORKFLOW_SERVICE / DISABLE_AI_GATEWAY (handled by the image's scripts/run.sh).
12
+ class DuoWorkflowService < Base
13
+ # Same artifact as the AI Gateway container, so the agentic mock model and DWS agree.
14
+ DOCKER_IMAGE = AiGateway::DOCKER_IMAGE
15
+ DOCKER_IMAGE_TAG = AiGateway::DOCKER_IMAGE_TAG
16
+
17
+ GRPC_PORT = 50052
18
+ LOG_FILE_NAME = 'duo-workflow-service.log'
19
+
20
+ def initialize
21
+ super
22
+
23
+ @secrets << AiGateway::TEST_SIGNING_KEY
24
+ @secrets << AiGateway::TEST_VALIDATION_KEY
25
+ end
26
+
27
+ def name
28
+ @name ||= 'duo-workflow-service'
29
+ end
30
+
31
+ def configure_environment(gitlab_hostname:)
32
+ @environment = {
33
+ # Switch the shared image from the AIGW FastAPI app to the DWS gRPC server.
34
+ 'ENABLE_DUO_WORKFLOW_SERVICE' => true,
35
+ 'DISABLE_AI_GATEWAY' => true,
36
+ 'PORT' => GRPC_PORT,
37
+
38
+ # Agentic mock: select the deterministic in-process mock model. With both flags set,
39
+ # DWS makes no real LLM/AIGW call; the goal's <response>/<tool_calls> directives drive it.
40
+ 'AIGW_MOCK_MODEL_RESPONSES' => true,
41
+ 'AIGW_USE_AGENTIC_MOCK' => true,
42
+
43
+ # Disable DWS auth: with auth ENABLED, DWS prefetches JWKS from GitLab + CustomersDot
44
+ # at startup and hard-fails if unreachable (bad in a sealed CI network). Disabling
45
+ # skips that prefetch and bypasses ExecuteWorkflow token validation.
46
+ 'DUO_WORKFLOW_AUTH__ENABLED' => false,
47
+
48
+ # ...but Rails still calls the GenerateToken RPC first, which needs the signing key
49
+ # present or the encode fails. So supply the DWS-prefixed self-signed keypair.
50
+ 'DUO_WORKFLOW_SELF_SIGNED_JWT__SIGNING_KEY' => AiGateway::TEST_SIGNING_KEY,
51
+ 'DUO_WORKFLOW_SELF_SIGNED_JWT__VALIDATION_KEY' => AiGateway::TEST_VALIDATION_KEY,
52
+
53
+ # Falls back to AIGW_GITLAB_URL if unset; set both for consistency.
54
+ 'DUO_WORKFLOW_AUTH__OIDC_GITLAB_URL' => "http://#{gitlab_hostname}",
55
+ 'AIGW_GITLAB_URL' => "http://#{gitlab_hostname}"
56
+ }
57
+ end
58
+
59
+ # DWS logs to stdout/stderr and writes no in-container log file (unlike the AI Gateway),
60
+ # so capture `docker logs` into the host artifacts directory before the container is
61
+ # force-removed on teardown. Without this the DWS logs are lost on removal.
62
+ def teardown
63
+ capture_logs
64
+ ensure
65
+ super
66
+ end
67
+
68
+ private
69
+
70
+ def host_log_path
71
+ File.join(Runtime::Env.host_artifacts_dir, name, 'logs', LOG_FILE_NAME)
72
+ end
73
+
74
+ def capture_logs
75
+ FileUtils.mkdir_p(File.dirname(host_log_path))
76
+ File.write(host_log_path, Docker::Command.execute("logs #{name}", mask_secrets: @secrets))
77
+ rescue Support::ShellCommand::StatusError, SystemCallError => e
78
+ Runtime::Logger.warn("Unable to capture logs from #{name}: #{e.message}")
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -14,6 +14,10 @@ module Gitlab
14
14
  @ai_gateway_name = 'ai-gateway'
15
15
  @ai_gateway_hostname = "#{@ai_gateway_name}.#{@network}"
16
16
  @ai_gateway_port = 5000
17
+ @dws_name = 'duo-workflow-service'
18
+ @dws_hostname = "#{@dws_name}.#{@network}"
19
+ @dws_port = Component::DuoWorkflowService::GRPC_PORT
20
+ @boot_duo_workflow_service = false
17
21
  @use_cloud_license = true
18
22
  @has_add_on = true
19
23
  @assign_seats = true
@@ -27,15 +31,31 @@ module Gitlab
27
31
  set_up_ai_gateway(ai_gateway, gitlab_hostname: gitlab.hostname)
28
32
 
29
33
  ai_gateway.instance do
30
- gitlab.instance do
31
- set_up_gitlab_duo(gitlab) if @use_cloud_license
32
- run_specs(gitlab, *rspec_args)
34
+ with_duo_workflow_service(gitlab_hostname: gitlab.hostname) do
35
+ gitlab.instance do
36
+ set_up_gitlab_duo(gitlab) if @use_cloud_license
37
+ run_specs(gitlab, *rspec_args)
38
+ end
33
39
  end
34
40
  end
35
41
  end
36
42
  end
37
43
  end
38
44
 
45
+ # Boots the agentic-mock Duo Workflow Service alongside the AI Gateway and runs the
46
+ # given block inside it. When @boot_duo_workflow_service is false (the default for
47
+ # AiGateway and the No*/NoLicense variants) it is a no-op passthrough, so only the
48
+ # DuoAgentPlatform scenario has the extra gRPC container.
49
+ def with_duo_workflow_service(gitlab_hostname:, &block)
50
+ return yield unless @boot_duo_workflow_service
51
+
52
+ Component::DuoWorkflowService.perform do |dws|
53
+ set_up_duo_workflow_service(dws, gitlab_hostname: gitlab_hostname)
54
+
55
+ dws.instance(&block)
56
+ end
57
+ end
58
+
39
59
  def set_up_gitlab(gitlab, release)
40
60
  gitlab.release = QA::Release.new(release)
41
61
  gitlab.name = 'gitlab'
@@ -44,6 +64,15 @@ module Gitlab
44
64
  gitlab.omnibus_gitlab_rails_env['AI_GATEWAY_URL'] = "http://#{@ai_gateway_hostname}:#{@ai_gateway_port}"
45
65
  gitlab.omnibus_gitlab_rails_env['LLM_DEBUG'] = 'true'
46
66
 
67
+ if @boot_duo_workflow_service
68
+ # Point the foundational-flow path at the in-network agentic-mock DWS, plaintext.
69
+ # These are read by config/initializers/1_settings.rb (duo_workflow.service_url /
70
+ # .secure); the value is a bare gRPC host:port (no scheme), and 'false' is parsed
71
+ # via Gitlab::Utils.to_boolean.
72
+ gitlab.omnibus_gitlab_rails_env['GITLAB_DUO_WORKFLOW_SERVICE_URL'] = "#{@dws_hostname}:#{@dws_port}"
73
+ gitlab.omnibus_gitlab_rails_env['GITLAB_DUO_WORKFLOW_SECURE'] = 'false'
74
+ end
75
+
47
76
  gitlab.set_ee_activation_code if @use_cloud_license
48
77
  end
49
78
 
@@ -55,6 +84,14 @@ module Gitlab
55
84
  ai_gateway.configure_environment(gitlab_hostname: gitlab_hostname)
56
85
  end
57
86
 
87
+ def set_up_duo_workflow_service(dws, gitlab_hostname:)
88
+ dws.name = @dws_name
89
+ dws.network = @network
90
+ dws.ports = [@dws_port]
91
+
92
+ dws.configure_environment(gitlab_hostname: gitlab_hostname)
93
+ end
94
+
58
95
  def set_up_gitlab_duo(gitlab)
59
96
  Runtime::Logger.info('Setting up Gitlab Duo on GitLab instance')
60
97
 
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module Scenario
6
+ module Test
7
+ module Integration
8
+ # Duo Agent Platform foundational-flow smoke scenario. Reuses the AiGateway scenario's
9
+ # setup (EE omnibus GitLab + mock AI Gateway) and additionally boots the agentic-mock
10
+ # Duo Workflow Service, running under its own tag so the foundational flow gets a
11
+ # dedicated omnibus job, separate from the ai-gateway job (Duo Chat / Code Suggestions).
12
+ class DuoAgentPlatform < AiGateway
13
+ def initialize
14
+ super
15
+ @tag = 'duo_agent_platform'
16
+ # Only the DAP foundational flow needs the Duo Workflow Service; the ai-gateway
17
+ # job (Duo Chat / Code Suggestions) does not, so boot DWS here rather than on the
18
+ # base AiGateway scenario.
19
+ @boot_duo_workflow_service = true
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Gitlab
4
4
  module QA
5
- VERSION = '15.7.2'
5
+ VERSION = '15.8.0'
6
6
  end
7
7
  end
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.7.2
4
+ version: 15.8.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: 2026-04-16 00:00:00.000000000 Z
11
+ date: 2026-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control
@@ -403,6 +403,7 @@ files:
403
403
  - lib/gitlab/qa/component/alpine.rb
404
404
  - lib/gitlab/qa/component/base.rb
405
405
  - lib/gitlab/qa/component/chaos.rb
406
+ - lib/gitlab/qa/component/duo_workflow_service.rb
406
407
  - lib/gitlab/qa/component/elasticsearch.rb
407
408
  - lib/gitlab/qa/component/gitaly.rb
408
409
  - lib/gitlab/qa/component/gitaly_cluster.rb
@@ -470,6 +471,7 @@ files:
470
471
  - lib/gitlab/qa/scenario/test/integration/chaos.rb
471
472
  - lib/gitlab/qa/scenario/test/integration/client_ssl.rb
472
473
  - lib/gitlab/qa/scenario/test/integration/continuous_vulnerability_scanning.rb
474
+ - lib/gitlab/qa/scenario/test/integration/duo_agent_platform.rb
473
475
  - lib/gitlab/qa/scenario/test/integration/elasticsearch.rb
474
476
  - lib/gitlab/qa/scenario/test/integration/geo.rb
475
477
  - lib/gitlab/qa/scenario/test/integration/gitaly_cluster.rb
@@ -484,7 +486,6 @@ files:
484
486
  - lib/gitlab/qa/scenario/test/integration/ldap_no_server.rb
485
487
  - lib/gitlab/qa/scenario/test/integration/ldap_no_tls.rb
486
488
  - lib/gitlab/qa/scenario/test/integration/ldap_tls.rb
487
- - lib/gitlab/qa/scenario/test/integration/mattermost.rb
488
489
  - lib/gitlab/qa/scenario/test/integration/metrics.rb
489
490
  - lib/gitlab/qa/scenario/test/integration/mtls.rb
490
491
  - lib/gitlab/qa/scenario/test/integration/opensearch.rb
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Gitlab
4
- module QA
5
- module Scenario
6
- module Test
7
- module Integration
8
- class Mattermost < Scenario::Template
9
- def perform(release, *rspec_args)
10
- Component::Gitlab.perform do |gitlab|
11
- gitlab.release = release
12
- gitlab.network = Runtime::Env.docker_network
13
-
14
- mattermost_hostname = "mattermost.#{gitlab.network}"
15
- mattermost_external_url = "http://#{mattermost_hostname}"
16
-
17
- gitlab.add_network_alias(mattermost_hostname)
18
- gitlab.omnibus_configuration << <<~OMNIBUS
19
- mattermost_external_url '#{mattermost_external_url}';
20
- OMNIBUS
21
-
22
- gitlab.instance do
23
- Component::Specs.perform do |specs|
24
- specs.suite = 'Test::Integration::Mattermost'
25
- specs.release = gitlab.release
26
- specs.network = gitlab.network
27
- specs.args = [
28
- gitlab.address,
29
- "--mattermost-address", mattermost_external_url,
30
- *rspec_args
31
- ]
32
- end
33
- end
34
- end
35
- end
36
- end
37
- end
38
- end
39
- end
40
- end
41
- end