Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
9bef5f3d98
commit
c21f4c45f9
|
|
@ -39,7 +39,7 @@ rails-production-server-boot-puma-example:
|
|||
- sed --in-place "s:/home/git/gitlab:${PWD}:" config/puma.rb
|
||||
- echo 'bind "tcp://127.0.0.1:3000"' >> config/puma.rb
|
||||
- bundle exec puma --environment production --config config/puma.rb &
|
||||
- sleep 40 # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/114124#note_1309506358
|
||||
- sleep 50 # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/114124#note_1309506358
|
||||
- retry_times_sleep 10 5 "curl http://127.0.0.1:3000"
|
||||
- kill $(jobs -p)
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ rails-production-server-boot-puma-cng:
|
|||
- curl --silent "https://gitlab.com/gitlab-org/build/CNG/-/raw/${TRIGGER_BRANCH}/gitlab-webservice/configuration/puma.rb" > config/puma.rb
|
||||
- sed --in-place "s:/srv/gitlab:${PWD}:" config/puma.rb
|
||||
- bundle exec puma --environment production --config config/puma.rb &
|
||||
- sleep 40 # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/114124#note_1309506358
|
||||
- sleep 50 # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/114124#note_1309506358
|
||||
- retry_times_sleep 10 5 "curl http://127.0.0.1:8080"
|
||||
- kill $(jobs -p)
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@ include:
|
|||
inputs:
|
||||
gem_name: "gitlab-topology-service-client"
|
||||
gem_path_prefix: "vendor/gems/"
|
||||
- local: .gitlab/ci/templates/gem.gitlab-ci.yml
|
||||
inputs:
|
||||
gem_name: "gitlab-duo-workflow-service-client"
|
||||
gem_path_prefix: "vendor/gems/"
|
||||
- local: .gitlab/ci/templates/gem.gitlab-ci.yml
|
||||
inputs:
|
||||
gem_name: "sidekiq-7.1.6"
|
||||
|
|
|
|||
11
Gemfile
11
Gemfile
|
|
@ -166,6 +166,11 @@ gem 'gitlab-topology-service-client', '~> 0.1',
|
|||
path: 'vendor/gems/gitlab-topology-service-client',
|
||||
feature_category: :cell
|
||||
|
||||
# Duo Workflow
|
||||
gem 'gitlab-duo-workflow-service-client', '~> 0.1',
|
||||
path: 'vendor/gems/gitlab-duo-workflow-service-client',
|
||||
feature_category: :duo_workflow
|
||||
|
||||
# Generate Fake data
|
||||
gem 'ffaker', '~> 2.23' # rubocop:todo Gemfile/MissingFeatureCategory
|
||||
|
||||
|
|
@ -628,7 +633,11 @@ gem 'gitaly', '~> 17.2.0', feature_category: :gitaly
|
|||
# KAS GRPC protocol definitions
|
||||
gem 'kas-grpc', '~> 0.6.0', feature_category: :deployment_management
|
||||
|
||||
gem 'grpc', '~> 1.63', feature_category: :shared
|
||||
# Lock the version before issues below are resolved:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/473169#note_2028352939
|
||||
# Or we can upgrade to a more recent version as long as we can confirm
|
||||
# that it doesn't have the same issues.
|
||||
gem 'grpc', '= 1.63.0', feature_category: :shared
|
||||
|
||||
gem 'google-protobuf', '~> 3.25', '>= 3.25.3' # rubocop:todo Gemfile/MissingFeatureCategory
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@
|
|||
{"name":"bigdecimal","version":"3.1.7","platform":"ruby","checksum":"e799b369a0005fc6d62eed7ef19139ac9bc319cc51470c637b9dcdf593600133"},
|
||||
{"name":"bindata","version":"2.4.11","platform":"ruby","checksum":"c38e0c99ffcd80c10a0a7ae6c8586d2fe26bf245cbefac90bec8764523220f6a"},
|
||||
{"name":"binding_of_caller","version":"1.0.0","platform":"ruby","checksum":"3aad25d1d538fc6e7972978f9bf512ccd992784009947c81633bea776713161d"},
|
||||
{"name":"bootsnap","version":"1.18.3","platform":"ruby","checksum":"d7b70de761e2fb1d63d21dd941b393c881c5cab5575211369cede788dfc034eb"},
|
||||
{"name":"bootsnap","version":"1.18.4","platform":"ruby","checksum":"ac4c42af397f7ee15521820198daeff545e4c360d2772c601fbdc2c07d92af55"},
|
||||
{"name":"browser","version":"5.3.1","platform":"ruby","checksum":"62745301701ff2c6c5d32d077bb12532b20be261929dcb52c6781ed0d5658b3c"},
|
||||
{"name":"builder","version":"3.2.4","platform":"ruby","checksum":"99caf08af60c8d7f3a6b004029c4c3c0bdaebced6c949165fe98f1db27fbbc10"},
|
||||
{"name":"bullet","version":"7.1.2","platform":"ruby","checksum":"429725c174cb74ca0ae99b9720bf22cab80be59ee9401805f7ecc9ac62cbb3bb"},
|
||||
|
|
|
|||
11
Gemfile.lock
11
Gemfile.lock
|
|
@ -145,6 +145,12 @@ PATH
|
|||
specs:
|
||||
diff_match_patch (0.1.0)
|
||||
|
||||
PATH
|
||||
remote: vendor/gems/gitlab-duo-workflow-service-client
|
||||
specs:
|
||||
gitlab-duo-workflow-service-client (0.1)
|
||||
grpc
|
||||
|
||||
PATH
|
||||
remote: vendor/gems/gitlab-topology-service-client
|
||||
specs:
|
||||
|
|
@ -368,7 +374,7 @@ GEM
|
|||
bindata (2.4.11)
|
||||
binding_of_caller (1.0.0)
|
||||
debug_inspector (>= 0.0.1)
|
||||
bootsnap (1.18.3)
|
||||
bootsnap (1.18.4)
|
||||
msgpack (~> 1.2)
|
||||
browser (5.3.1)
|
||||
builder (3.2.4)
|
||||
|
|
@ -2047,6 +2053,7 @@ DEPENDENCIES
|
|||
gitlab-backup-cli!
|
||||
gitlab-chronic (~> 0.10.5)
|
||||
gitlab-dangerfiles (~> 4.8.0)
|
||||
gitlab-duo-workflow-service-client (~> 0.1)!
|
||||
gitlab-experiment (~> 0.9.1)
|
||||
gitlab-fog-azure-rm (~> 2.0.1)
|
||||
gitlab-glfm-markdown (~> 0.0.17)
|
||||
|
|
@ -2099,7 +2106,7 @@ DEPENDENCIES
|
|||
graphlyte (~> 1.0.0)
|
||||
graphql (~> 2.3.5)
|
||||
graphql-docs (~> 5.0.0)
|
||||
grpc (~> 1.63)
|
||||
grpc (= 1.63.0)
|
||||
gssapi (~> 1.3.1)
|
||||
guard-rspec
|
||||
haml_lint (~> 0.58)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,9 @@ module OauthApplications
|
|||
end
|
||||
|
||||
def load_scopes
|
||||
@scopes ||= Doorkeeper.configuration.scopes
|
||||
@scopes ||= Doorkeeper::OAuth::Scopes.from_array(
|
||||
Doorkeeper.configuration.scopes.to_a - [::Gitlab::Auth::AI_WORKFLOW.to_s]
|
||||
)
|
||||
end
|
||||
|
||||
def permitted_params
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ module WikiActions
|
|||
|
||||
before_action do
|
||||
push_frontend_feature_flag(:preserve_markdown, container)
|
||||
push_force_frontend_feature_flag(:glql_integration, container&.glql_integration_feature_flag_enabled?)
|
||||
end
|
||||
|
||||
before_action only: [:show, :edit, :update] do
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ module Groups
|
|||
push_force_frontend_feature_flag(:namespace_level_work_items, namespace_work_items_enabled?)
|
||||
push_force_frontend_feature_flag(:create_group_level_work_items,
|
||||
group&.create_group_level_work_items_feature_flag_enabled?)
|
||||
push_force_frontend_feature_flag(:glql_integration, group&.glql_integration_feature_flag_enabled?)
|
||||
end
|
||||
before_action :handle_new_work_item_path, only: [:show]
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
push_frontend_feature_flag(:issues_list_drawer, project)
|
||||
push_frontend_feature_flag(:notifications_todos_buttons, current_user)
|
||||
push_frontend_feature_flag(:comment_tooltips, current_user)
|
||||
push_force_frontend_feature_flag(:glql_integration, project&.glql_integration_feature_flag_enabled?)
|
||||
end
|
||||
|
||||
before_action only: [:index, :show] do
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@ class Projects::MergeRequests::ApplicationController < Projects::ApplicationCont
|
|||
|
||||
feature_category :code_review_workflow
|
||||
|
||||
before_action do
|
||||
push_force_frontend_feature_flag(:glql_integration, project&.glql_integration_feature_flag_enabled?)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Normally the methods with `check_(\w+)_available!` pattern are
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ class Projects::WorkItemsController < Projects::ApplicationController
|
|||
push_force_frontend_feature_flag(:work_items, project&.work_items_feature_flag_enabled?)
|
||||
push_force_frontend_feature_flag(:work_items_beta, project&.work_items_beta_feature_flag_enabled?)
|
||||
push_force_frontend_feature_flag(:work_items_alpha, project&.work_items_alpha_feature_flag_enabled?)
|
||||
push_force_frontend_feature_flag(:glql_integration, project&.glql_integration_feature_flag_enabled?)
|
||||
push_frontend_feature_flag(:namespace_level_work_items, project&.group)
|
||||
push_frontend_feature_flag(:comment_tooltips)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -952,6 +952,10 @@ class Group < Namespace
|
|||
feature_flag_enabled_for_self_or_ancestor?(:work_items_rolledup_dates)
|
||||
end
|
||||
|
||||
def glql_integration_feature_flag_enabled?
|
||||
feature_flag_enabled_for_self_or_ancestor?(:glql_integration)
|
||||
end
|
||||
|
||||
# Note: this method is overridden in EE to check the work_item_epics feature flag which also enables this feature
|
||||
def namespace_work_items_enabled?(_user = nil)
|
||||
::Feature.enabled?(:namespace_level_work_items, self, type: :development)
|
||||
|
|
|
|||
|
|
@ -33,6 +33,10 @@ class MergeRequestsClosingIssues < ApplicationRecord
|
|||
preload(merge_request: [:target_project, :author])
|
||||
end
|
||||
|
||||
def preload_issue
|
||||
preload(:issue)
|
||||
end
|
||||
|
||||
def count_for_collection(ids, current_user)
|
||||
closing_merge_requests(ids, current_user).group(:issue_id).pluck('issue_id', Arel.sql('COUNT(*) as count'))
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3273,6 +3273,10 @@ class Project < ApplicationRecord
|
|||
group&.work_items_alpha_feature_flag_enabled? || Feature.enabled?(:work_items_alpha)
|
||||
end
|
||||
|
||||
def glql_integration_feature_flag_enabled?
|
||||
group&.glql_integration_feature_flag_enabled? || Feature.enabled?(:glql_integration, self)
|
||||
end
|
||||
|
||||
def enqueue_record_project_target_platforms
|
||||
return unless Gitlab.com?
|
||||
|
||||
|
|
|
|||
|
|
@ -53,27 +53,49 @@ module MergeRequests
|
|||
def close_issues(merge_request)
|
||||
return unless merge_request.target_branch == project.default_branch
|
||||
|
||||
closed_issues = merge_request.visible_closing_issues_for(current_user)
|
||||
|
||||
closed_issues.each do |issue|
|
||||
# We are intentionally only closing Issues asynchronously (excluding ExternalIssues)
|
||||
# as the worker only supports finding an Issue. We are also only experiencing
|
||||
# SQL timeouts when closing an Issue.
|
||||
if issue.is_a?(Issue)
|
||||
next unless issue.autoclose_by_merged_closing_merge_request?
|
||||
|
||||
MergeRequests::CloseIssueWorker.perform_async(
|
||||
project.id,
|
||||
current_user.id,
|
||||
issue.id,
|
||||
merge_request.id
|
||||
)
|
||||
else
|
||||
Issues::CloseService.new(container: project, current_user: current_user).execute(issue, commit: merge_request)
|
||||
if merge_request.target_project.has_external_issue_tracker?
|
||||
merge_request.closes_issues(current_user).each do |issue|
|
||||
close_issue(issue, merge_request)
|
||||
end
|
||||
else
|
||||
merge_request.merge_requests_closing_issues.preload_issue.find_each(batch_size: 100) do |closing_issue| # rubocop:disable CodeReuse/ActiveRecord -- Would require exact redefinition of the method
|
||||
close_issue(closing_issue.issue, merge_request, !closing_issue.from_mr_description)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def close_issue(issue, merge_request, skip_authorization = false)
|
||||
# We are intentionally only closing Issues asynchronously (excluding ExternalIssues)
|
||||
# as the worker only supports finding an Issue. We are also only experiencing
|
||||
# SQL timeouts when closing an Issue.
|
||||
if issue.is_a?(Issue)
|
||||
# Doing this check here only to save a scheduled worker. The worker will also do this policy check.
|
||||
return if !skip_authorization && !current_user.can?(:update_issue, issue)
|
||||
return unless issue.autoclose_by_merged_closing_merge_request?
|
||||
|
||||
MergeRequests::CloseIssueWorker.perform_async(
|
||||
*close_worker_arguments(issue, merge_request, skip_authorization)
|
||||
)
|
||||
else
|
||||
Issues::CloseService.new(container: project, current_user: current_user).execute(issue, commit: merge_request)
|
||||
end
|
||||
end
|
||||
|
||||
def close_worker_arguments(issue, merge_request, skip_authorization)
|
||||
worker_arguments = [
|
||||
project.id,
|
||||
current_user.id,
|
||||
issue.id,
|
||||
merge_request.id
|
||||
]
|
||||
|
||||
if Feature.enabled?(:mr_merge_skips_close_issue_authorization, project)
|
||||
worker_arguments << { skip_authorization: skip_authorization }
|
||||
end
|
||||
|
||||
worker_arguments
|
||||
end
|
||||
|
||||
def delete_non_latest_diffs(merge_request)
|
||||
DeleteNonLatestDiffsService.new(merge_request).execute
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"description": "Duo Workflow application settings",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"duo_workflow_oauth_application_id": {
|
||||
"type": "integer",
|
||||
"description": "oauth application id for duo workflow"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@ module MergeRequests
|
|||
# This worker only accepts ID of an Issue. We are intentionally using this
|
||||
# worker to close Issues asynchronously as we only experience SQL timeouts
|
||||
# when closing an Issue.
|
||||
def perform(project_id, user_id, issue_id, merge_request_id)
|
||||
def perform(project_id, user_id, issue_id, merge_request_id, params = {})
|
||||
project = Project.find_by_id(project_id)
|
||||
|
||||
unless project
|
||||
|
|
@ -46,7 +46,11 @@ module MergeRequests
|
|||
|
||||
Issues::CloseService
|
||||
.new(container: project, current_user: user)
|
||||
.execute(issue, commit: merge_request)
|
||||
.execute(
|
||||
issue,
|
||||
commit: merge_request,
|
||||
skip_authorization: !!params.with_indifferent_access[:skip_authorization]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
name: mr_merge_skips_close_issue_authorization
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/471849
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/160914
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/475108
|
||||
milestone: '17.3'
|
||||
group: group::project management
|
||||
type: beta
|
||||
default_enabled: false
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: add_validation_for_push_rules
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121030
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/411901
|
||||
milestone: '16.1'
|
||||
type: development
|
||||
group: group::source code
|
||||
default_enabled: true
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
name: glql_integration
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/161942
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/476990
|
||||
feature_issue_url: https://gitlab.com/groups/gitlab-org/-/epics/14767
|
||||
milestone: '17.3'
|
||||
type: development
|
||||
group: group::knowledge
|
||||
default_enabled: false
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddDuoWorkflowToApplicationSettings < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.3'
|
||||
|
||||
def change
|
||||
add_column :application_settings, :duo_workflow, :jsonb, default: {}, null: true
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddDuoWorkflowHashConstraintToApplicationSetting < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.3'
|
||||
disable_ddl_transaction!
|
||||
|
||||
CONSTRAINT_NAME = 'check_application_settings_duo_workflow_is_hash'
|
||||
def up
|
||||
add_check_constraint(
|
||||
:application_settings,
|
||||
"(jsonb_typeof(duo_workflow) = 'object')",
|
||||
CONSTRAINT_NAME
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
remove_check_constraint :application_settings, CONSTRAINT_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
5c547fdc271a155354843e424c47ebe3e643688d5e013a96501edf051baf63b3
|
||||
|
|
@ -0,0 +1 @@
|
|||
902245f1d45510a06f5bba17841cfff0a6c7391beeef2e46638ffed5353a7935
|
||||
|
|
@ -5882,6 +5882,7 @@ CREATE TABLE application_settings (
|
|||
code_suggestions_api_rate_limit integer DEFAULT 60 NOT NULL,
|
||||
ai_action_api_rate_limit integer DEFAULT 160 NOT NULL,
|
||||
require_personal_access_token_expiry boolean DEFAULT true NOT NULL,
|
||||
duo_workflow jsonb DEFAULT '{}'::jsonb,
|
||||
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
|
||||
CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)),
|
||||
CONSTRAINT app_settings_ext_pipeline_validation_service_url_text_limit CHECK ((char_length(external_pipeline_validation_service_url) <= 255)),
|
||||
|
|
@ -5932,6 +5933,7 @@ CREATE TABLE application_settings (
|
|||
CONSTRAINT check_app_settings_sentry_clientside_traces_sample_rate_range CHECK (((sentry_clientside_traces_sample_rate >= (0)::double precision) AND (sentry_clientside_traces_sample_rate <= (1)::double precision))),
|
||||
CONSTRAINT check_application_settings_clickhouse_is_hash CHECK ((jsonb_typeof(clickhouse) = 'object'::text)),
|
||||
CONSTRAINT check_application_settings_code_creation_is_hash CHECK ((jsonb_typeof(code_creation) = 'object'::text)),
|
||||
CONSTRAINT check_application_settings_duo_workflow_is_hash CHECK ((jsonb_typeof(duo_workflow) = 'object'::text)),
|
||||
CONSTRAINT check_application_settings_importers_is_hash CHECK ((jsonb_typeof(importers) = 'object'::text)),
|
||||
CONSTRAINT check_application_settings_package_registry_is_hash CHECK ((jsonb_typeof(package_registry) = 'object'::text)),
|
||||
CONSTRAINT check_application_settings_rate_limits_is_hash CHECK ((jsonb_typeof(rate_limits) = 'object'::text)),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,181 @@
|
|||
---
|
||||
stage: AI-powered
|
||||
group: AI Framework
|
||||
info: Any user with at least the Maintainer role can merge updates to this content. For details, see https://docs.gitlab.com/ee/development/development_processes.html#development-guidelines-review.
|
||||
---
|
||||
|
||||
# Setting up local development for Duo Workflow
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker
|
||||
- NOTE: We aren't allowed to use [Docker Desktop](https://handbook.gitlab.com/handbook/tools-and-tips/mac/#docker-desktop).
|
||||
- [AI Gateway](../ai_features/index.md)
|
||||
|
||||
## Setting up Duo Workflow
|
||||
|
||||
### Set up Duo Workflow Service
|
||||
|
||||
1. Clone the [Duo Workflow Service](https://gitlab.com/gitlab-org/duo-workflow/duo-workflow-service)
|
||||
|
||||
```shell
|
||||
git clone git@gitlab.com:gitlab-org/duo-workflow/duo-workflow-service.git
|
||||
```
|
||||
|
||||
1. Navigate to the Duo Workflow Service directory
|
||||
|
||||
1. Install dependencies
|
||||
|
||||
```shell
|
||||
poetry install
|
||||
```
|
||||
|
||||
1. Copy the example env file in the Service repo. Enter your Anthropic API key.
|
||||
|
||||
```shell
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
```dotenv
|
||||
ANTHROPIC_API_KEY=<YOUR_API_KEY>
|
||||
```
|
||||
|
||||
You can disable auth for local development by setting DUO_WORKFLOW_AUTH__ENABLED=false in `.env`
|
||||
|
||||
1. Run Duo Workflow Service
|
||||
|
||||
```shell
|
||||
poetry run python -m duo_workflow_service.server
|
||||
```
|
||||
|
||||
1. In your local GitLab instance enable the `duo_workflow` feature flag from the rails console:
|
||||
|
||||
```ruby
|
||||
Feature.enable(:duo_workflow)
|
||||
```
|
||||
|
||||
1. Create a [personal access token](../../user/profile/personal_access_tokens.md) in your local GitLab instance with `api` scope
|
||||
|
||||
1. Generate a workflow ID. Replace `$GITLAB_TOKEN` with a PAT from your local GitLab instance.
|
||||
|
||||
```shell
|
||||
curl POST --verbose \
|
||||
--header "Authorization: Bearer $GITLAB_TOKEN" \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data '{
|
||||
"project_id": "7"
|
||||
}' \
|
||||
http://<GDK_HOST>:3000/api/v4/ai/duo_workflows/workflows
|
||||
```
|
||||
|
||||
### Set up the Duo Workflow Executor
|
||||
|
||||
1. Clone the [Duo Workflow Executor](https://gitlab.com/gitlab-org/duo-workflow/duo-workflow-executor)
|
||||
|
||||
1. Navigate to the Duo Workflow Executor directory
|
||||
|
||||
1. Create a Dockerfile
|
||||
|
||||
```Dockerfile
|
||||
FROM alpine
|
||||
|
||||
RUN apk add go busybox-extras git bash
|
||||
```
|
||||
|
||||
1. Run the executor with your GitLab token and workflow ID. Below is an example prompt goal
|
||||
|
||||
```shell
|
||||
make && \
|
||||
./bin/duo-workflow-executor \
|
||||
--goal='Can you fix the pipeline for the Merge request: 1 in the project 60003631.
|
||||
You will have to clone the repository if you need to fix files. You can use the `run_command` tool to do so."
|
||||
Please also checkout the right branch before making the changes.
|
||||
You can fetch the repository name from the `get_project` tool.
|
||||
|
||||
Once you have fixed the pipeline please push the code to the same branch.' \
|
||||
--workflow-id=$WORKFLOW_ID \
|
||||
--token=$GITLAB_TOKEN \
|
||||
--base-url="http://<GDK_HOST>:3000" \
|
||||
--realm="saas" \
|
||||
--userID="777"
|
||||
```
|
||||
|
||||
You can also find more instructions to [run the executor locally in a Docker container](https://gitlab.com/gitlab-org/duo-workflow/duo-workflow-executor/-/blob/9dbe47ce3c61e1274af184f595ae5af1417d7a39/README.md).
|
||||
|
||||
1. Verify that the checkpoints for workflow have been created
|
||||
|
||||
```shell
|
||||
curl --verbose \
|
||||
--header "Authorization: Bearer $GITLAB_TOKEN" \
|
||||
http://<GDK_HOST>/api/v4/ai/duo_workflows/workflows/<workflow_id>/checkpoints
|
||||
```
|
||||
|
||||
## Optional: Testing the Auth flow via GitLab
|
||||
|
||||
Please note that this work is in progress and only half-implemented. These instructions are left here in case they are useful for testing purposes.
|
||||
|
||||
1. Generate a Cloud Connector token and grab your GitLab instance ID from the rails console
|
||||
|
||||
```shell
|
||||
cd <GDK-root>
|
||||
gdk start
|
||||
gdk rails console
|
||||
```
|
||||
|
||||
To grab your Cloud Connector token:
|
||||
|
||||
```ruby
|
||||
::Gitlab::CloudConnector::SelfIssuedToken.new(
|
||||
audience: "gitlab-duo-workflow-service",
|
||||
subject: Gitlab::CurrentSettings.uuid,
|
||||
scopes: ["duo_workflow_generate_token"]).encoded
|
||||
```
|
||||
|
||||
To grab your GitLab instance ID:
|
||||
|
||||
<!-- markdownlint-disable MD044 -->
|
||||
```ruby
|
||||
Gitlab::CurrentSettings.uuid
|
||||
```
|
||||
<!-- markdownlint-enable MD044 -->
|
||||
|
||||
1. Navigate to the [client.py file](https://gitlab.com/gitlab-org/duo-workflow/duo-workflow-service/-/blob/83b62846cad3cfb633c31c0c9aa02e4535f44941/duo_workflow_service/client.py#L32-38) and replace the values in this file with the token and instance ID from the previous step.
|
||||
|
||||
```python
|
||||
token = "<set-your-local-gdk-token>"
|
||||
|
||||
# To get your gitlab_instance_id, run in gdk rails console:
|
||||
# ```
|
||||
# puts Gitlab::CurrentSettings.uuid
|
||||
# ```
|
||||
gitlab_instance_id = "<set-your-local-gdk-instance-id>"
|
||||
```
|
||||
|
||||
1. Update the metadata in the [client.py file](https://gitlab.com/gitlab-org/duo-workflow/duo-workflow-service/-/blob/83b62846cad3cfb633c31c0c9aa02e4535f44941/duo_workflow_service/client.py#L40-46) to the following:
|
||||
|
||||
```python
|
||||
metadata = [
|
||||
("authorization", f"Bearer {token}"),
|
||||
("x-gitlab-authentication-type", "oidc"),
|
||||
("x-gitlab-realm", "saas"),
|
||||
("x-gitlab-instance-id", gitlab_instance_id),
|
||||
("x-gitlab-global-user-id", "777"),
|
||||
]
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Issues connecting to 50052 port
|
||||
|
||||
JAMF may be listening on the `50052` port which will conflict with Duo Workflow Service.
|
||||
|
||||
```shell
|
||||
$ sudo lsof -i -P | grep LISTEN | grep :50052
|
||||
jamfRemot <redacted> root 11u IPv4 <redacted> 0t0 TCP localhost:50052 (LISTEN)
|
||||
```
|
||||
|
||||
To work around this,run the serveron 50053 with:
|
||||
|
||||
```shell
|
||||
PORT=50053 poetry run duo-workflow-service
|
||||
```
|
||||
|
|
@ -24,6 +24,53 @@ Download the extension from the [JetBrains Plugin Marketplace](https://plugins.j
|
|||
|
||||
Instructions for getting started can be found in the project README under [setup](https://gitlab.com/gitlab-org/editor-extensions/gitlab-jetbrains-plugin#setup).
|
||||
|
||||
### Add a custom certificate for Code Suggestions
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/editor-extensions/gitlab-jetbrains-plugin/-/issues/561) in GitLab Duo 2.10.0.
|
||||
|
||||
GitLab Duo attempts to detect [trusted root certificates](https://www.jetbrains.com/help/idea/ssl-certificates.html)
|
||||
without configuration on your part. If needed, you can configure your JetBrains IDE to allow the GitLab Duo plugin
|
||||
to connect to your GitLab instance using a custom certificate.
|
||||
|
||||
To use a custom certificate:
|
||||
|
||||
1. In your IDE, on the top bar, select your IDE name, then select **Settings**.
|
||||
1. On the left sidebar, select **Tools > GitLab Duo**.
|
||||
1. Under **Connection**, enter the **URL to GitLab instance**.
|
||||
1. To verify your connection, select **Verify setup**.
|
||||
1. Select **OK**.
|
||||
|
||||
If your IDE detects a non-trusted certificate:
|
||||
|
||||
1. The GitLab Duo plugin displays a confirmation dialog.
|
||||
1. Review the certificate details shown.
|
||||
- Confirm that when you connect to GitLab in your browser, you see the same certificate details.
|
||||
1. If the certificate matches your expectations, select **Accept**.
|
||||
|
||||
To review certificates you've already accepted:
|
||||
|
||||
1. In your IDE, on the top bar, select your IDE name, then select **Settings**.
|
||||
1. On the left sidebar, select **Tools > Server Certificates**.
|
||||
1. Select [**Server Certificates**](https://www.jetbrains.com/help/idea/settings-tools-server-certificates.html).
|
||||
1. Select a certificate to view it.
|
||||
|
||||
### Allow a custom certificate for Code Suggestions
|
||||
|
||||
GitLab Duo attempts to pass custom certificate details to the GitLab Language Server process without configuration on your part.
|
||||
|
||||
To enforce a specific custom certificate:
|
||||
|
||||
1. In your IDE, on the top bar, select your IDE name, then select **Settings**.
|
||||
1. On the left sidebar, select **Tools > GitLab Duo**.
|
||||
1. Under **Advanced**, select **GitLab Language Server**.
|
||||
1. Under **GitLab Language Server**, select **HTTP Agent Options**.
|
||||
1. Under **HTTP Agent Options**:
|
||||
1. For **Certificate authority (CA)**, enter the full path to your server's certificate authority.
|
||||
1. Optional. In **Certificate**, enter the full file path to your client certificate.
|
||||
1. Optional. In **Certificate key**, enter the full file path to your private key.
|
||||
1. Insert the full path to the PEM-encoded certificate authority.
|
||||
1. Select **OK**.
|
||||
|
||||
### Integrate with 1Password CLI
|
||||
|
||||
DETAILS:
|
||||
|
|
@ -61,6 +108,25 @@ From the IDE:
|
|||
1. Optional. To verify your credentials, select **Verify setup**.
|
||||
1. Select **OK**.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Error: `unable to find valid certification path to requested target`
|
||||
|
||||
The GitLab Duo plugin verifies TLS certificate information before connecting to your GitLab instance.
|
||||
If necessary you can [allow a custom certificate](#allow-a-custom-certificate-for-code-suggestions).
|
||||
|
||||
### Error: `Failed to check token`
|
||||
|
||||
This error occurs when the provided connection instance URL and authentication token passed through to the
|
||||
GitLab Language Server process are invalid. To re-enable code suggestions:
|
||||
|
||||
1. In your IDE, on the top bar, select your IDE name, then select **Settings**.
|
||||
1. On the left sidebar, select **Tools > GitLab Duo**.
|
||||
1. Under **Connection**, select **Verify setup**.
|
||||
1. Update your **Connection** details as needed.
|
||||
1. Select **Verify setup**, and confirm that authentication succeeds.
|
||||
1. Select **OK**.
|
||||
|
||||
## Report issues with the extension
|
||||
|
||||
Report any issues, bugs, or feature requests in the
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ module Gitlab
|
|||
# Scopes for Duo
|
||||
AI_FEATURES = :ai_features
|
||||
AI_FEATURES_SCOPES = [AI_FEATURES].freeze
|
||||
AI_WORKFLOW = :ai_workflows
|
||||
AI_WORKFLOW_SCOPES = [AI_WORKFLOW].freeze
|
||||
|
||||
PROFILE_SCOPE = :profile
|
||||
EMAIL_SCOPE = :email
|
||||
|
|
@ -415,7 +417,7 @@ module Gitlab
|
|||
|
||||
# Other available scopes
|
||||
def optional_scopes
|
||||
all_available_scopes + OPENID_SCOPES + PROFILE_SCOPES - DEFAULT_SCOPES
|
||||
all_available_scopes + OPENID_SCOPES + PROFILE_SCOPES - DEFAULT_SCOPES + AI_WORKFLOW_SCOPES
|
||||
end
|
||||
|
||||
def registry_scopes
|
||||
|
|
@ -448,7 +450,12 @@ module Gitlab
|
|||
end
|
||||
|
||||
def unavailable_scopes_for_resource(resource)
|
||||
unavailable_observability_scopes_for_resource(resource)
|
||||
unavailable_ai_features_scopes +
|
||||
unavailable_observability_scopes_for_resource(resource)
|
||||
end
|
||||
|
||||
def unavailable_ai_features_scopes
|
||||
AI_WORKFLOW_SCOPES
|
||||
end
|
||||
|
||||
def unavailable_observability_scopes_for_resource(resource)
|
||||
|
|
|
|||
|
|
@ -4993,7 +4993,7 @@ msgstr ""
|
|||
msgid "AiImpactAnalytics|Code Suggestions usage"
|
||||
msgstr ""
|
||||
|
||||
msgid "AiImpactAnalytics|Duo Pro seats: Assigned and used"
|
||||
msgid "AiImpactAnalytics|Duo seats: Assigned and used"
|
||||
msgstr ""
|
||||
|
||||
msgid "AiImpactAnalytics|Monthly user engagement with AI Code Suggestions. Percentage ratio calculated as monthly unique Code Suggestions users / total monthly unique code contributors."
|
||||
|
|
|
|||
|
|
@ -57,8 +57,9 @@ task :delete_projects, [:dry_run] do |_, args|
|
|||
end
|
||||
|
||||
desc "Deletes test users"
|
||||
task :delete_test_users, [:delete_before, :dry_run, :exclude_users] do |_, args|
|
||||
QA::Tools::DeleteTestUsers.new(args).run
|
||||
task :delete_test_users, [:dry_run, :exclude_users] do |_, args|
|
||||
args.with_defaults(dry_run: false, exclude_users: nil)
|
||||
QA::Tools::DeleteTestUsers.new(dry_run: args[:dry_run], exclude_users: args[:exclude_users]).run
|
||||
end
|
||||
|
||||
desc "Deletes snippets"
|
||||
|
|
|
|||
|
|
@ -58,27 +58,46 @@ module QA
|
|||
# Deletes a list of resources
|
||||
#
|
||||
# @param [Array<Hash>] resources
|
||||
# @param [Boolean] wait until the end of the script to verify deletions. used for deletions that take a long time
|
||||
# @param [Hash] API call options
|
||||
# @return [Array<String, Hash>] results
|
||||
def delete_resources(resources)
|
||||
def delete_resources(resources, delayed_verification = false, **options)
|
||||
logger.info("Deleting #{resources.length} #{@type}s...\n")
|
||||
|
||||
resources.filter_map do |resource|
|
||||
unverified_deletions = []
|
||||
results = []
|
||||
|
||||
resources.each do |resource|
|
||||
path = resource_path(resource)
|
||||
logger.info("Deleting #{@type} #{path}...")
|
||||
|
||||
delete_resource(resource)
|
||||
result = delete_resource(resource, delayed_verification, **options)
|
||||
|
||||
if result.is_a?(Array)
|
||||
results.append(result)
|
||||
else
|
||||
unverified_deletions << result
|
||||
end
|
||||
end
|
||||
|
||||
results.concat(verify_deletions(unverified_deletions)) unless unverified_deletions.empty?
|
||||
|
||||
results
|
||||
end
|
||||
|
||||
# Deletes a given resource
|
||||
#
|
||||
# @param [<Hash>] resource
|
||||
# @param [Boolean] wait until the end of the script to verify deletion
|
||||
# @param [Hash] API call options
|
||||
# @return [Array<String, Hash>] results
|
||||
def delete_resource(resource)
|
||||
def delete_resource(resource, delayed_verification = false, **options)
|
||||
# If delayed deletion is not enabled, resource will be permanently deleted
|
||||
response = delete(resource_request(resource))
|
||||
response = delete(resource_request(resource, **options))
|
||||
|
||||
if success?(response&.code) || response.include?("already marked for deletion")
|
||||
return resource if delayed_verification
|
||||
|
||||
wait_for_resource_deletion(resource)
|
||||
|
||||
return log_permanent_deletion(resource) if permanently_deleted?(resource)
|
||||
|
|
@ -300,12 +319,27 @@ module QA
|
|||
personal_access_token: token)
|
||||
end
|
||||
|
||||
def verify_deletions(unverified_deletions)
|
||||
logger.info('Verifying deletions...')
|
||||
|
||||
unverified_deletions.filter_map do |resource|
|
||||
wait_for_resource_deletion(resource, permanent: true)
|
||||
response = get(resource_request(resource))
|
||||
|
||||
if response&.code == HTTP_STATUS_NOT_FOUND
|
||||
log_permanent_deletion(resource)
|
||||
else
|
||||
log_failure(resource, response)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Wait for resource to be deleted (resource cannot be found or resource has been marked for deletion)
|
||||
#
|
||||
# @param resource [Hash] Resource to wait for deletion for
|
||||
# @return [Boolean] Whether the resource was deleted
|
||||
def wait_for_resource_deletion(resource, permanent = false)
|
||||
wait_until(max_duration: 60, sleep_interval: 1, raise_on_failure: false) do
|
||||
wait_until(max_duration: 160, sleep_interval: 1, raise_on_failure: false) do
|
||||
response = get(resource_request(resource))
|
||||
deleted = response&.code == HTTP_STATUS_NOT_FOUND
|
||||
|
||||
|
|
|
|||
|
|
@ -1,86 +1,69 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# This script deletes users with a username starting with "qa-user-"
|
||||
# - Specify `delete_before` to delete only keys that were created before the given date (default: yesterday)
|
||||
# - If `dry_run` is true the script will list the users to be deleted by username, but it won't delete them
|
||||
# This script deletes users with a username starting with "qa-user-" or "test-user-"
|
||||
# - If `dry_run` is true the script will list the users to be deleted, but it won't delete them
|
||||
# - Specify `exclude_users` as a comma-separated list of usernames to not delete.
|
||||
#
|
||||
# Required environment variables: GITLAB_QA_ADMIN_ACCESS_TOKEN and GITLAB_ADDRESS
|
||||
|
||||
# Required environment variables: GITLAB_QA_ADMIN_ACCESS_TOKEN, GITLAB_QA_ACCESS_TOKEN, and GITLAB_ADDRESS
|
||||
# - GITLAB_QA_ADMIN_ACCESS_TOKEN must have admin API access
|
||||
|
||||
# Optional environment variables: DELETE_BEFORE (default: 1 day ago)
|
||||
# - Set DELETE_BEFORE to only delete users that were created before a given date, otherwise defaults to 1 day ago
|
||||
|
||||
# Run `rake delete_test_users`
|
||||
|
||||
module QA
|
||||
module Tools
|
||||
class DeleteTestUsers
|
||||
include Support::API
|
||||
class DeleteTestUsers < DeleteResourceBase
|
||||
EXCLUDE_USERS = %w[gitlab-qa gitlab-qa-user-for-ai].freeze
|
||||
|
||||
ITEMS_PER_PAGE = '100'
|
||||
EXCLUDE_USERS = %w[qa-user-abc123].freeze
|
||||
FALSY_VALUES = %w[false no 0].freeze
|
||||
def initialize(dry_run: false, exclude_users: nil)
|
||||
super(dry_run: dry_run)
|
||||
|
||||
def initialize(delete_before: (Date.today - 1).to_s, dry_run: 'false', exclude_users: nil)
|
||||
raise ArgumentError, "Please provide GITLAB_ADDRESS" unless ENV['GITLAB_ADDRESS']
|
||||
raise ArgumentError, "Please provide GITLAB_QA_ADMIN_ACCESS_TOKEN" unless ENV['GITLAB_QA_ADMIN_ACCESS_TOKEN']
|
||||
|
||||
@api_client = Runtime::API::Client.new(ENV['GITLAB_ADDRESS'], personal_access_token: ENV['GITLAB_QA_ADMIN_ACCESS_TOKEN'])
|
||||
@dry_run = FALSY_VALUES.exclude?(dry_run.to_s.downcase)
|
||||
@delete_before = Date.parse(delete_before)
|
||||
@page_no = '1'
|
||||
@exclude_users = Array(exclude_users.to_s.split(',')) + EXCLUDE_USERS
|
||||
@type = 'user'
|
||||
end
|
||||
|
||||
def run
|
||||
puts "Deleting users with a username starting with 'qa-user-' or 'test-user-' created before #{@delete_before}..."
|
||||
users = fetch_test_users
|
||||
|
||||
while page_no.present?
|
||||
users = fetch_test_users
|
||||
results = delete_test_users(users)
|
||||
|
||||
delete_test_users(users) if users.present?
|
||||
end
|
||||
|
||||
puts "\nDone"
|
||||
log_results(results)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :dry_run, :page_no
|
||||
alias_method :dry_run?, :dry_run
|
||||
|
||||
def fetch_test_users
|
||||
puts "Fetching QA test users from page #{page_no}..."
|
||||
users = fetch_resources("/users")
|
||||
|
||||
response = get Runtime::API::Request.new(@api_client, "/users", page: page_no, per_page: ITEMS_PER_PAGE).url
|
||||
|
||||
# When we reach the last page, the x-next-page header is a blank string
|
||||
@page_no = response.headers[:x_next_page].to_s
|
||||
|
||||
if @page_no.to_i > 1000
|
||||
puts "Finishing early to avoid timing out the CI job"
|
||||
exit
|
||||
end
|
||||
|
||||
JSON.parse(response.body).select do |user|
|
||||
user['username'].start_with?('qa-user-', 'test-user-') \
|
||||
&& (user['name'] == 'QA Tests' || user['name'].start_with?('QA User')) \
|
||||
&& @exclude_users.exclude?(user['username']) \
|
||||
&& Date.parse(user.fetch('created_at', Date.today.to_s)) < @delete_before
|
||||
users.select do |user|
|
||||
user[:username].start_with?('qa-user-', 'test-user-') \
|
||||
&& user[:name].start_with?('QA User', 'QA Test') \
|
||||
&& @exclude_users.exclude?(user[:username]) \
|
||||
&& Date.parse(user.fetch(:created_at, Date.today.to_s)) < @delete_before
|
||||
end
|
||||
end
|
||||
|
||||
def delete_test_users(users)
|
||||
usernames = users.map { |user| user['username'] }.join(', ')
|
||||
if dry_run?
|
||||
puts "Dry run: found users with usernames #{usernames}"
|
||||
|
||||
if @dry_run
|
||||
log_dry_run_output(users)
|
||||
return
|
||||
end
|
||||
|
||||
puts "Deleting #{users.length} users with usernames #{usernames}..."
|
||||
users.each do |user|
|
||||
delete_response = delete Runtime::API::Request.new(@api_client, "/users/#{user['id']}", hard_delete: 'true').url
|
||||
dot_or_f = delete_response.code == 204 ? "\e[32m.\e[0m" : "\e[31mF\e[0m"
|
||||
print dot_or_f
|
||||
if users.empty?
|
||||
logger.info("No users found\n")
|
||||
return
|
||||
end
|
||||
print "\n"
|
||||
|
||||
delete_resources(users, true, hard_delete: 'true')
|
||||
end
|
||||
|
||||
def resource_request(user, **options)
|
||||
Runtime::API::Request.new(@api_client, "/users/#{user[:id]}", **options).url
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,6 +27,16 @@ RSpec.describe UserSettings::PersonalAccessTokensController, feature_category: :
|
|||
expect(PersonalAccessToken.active).to include(created_token)
|
||||
end
|
||||
|
||||
it "does not allow creation of a token with workflow scope" do
|
||||
name = 'My PAT'
|
||||
scopes = %w[ai_workflow]
|
||||
|
||||
post :create, params: { personal_access_token: token_attributes.merge(scopes: scopes, name: name) }
|
||||
|
||||
expect(created_token).to be_nil
|
||||
expect(response).to have_gitlab_http_status(:unprocessable_entity)
|
||||
end
|
||||
|
||||
it "allows creation of a token with an expiry date" do
|
||||
expires_at = 5.days.from_now.to_date
|
||||
|
||||
|
|
|
|||
|
|
@ -88,9 +88,25 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching, feature_cate
|
|||
|
||||
it 'optional_scopes contains all non-default scopes' do
|
||||
expect(subject.optional_scopes).to match_array %i[
|
||||
read_user read_api read_repository write_repository read_registry read_service_ping
|
||||
write_registry sudo admin_mode openid profile email read_observability write_observability
|
||||
create_runner manage_runner k8s_proxy ai_features
|
||||
admin_mode
|
||||
ai_features
|
||||
ai_workflows
|
||||
create_runner
|
||||
email
|
||||
k8s_proxy
|
||||
manage_runner
|
||||
openid
|
||||
profile
|
||||
read_api
|
||||
read_observability
|
||||
read_registry
|
||||
read_repository
|
||||
read_service_ping
|
||||
read_user
|
||||
sudo
|
||||
write_observability
|
||||
write_registry
|
||||
write_repository
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -3837,6 +3837,13 @@ RSpec.describe Group, feature_category: :groups_and_projects do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#glql_integration_feature_flag_enabled?' do
|
||||
it_behaves_like 'checks self and root ancestor feature flag' do
|
||||
let(:feature_flag) { :glql_integration }
|
||||
let(:feature_flag_method) { :glql_integration_feature_flag_enabled? }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#supports_lock_on_merge?' do
|
||||
it_behaves_like 'checks self and root ancestor feature flag' do
|
||||
let(:feature_flag) { :enforce_locked_labels_on_merge }
|
||||
|
|
|
|||
|
|
@ -8939,30 +8939,20 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
|
|||
describe '#work_items_feature_flag_enabled?' do
|
||||
let_it_be(:group_project) { create(:project, :in_subgroup) }
|
||||
|
||||
it_behaves_like 'checks parent group feature flag' do
|
||||
it_behaves_like 'checks parent group and self feature flag' do
|
||||
let(:feature_flag_method) { :work_items_feature_flag_enabled? }
|
||||
let(:feature_flag) { :work_items }
|
||||
let(:subject_project) { group_project }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when feature flag is enabled for the project' do
|
||||
subject { subject_project.work_items_feature_flag_enabled? }
|
||||
describe '#glql_integration_feature_flag_enabled?' do
|
||||
let_it_be(:group_project) { create(:project, :in_subgroup) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(work_items: subject_project)
|
||||
end
|
||||
|
||||
context 'when project belongs to a group' do
|
||||
let(:subject_project) { group_project }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
|
||||
context 'when project does not belong to a group' do
|
||||
let(:subject_project) { create(:project, namespace: create(:namespace)) }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
it_behaves_like 'checks parent group and self feature flag' do
|
||||
let(:feature_flag_method) { :glql_integration_feature_flag_enabled? }
|
||||
let(:feature_flag) { :glql_integration }
|
||||
let(:subject_project) { group_project }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -14,5 +14,7 @@ RSpec.describe Admin::ApplicationsController, :enable_admin_mode, feature_catego
|
|||
|
||||
include_examples 'applications controller - GET #show'
|
||||
|
||||
include_examples 'applications controller - GET #new'
|
||||
|
||||
include_examples 'applications controller - POST #create'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -16,5 +16,7 @@ RSpec.describe Groups::Settings::ApplicationsController, feature_category: :syst
|
|||
|
||||
include_examples 'applications controller - GET #show'
|
||||
|
||||
include_examples 'applications controller - GET #new'
|
||||
|
||||
include_examples 'applications controller - POST #create'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,5 +14,7 @@ RSpec.describe Oauth::ApplicationsController, feature_category: :system_access d
|
|||
|
||||
include_examples 'applications controller - GET #show'
|
||||
|
||||
include_examples 'applications controller - GET #new'
|
||||
|
||||
include_examples 'applications controller - POST #create'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -273,7 +273,7 @@ RSpec.describe 'OpenID Connect requests', feature_category: :system_access do
|
|||
let(:expected_scopes) do
|
||||
%w[
|
||||
admin_mode api read_user read_api read_repository write_repository sudo openid profile email
|
||||
read_observability write_observability create_runner manage_runner k8s_proxy ai_features read_service_ping
|
||||
read_observability write_observability create_runner manage_runner k8s_proxy ai_features read_service_ping ai_workflows
|
||||
]
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -250,7 +250,11 @@ RSpec.describe MergeRequests::MergeService, feature_category: :code_review_workf
|
|||
end
|
||||
end
|
||||
|
||||
context 'closes related issues' do
|
||||
context 'closes related issues', :sidekiq_inline do
|
||||
let_it_be_with_refind(:group) { create(:group) }
|
||||
let_it_be_with_refind(:other_project) { create(:project, group: group) }
|
||||
let_it_be(:other_issue) { create(:issue, project: other_project) }
|
||||
let_it_be(:group_issue) { create(:issue, :group_level, namespace: group) }
|
||||
let(:issue1) { create(:issue, project: project) }
|
||||
let(:issue2) { create(:issue, project: project) }
|
||||
let(:commit) do
|
||||
|
|
@ -268,7 +272,7 @@ RSpec.describe MergeRequests::MergeService, feature_category: :code_review_workf
|
|||
)
|
||||
end
|
||||
|
||||
it 'closes GitLab issue tracker issues', :sidekiq_inline do
|
||||
it 'closes GitLab issue tracker issues' do
|
||||
merge_request.cache_merge_request_closes_issues!
|
||||
|
||||
expect do
|
||||
|
|
@ -278,21 +282,74 @@ RSpec.describe MergeRequests::MergeService, feature_category: :code_review_workf
|
|||
)
|
||||
end
|
||||
|
||||
context 'when issue project has auto close disabled', :sidekiq_inline do
|
||||
let_it_be(:group) { create(:group) }
|
||||
let_it_be(:other_project) { create(:project, autoclose_referenced_issues: false, group: group) }
|
||||
let_it_be(:no_close_issue) { create(:issue, project: other_project) }
|
||||
let_it_be(:group_issue) { create(:issue, :group_level, namespace: group) }
|
||||
context 'when closing issues exist in a namespace the merging user doesn\'t have access to' do
|
||||
context 'when the closing work item was created in the merge request description' do
|
||||
before do
|
||||
create(
|
||||
:merge_requests_closing_issues,
|
||||
issue: other_issue,
|
||||
merge_request: merge_request,
|
||||
from_mr_description: true
|
||||
)
|
||||
create(
|
||||
:merge_requests_closing_issues,
|
||||
issue: group_issue,
|
||||
merge_request: merge_request,
|
||||
from_mr_description: true
|
||||
)
|
||||
end
|
||||
|
||||
it 'does not close the related issues' do
|
||||
merge_request.cache_merge_request_closes_issues!
|
||||
|
||||
expect do
|
||||
service.execute(merge_request)
|
||||
end.to not_change { other_issue.reload.opened? }.from(true).and(
|
||||
not_change { group_issue.reload.opened? }.from(true)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the closing work item was not created in the merge request description' do
|
||||
before do
|
||||
create(
|
||||
:merge_requests_closing_issues,
|
||||
issue: other_issue,
|
||||
merge_request: merge_request,
|
||||
from_mr_description: false
|
||||
)
|
||||
create(
|
||||
:merge_requests_closing_issues,
|
||||
issue: group_issue,
|
||||
merge_request: merge_request,
|
||||
from_mr_description: false
|
||||
)
|
||||
end
|
||||
|
||||
it 'closes the related issues' do
|
||||
merge_request.cache_merge_request_closes_issues!
|
||||
|
||||
expect do
|
||||
service.execute(merge_request)
|
||||
end.to change { other_issue.reload.opened? }.from(true).to(false).and(
|
||||
# Autoclose is disabled for group level issues until we introduce a setting at the grouo level
|
||||
# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/472907
|
||||
not_change { group_issue.reload.opened? }.from(true)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when issue project has auto close disabled' do
|
||||
before_all do
|
||||
other_project.add_developer(user)
|
||||
other_project.update!(autoclose_referenced_issues: false)
|
||||
group.add_developer(user)
|
||||
end
|
||||
|
||||
before do
|
||||
create(
|
||||
:merge_requests_closing_issues,
|
||||
issue: no_close_issue,
|
||||
issue: other_issue,
|
||||
merge_request: merge_request,
|
||||
from_mr_description: false
|
||||
)
|
||||
|
|
@ -312,7 +369,7 @@ RSpec.describe MergeRequests::MergeService, feature_category: :code_review_workf
|
|||
end.to change { issue1.reload.closed? }.from(false).to(true).and(
|
||||
change { issue2.reload.closed? }.from(false).to(true)
|
||||
).and(
|
||||
not_change { no_close_issue.reload.opened? }.from(true)
|
||||
not_change { other_issue.reload.opened? }.from(true)
|
||||
).and(
|
||||
not_change { group_issue.reload.opened? }.from(true)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ RSpec.describe MergeRequests::PostMergeService, feature_category: :code_review_w
|
|||
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:merge_request, reload: true) { create(:merge_request, assignees: [user]) }
|
||||
let_it_be(:project) { merge_request.project }
|
||||
let_it_be(:project, reload: true) { merge_request.project }
|
||||
let(:params) { {} }
|
||||
|
||||
subject { described_class.new(project: project, current_user: user, params: params).execute(merge_request) }
|
||||
|
|
@ -85,22 +85,47 @@ RSpec.describe MergeRequests::PostMergeService, feature_category: :code_review_w
|
|||
merge_request.update!(target_branch: 'foo')
|
||||
|
||||
allow(project).to receive(:default_branch).and_return('foo')
|
||||
allow(merge_request).to receive(:visible_closing_issues_for).and_return([issue])
|
||||
allow(merge_request).to receive(:closes_issues).and_return([issue])
|
||||
end
|
||||
|
||||
it 'performs MergeRequests::CloseIssueWorker asynchronously' do
|
||||
create(:merge_requests_closing_issues, merge_request: merge_request, issue: issue)
|
||||
|
||||
expect(MergeRequests::CloseIssueWorker)
|
||||
.to receive(:perform_async)
|
||||
.with(project.id, user.id, issue.id, merge_request.id)
|
||||
.with(project.id, user.id, issue.id, merge_request.id, { skip_authorization: false })
|
||||
|
||||
subject
|
||||
|
||||
expect(merge_request.reload).to be_merged
|
||||
end
|
||||
|
||||
context 'when mr_merge_skips_close_issue_authorization feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(mr_merge_skips_close_issue_authorization: false)
|
||||
end
|
||||
|
||||
it 'does not use the last optional argument of the worker' do
|
||||
create(:merge_requests_closing_issues, merge_request: merge_request, issue: issue)
|
||||
|
||||
expect(MergeRequests::CloseIssueWorker)
|
||||
.to receive(:perform_async)
|
||||
.with(project.id, user.id, issue.id, merge_request.id)
|
||||
|
||||
subject
|
||||
|
||||
expect(merge_request.reload).to be_merged
|
||||
end
|
||||
end
|
||||
|
||||
context 'when issue is an external issue' do
|
||||
let_it_be(:issue) { ExternalIssue.new('JIRA-123', project) }
|
||||
|
||||
before do
|
||||
project.update!(has_external_issue_tracker: true)
|
||||
merge_request.reload
|
||||
end
|
||||
|
||||
it 'executes Issues::CloseService' do
|
||||
expect_next_instance_of(Issues::CloseService) do |close_service|
|
||||
expect(close_service).to receive(:execute).with(issue, commit: merge_request)
|
||||
|
|
|
|||
|
|
@ -61,6 +61,30 @@ RSpec.shared_examples 'checks parent group feature flag' do
|
|||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'checks parent group and self feature flag' do
|
||||
it_behaves_like 'checks parent group feature flag'
|
||||
|
||||
context 'when feature flag is enabled for the project' do
|
||||
before do
|
||||
stub_feature_flags(feature_flag => subject_project)
|
||||
end
|
||||
|
||||
context 'when project belongs to a group' do
|
||||
let(:subject_project) { group_project }
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
|
||||
context 'when project does not belong to a group' do
|
||||
let(:subject_project) do
|
||||
create(:project, namespace: create(:namespace))
|
||||
end
|
||||
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'refreshes project.lfs_file_locks_changed_epoch value' do
|
||||
it 'updates the lfs_file_locks_changed_epoch value', :clean_gitlab_redis_cache do
|
||||
travel_to(1.hour.ago) { project.refresh_lfs_file_locks_changed_epoch }
|
||||
|
|
|
|||
|
|
@ -10,6 +10,32 @@ RSpec.shared_examples 'applications controller - GET #show' do
|
|||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'applications controller - GET #new' do
|
||||
it "sets `@scopes` to list of all scopes that should be shown" do
|
||||
create_application
|
||||
|
||||
expect(assigns[:scopes]).to match_array(%w[
|
||||
admin_mode
|
||||
ai_features
|
||||
api
|
||||
create_runner
|
||||
email
|
||||
k8s_proxy
|
||||
manage_runner
|
||||
openid
|
||||
profile
|
||||
read_api
|
||||
read_observability
|
||||
read_repository
|
||||
read_service_ping
|
||||
read_user
|
||||
sudo
|
||||
write_observability
|
||||
write_repository
|
||||
])
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'applications controller - POST #create' do
|
||||
it "sets `@created` instance variable to `true`" do
|
||||
create_application
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ RSpec.describe MergeRequests::CloseIssueWorker, feature_category: :code_review_w
|
|||
|
||||
it 'calls the close issue service' do
|
||||
expect_next_instance_of(Issues::CloseService, container: project, current_user: user) do |service|
|
||||
expect(service).to receive(:execute).with(issue, commit: merge_request)
|
||||
expect(service).to receive(:execute).with(issue, commit: merge_request, skip_authorization: false)
|
||||
end
|
||||
|
||||
subject.perform(project.id, user.id, issue.id, merge_request.id)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
include:
|
||||
- local: gems/gem.gitlab-ci.yml
|
||||
inputs:
|
||||
gem_name: "gitlab-duo-workflow-service-client"
|
||||
gem_path_prefix: "vendor/gems/"
|
||||
|
|
@ -0,0 +1 @@
|
|||
@gitlab-org/ai-powered/ai-framework/engineering/all
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
# Duo Workflow Service Client Gem
|
||||
|
||||
This Ruby Gem is meant to initialize a client to the Duo Workflow Service
|
||||
This Gem is automatically generated via GRPC from the
|
||||
repository https://gitlab.com/gitlab-org/duo-workflow/duo-workflow-service
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
source "https://rubygems.org"
|
||||
|
||||
# Specify your gem's dependencies in ruby.gemspec
|
||||
gemspec
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
gitlab-duo-workflow-service-client (0.1)
|
||||
grpc
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (7.1.3.2)
|
||||
base64
|
||||
bigdecimal
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
connection_pool (>= 2.2.5)
|
||||
drb
|
||||
i18n (>= 1.6, < 2)
|
||||
minitest (>= 5.1)
|
||||
mutex_m
|
||||
tzinfo (~> 2.0)
|
||||
ast (2.4.2)
|
||||
base64 (0.2.0)
|
||||
bigdecimal (3.1.8)
|
||||
binding_of_caller (1.0.1)
|
||||
debug_inspector (>= 1.2.0)
|
||||
concurrent-ruby (1.2.3)
|
||||
connection_pool (2.4.1)
|
||||
debug_inspector (1.2.0)
|
||||
diff-lcs (1.5.1)
|
||||
drb (2.2.1)
|
||||
gitlab-styles (10.1.0)
|
||||
rubocop (~> 1.50.2)
|
||||
rubocop-graphql (~> 0.18)
|
||||
rubocop-performance (~> 1.15)
|
||||
rubocop-rails (~> 2.17)
|
||||
rubocop-rspec (~> 2.22)
|
||||
google-protobuf (4.27.3)
|
||||
bigdecimal
|
||||
rake (>= 13)
|
||||
googleapis-common-protos-types (1.15.0)
|
||||
google-protobuf (>= 3.18, < 5.a)
|
||||
grpc (1.65.2)
|
||||
google-protobuf (>= 3.25, < 5.0)
|
||||
googleapis-common-protos-types (~> 1.0)
|
||||
grpc-tools (1.65.2)
|
||||
i18n (1.14.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
json (2.7.1)
|
||||
minitest (5.22.3)
|
||||
mutex_m (0.2.0)
|
||||
parallel (1.24.0)
|
||||
parser (3.3.0.5)
|
||||
ast (~> 2.4.1)
|
||||
racc
|
||||
proc_to_ast (0.2.0)
|
||||
parser
|
||||
rouge
|
||||
unparser
|
||||
racc (1.7.3)
|
||||
rack (3.0.11)
|
||||
rainbow (3.1.1)
|
||||
rake (13.2.1)
|
||||
regexp_parser (2.9.0)
|
||||
rexml (3.2.6)
|
||||
rouge (4.3.0)
|
||||
rspec (3.13.0)
|
||||
rspec-core (~> 3.13.0)
|
||||
rspec-expectations (~> 3.13.0)
|
||||
rspec-mocks (~> 3.13.0)
|
||||
rspec-core (3.13.0)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-expectations (3.13.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-mocks (3.13.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.13.0)
|
||||
rspec-parameterized (1.0.2)
|
||||
rspec-parameterized-core (< 2)
|
||||
rspec-parameterized-table_syntax (< 2)
|
||||
rspec-parameterized-core (1.0.1)
|
||||
parser
|
||||
proc_to_ast (>= 0.2.0)
|
||||
rspec (>= 2.13, < 4)
|
||||
unparser
|
||||
rspec-parameterized-table_syntax (1.0.1)
|
||||
binding_of_caller
|
||||
rspec-parameterized-core (< 2)
|
||||
rspec-support (3.13.0)
|
||||
rubocop (1.50.2)
|
||||
json (~> 2.3)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 3.2.0.0)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 1.8, < 3.0)
|
||||
rexml (>= 3.2.5, < 4.0)
|
||||
rubocop-ast (>= 1.28.0, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 2.4.0, < 3.0)
|
||||
rubocop-ast (1.30.0)
|
||||
parser (>= 3.2.1.0)
|
||||
rubocop-capybara (2.20.0)
|
||||
rubocop (~> 1.41)
|
||||
rubocop-factory_bot (2.25.1)
|
||||
rubocop (~> 1.41)
|
||||
rubocop-graphql (0.19.0)
|
||||
rubocop (>= 0.87, < 2)
|
||||
rubocop-performance (1.20.2)
|
||||
rubocop (>= 1.48.1, < 2.0)
|
||||
rubocop-ast (>= 1.30.0, < 2.0)
|
||||
rubocop-rails (2.23.1)
|
||||
activesupport (>= 4.2.0)
|
||||
rack (>= 1.1)
|
||||
rubocop (>= 1.33.0, < 2.0)
|
||||
rubocop-ast (>= 1.30.0, < 2.0)
|
||||
rubocop-rspec (2.29.2)
|
||||
rubocop (~> 1.40)
|
||||
rubocop-capybara (~> 2.17)
|
||||
rubocop-factory_bot (~> 2.22)
|
||||
rubocop-rspec_rails (~> 2.28)
|
||||
rubocop-rspec_rails (2.28.3)
|
||||
rubocop (~> 1.40)
|
||||
ruby-progressbar (1.13.0)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
unicode-display_width (2.5.0)
|
||||
unparser (0.6.15)
|
||||
diff-lcs (~> 1.3)
|
||||
parser (>= 3.3.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
gitlab-duo-workflow-service-client!
|
||||
gitlab-styles (~> 10.1.0)
|
||||
grpc-tools
|
||||
rspec (~> 3.0)
|
||||
rspec-parameterized (~> 1.0.2)
|
||||
rubocop (~> 1.21)
|
||||
|
||||
BUNDLED WITH
|
||||
2.4.4
|
||||
25
vendor/gems/gitlab-duo-workflow-service-client/gitlab-duo-workflow-service-client.gemspec
vendored
Normal file
25
vendor/gems/gitlab-duo-workflow-service-client/gitlab-duo-workflow-service-client.gemspec
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "lib/gitlab/duo_workflow_service/version"
|
||||
|
||||
Gem::Specification.new do |spec|
|
||||
spec.name = "gitlab-duo-workflow-service-client"
|
||||
spec.version = Gitlab::DuoWorkflowService::VERSION
|
||||
spec.authors = ["group::ai framework"]
|
||||
spec.email = ["engineering@gitlab.com"]
|
||||
|
||||
spec.summary = "Client library to interact with the Duo Workflow Service"
|
||||
spec.homepage = "https://gitlab.com/gitlab-org/duo-workflow/duo-workflow-service"
|
||||
spec.license = "MIT"
|
||||
spec.required_ruby_version = ">= 2.6.0"
|
||||
|
||||
spec.files = Dir['lib/**/*.rb']
|
||||
spec.require_paths = ["lib"]
|
||||
|
||||
spec.add_dependency "grpc"
|
||||
spec.add_development_dependency "gitlab-styles", "~> 10.1.0"
|
||||
spec.add_development_dependency "rspec", "~> 3.0"
|
||||
spec.add_development_dependency "rspec-parameterized", "~> 1.0.2"
|
||||
spec.add_development_dependency "rubocop", "~> 1.21"
|
||||
spec.add_development_dependency 'grpc-tools'
|
||||
end
|
||||
5
vendor/gems/gitlab-duo-workflow-service-client/lib/gitlab/duo_workflow_service.rb
vendored
Normal file
5
vendor/gems/gitlab-duo-workflow-service-client/lib/gitlab/duo_workflow_service.rb
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "duo_workflow_service/version"
|
||||
|
||||
require "proto/contract_services_pb"
|
||||
7
vendor/gems/gitlab-duo-workflow-service-client/lib/gitlab/duo_workflow_service/version.rb
vendored
Normal file
7
vendor/gems/gitlab-duo-workflow-service-client/lib/gitlab/duo_workflow_service/version.rb
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module DuoWorkflowService
|
||||
VERSION = "0.1"
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: contract.proto
|
||||
|
||||
require 'google/protobuf'
|
||||
|
||||
|
||||
descriptor_data = "\n\x0e\x63ontract.proto\"s\n\x0b\x43lientEvent\x12-\n\x0cstartRequest\x18\x01 \x01(\x0b\x32\x15.StartWorkflowRequestH\x00\x12)\n\x0e\x61\x63tionResponse\x18\x02 \x01(\x0b\x32\x0f.ActionResponseH\x00\x42\n\n\x08response\"k\n\x14StartWorkflowRequest\x12\x15\n\rclientVersion\x18\x01 \x01(\t\x12\x12\n\nworkflowID\x18\x02 \x01(\t\x12\x1a\n\x12workflowDefinition\x18\x03 \x01(\t\x12\x0c\n\x04goal\x18\x04 \x01(\t\"5\n\x0e\x41\x63tionResponse\x12\x11\n\trequestID\x18\x01 \x01(\t\x12\x10\n\x08response\x18\x02 \x01(\t\"\xbf\x01\n\x06\x41\x63tion\x12\x11\n\trequestID\x18\x01 \x01(\t\x12\'\n\nrunCommand\x18\x02 \x01(\x0b\x32\x11.RunCommandActionH\x00\x12)\n\x0erunHTTPRequest\x18\x03 \x01(\x0b\x32\x0f.RunHTTPRequestH\x00\x12 \n\x0brunReadFile\x18\x04 \x01(\x0b\x32\t.ReadFileH\x00\x12\"\n\x0crunWriteFile\x18\x05 \x01(\x0b\x32\n.WriteFileH\x00\x42\x08\n\x06\x61\x63tion\"#\n\x10RunCommandAction\x12\x0f\n\x07\x63ommand\x18\x01 \x01(\t\"\x1c\n\x08ReadFile\x12\x10\n\x08\x66ilepath\x18\x01 \x01(\t\"/\n\tWriteFile\x12\x10\n\x08\x66ilepath\x18\x01 \x01(\t\x12\x10\n\x08\x63ontents\x18\x02 \x01(\t\"J\n\x0eRunHTTPRequest\x12\x0e\n\x06method\x18\x01 \x01(\t\x12\x0c\n\x04path\x18\x02 \x01(\t\x12\x11\n\x04\x62ody\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x07\n\x05_body\"\x16\n\x14GenerateTokenRequest\"9\n\x15GenerateTokenResponse\x12\r\n\x05token\x18\x01 \x01(\t\x12\x11\n\texpiresAt\x18\x02 \x01(\x03\x32{\n\x0b\x44uoWorkflow\x12,\n\x0f\x45xecuteWorkflow\x12\x0c.ClientEvent\x1a\x07.Action(\x01\x30\x01\x12>\n\rGenerateToken\x12\x15.GenerateTokenRequest\x1a\x16.GenerateTokenResponseBfZOgitlab.com/gitlab-org/ai-powered/ai-framework/duo_workflow_executor/pkg/service\xea\x02\x12\x44uoWorkflowServiceb\x06proto3"
|
||||
|
||||
pool = Google::Protobuf::DescriptorPool.generated_pool
|
||||
pool.add_serialized_file(descriptor_data)
|
||||
|
||||
module DuoWorkflowService
|
||||
ClientEvent = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ClientEvent").msgclass
|
||||
StartWorkflowRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("StartWorkflowRequest").msgclass
|
||||
ActionResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ActionResponse").msgclass
|
||||
Action = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("Action").msgclass
|
||||
RunCommandAction = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("RunCommandAction").msgclass
|
||||
ReadFile = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("ReadFile").msgclass
|
||||
WriteFile = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("WriteFile").msgclass
|
||||
RunHTTPRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("RunHTTPRequest").msgclass
|
||||
GenerateTokenRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("GenerateTokenRequest").msgclass
|
||||
GenerateTokenResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("GenerateTokenResponse").msgclass
|
||||
end
|
||||
23
vendor/gems/gitlab-duo-workflow-service-client/lib/proto/contract_services_pb.rb
vendored
Normal file
23
vendor/gems/gitlab-duo-workflow-service-client/lib/proto/contract_services_pb.rb
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# Source: contract.proto for package 'DuoWorkflowService'
|
||||
|
||||
require 'grpc'
|
||||
require_relative 'contract_pb'
|
||||
|
||||
module DuoWorkflowService
|
||||
module DuoWorkflow
|
||||
class Service
|
||||
|
||||
include ::GRPC::GenericService
|
||||
|
||||
self.marshal_class_method = :encode
|
||||
self.unmarshal_class_method = :decode
|
||||
self.service_name = 'DuoWorkflow'
|
||||
|
||||
rpc :ExecuteWorkflow, stream(::DuoWorkflowService::ClientEvent), stream(::DuoWorkflowService::Action)
|
||||
rpc :GenerateToken, ::DuoWorkflowService::GenerateTokenRequest, ::DuoWorkflowService::GenerateTokenResponse
|
||||
end
|
||||
|
||||
Stub = Service.rpc_stub_class
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue