Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml37
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml11
-rw-r--r--.gitlab/issue_templates/Security developer workflow.md11
-rw-r--r--.rubocop_todo/layout/line_length.yml1
-rw-r--r--.rubocop_todo/style/if_unless_modifier.yml1
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.checksum20
-rw-r--r--Gemfile.lock6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/checks/rebase.stories.js2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/checks/rebase.vue9
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue7
-rw-r--r--app/controllers/projects/merge_requests_controller.rb1
-rw-r--r--app/models/ci/build.rb12
-rw-r--r--app/models/ci/pipeline.rb1
-rw-r--r--app/services/ci/job_artifacts/create_service.rb2
-rw-r--r--config/feature_flags/development/widget_pipeline_pass_subscription_update.yml8
-rw-r--r--doc/architecture/blueprints/new_diffs.md102
-rw-r--r--doc/development/ai_features/duo_chat.md21
-rw-r--r--doc/editor_extensions/visual_studio_code/index.md1
-rw-r--r--doc/user/gitlab_duo_chat.md24
-rw-r--r--doc/user/group/saml_sso/group_sync.md20
-rw-r--r--doc/user/project/web_ide/index.md4
-rw-r--r--lefthook.yml2
-rwxr-xr-xscripts/duo_chat/reporter.rb16
-rw-r--r--spec/frontend/vue_merge_request_widget/components/checks/rebase_spec.js4
-rw-r--r--spec/models/ci/build_spec.rb78
-rw-r--r--spec/models/ci/pipeline_spec.rb12
-rw-r--r--spec/requests/api/ci/job_artifacts_spec.rb6
-rw-r--r--spec/serializers/build_details_entity_spec.rb2
-rw-r--r--spec/services/ci/job_artifacts/create_service_spec.rb6
30 files changed, 304 insertions, 125 deletions
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index 30553026c03..96793b1f5d4 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -765,46 +765,41 @@ rspec system pg14-as-if-foss clusterwide-db:
- .clusterwide-db
- .rails:rules:clusterwide-db
-.rspec-ee-base-gitlab-duo:
- extends:
- - .rspec-ee-base-pg14
+rspec-ee unit gitlab-duo-chat pg14:
variables:
REAL_AI_REQUEST: "true"
-
-rspec-ee unit gitlab-duo-chat-zeroshot pg14:
- extends:
- - .rspec-ee-base-gitlab-duo
- - .rails:rules:ee-gitlab-duo-chat-optional
- script:
- - !reference [.base-script, script]
- - rspec_paralellized_job "--tag zeroshot_executor"
-
-rspec-ee unit gitlab-duo-chat-qa-fast pg14:
+ RSPEC_RETRY_RETRY_COUNT: 0
extends:
- - .rspec-ee-base-gitlab-duo
- - .rails:rules:ee-gitlab-duo-chat-fast
+ - .rspec-ee-base-pg14
+ - .rails:rules:ee-gitlab-duo-chat-base
+ parallel:
+ matrix:
+ - DUO_RSPEC: ["lib/gitlab/llm/chain/agents/zero_shot/executor_real_requests_spec.rb", "support_specs/helpers/chat_qa_evaluation_helpers_spec.rb"]
script:
- !reference [.base-script, script]
- - bundle exec rspec -Ispec -rspec_helper --color --tag fast_chat_qa_evaluation -- ee/spec/lib/gitlab/llm/chain/agents/zero_shot/qa_evaluation_spec.rb
+ - bundle exec rspec -Ispec -rspec_helper --failure-exit-code 0 --tag real_ai_request --color -- ee/spec/${DUO_RSPEC}
rspec-ee unit gitlab-duo-chat-qa pg14:
variables:
- QA_EVAL_REPORT_FILENAME: "qa_evaluation_report.md"
+ REAL_AI_REQUEST: "true"
RSPEC_RETRY_RETRY_COUNT: 0
extends:
- - .rspec-ee-base-gitlab-duo
- - .rails:rules:ee-gitlab-duo-chat-optional
+ - .rspec-ee-base-pg14
+ - .rails:rules:ee-gitlab-duo-chat-base
+ parallel:
+ matrix:
+ - DUO_RSPEC: ["qa_epic_spec.rb", "qa_issue_spec.rb"]
script:
- !reference [.base-script, script]
- source ./scripts/utils.sh
- install_gitlab_gem
- - bundle exec rspec -Ispec -rspec_helper --failure-exit-code 0 --color --tag chat_qa_evaluation -- ee/spec/lib/gitlab/llm/chain/agents/zero_shot/qa_evaluation_spec.rb
+ - bundle exec rspec -Ispec -rspec_helper --failure-exit-code 0 --tag real_ai_request --color -- ee/spec/lib/gitlab/llm/chain/agents/zero_shot/${DUO_RSPEC}
- ./scripts/duo_chat/reporter.rb
artifacts:
expire_in: 5d
paths:
- tmp/duo_chat/qa*.json
- - "${QA_EVAL_REPORT_FILENAME}"
+ - "${DUO_RSPEC}.md"
rspec-ee migration pg14:
extends:
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 6401d52899e..7b160a0efb5 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -2125,20 +2125,11 @@
when: never
- if: '$VERTEX_AI_CREDENTIALS == null'
when: never
-
-.rails:rules:ee-gitlab-duo-chat-optional:
- rules:
- - !reference [".rails:rules:ee-gitlab-duo-chat-base", rules]
- <<: *if-merge-request
+ changes: *ai-patterns
when: manual
allow_failure: true
-.rails:rules:ee-gitlab-duo-chat-fast:
- rules:
- - !reference [".rails:rules:ee-gitlab-duo-chat-base", rules]
- - <<: *if-merge-request
- changes: *ai-patterns
-
.rails:rules:as-if-foss-migration:
rules:
- !reference [".strict-ee-only-rules", rules]
diff --git a/.gitlab/issue_templates/Security developer workflow.md b/.gitlab/issue_templates/Security developer workflow.md
index d7ed4bf30e4..22b87786fb3 100644
--- a/.gitlab/issue_templates/Security developer workflow.md
+++ b/.gitlab/issue_templates/Security developer workflow.md
@@ -28,19 +28,19 @@ After your merge request has been approved according to our [approval guidelines
## Backports
-- [ ] Once the MR is ready to be merged, create MRs targeting the latest 3 stable branches
- * The 3 stable branches correspond to the versions in the title of the Security Release Tracking Issue.
+- [ ] Once the MR is ready to be merged, create MRs targeting the latest 3 stable branches.
+ * The 3 stable branches correspond to the versions in the title of the [Security Release Tracking Issue].
* At this point, it might be easy to squash the commits from the MR into one
* You can use the script `bin/secpick` instead of the following steps, to help you cherry-picking. See the [secpick documentation]
- [ ] Create each MR targeting the stable branch `X-Y-stable`, using the [Security Release merge request template].
* Every merge request will have its own set of to-dos, so make sure to complete those.
- [ ] On the "Related merge requests" section, ensure that `4` merge requests are associated: The one targeting `master` and the `3` backports.
-- [ ] If this issue requires less than `4` merge requests, post a message on the Security Release Tracking Issue and ping the Release Managers.
+- [ ] If this issue requires less than `4` merge requests, add the ~"reduced backports" label.
## Assigning to a release
-- [ ] **IMPORTANT**: When this issue is ready for release (Default branch MR and backports are approved and ready to be merged), apply the ~"security-target" label.
- * The `gitlab-release-tools-bot` evaluates and links issues with the label to the next planned security release tracking issue. If the bot finds the issue is not ready to be included in the security release, it will leave a comment on the issue explaining what needs to be done.
+- [ ] **IMPORTANT**: When this issue is ready for release (Default branch MR and backports are approved and ready to be merged), apply the ~"security-target" label.
+ * The `gitlab-release-tools-bot` evaluates and links issues with the label to the next planned security release tracking issue. If the bot finds the issue is not ready to be included in the security release, it will leave a comment on the issue explaining what needs to be done.
* This issue will only be included in a security release if it is successfully linked to the security release tracking issue.
## Documentation and final details
@@ -82,5 +82,6 @@ After your merge request has been approved according to our [approval guidelines
[issue as linked]: https://docs.gitlab.com/ee/user/project/issues/related_issues.html#add-a-linked-issue
[issue really needs to follow the security release workflow]: https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/security/developer.md#making-sure-the-issue-needs-to-follow-the-security-release-workflow
[breaking changes workflow]: https://gitlab.com/gitlab-org/release/docs/-/blob/master/general/security/far_reaching_impact_fixes_or_breaking_change_fixes.md
+[Security Release Tracking Issue]: https://gitlab.com/gitlab-org/gitlab/-/issues/?label_name%5B%5D=upcoming%20security%20release
/label ~security ~"security-notifications"
diff --git a/.rubocop_todo/layout/line_length.yml b/.rubocop_todo/layout/line_length.yml
index 4bb700df401..a3b6d17e24e 100644
--- a/.rubocop_todo/layout/line_length.yml
+++ b/.rubocop_todo/layout/line_length.yml
@@ -1237,7 +1237,6 @@ Layout/LineLength:
- 'ee/lib/gitlab/geo/git_ssh_proxy.rb'
- 'ee/lib/gitlab/geo/health_check.rb'
- 'ee/lib/gitlab/geo/jwt_request_decoder.rb'
- - 'ee/lib/gitlab/geo/log_cursor/events/repository_created_event.rb'
- 'ee/lib/gitlab/geo/registry_batcher.rb'
- 'ee/lib/gitlab/geo/replication/blob_downloader.rb'
- 'ee/lib/gitlab/geo/replicator.rb'
diff --git a/.rubocop_todo/style/if_unless_modifier.yml b/.rubocop_todo/style/if_unless_modifier.yml
index cd1c26b2330..70727e74805 100644
--- a/.rubocop_todo/style/if_unless_modifier.yml
+++ b/.rubocop_todo/style/if_unless_modifier.yml
@@ -596,7 +596,6 @@ Style/IfUnlessModifier:
- 'ee/lib/gitlab/geo/git_ssh_proxy.rb'
- 'ee/lib/gitlab/geo/health_check.rb'
- 'ee/lib/gitlab/geo/log_cursor/daemon.rb'
- - 'ee/lib/gitlab/geo/log_cursor/events/repository_deleted_event.rb'
- 'ee/lib/gitlab/geo/oauth/logout_token.rb'
- 'ee/lib/gitlab/geo/replication/blob_downloader.rb'
- 'ee/lib/gitlab/geo/replicator.rb'
diff --git a/Gemfile b/Gemfile
index 776ce789901..36a24eb099b 100644
--- a/Gemfile
+++ b/Gemfile
@@ -546,7 +546,7 @@ gem 'kas-grpc', '~> 0.3.0', feature_category: :deployment_management
gem 'grpc', '~> 1.58.0' # rubocop:todo Gemfile/MissingFeatureCategory
-gem 'google-protobuf', '~> 3.25' # rubocop:todo Gemfile/MissingFeatureCategory
+gem 'google-protobuf', '~> 3.25', '>= 3.25.1' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'toml-rb', '~> 2.2.0' # rubocop:todo Gemfile/MissingFeatureCategory
diff --git a/Gemfile.checksum b/Gemfile.checksum
index 750b2c40e5b..c04ec4641c3 100644
--- a/Gemfile.checksum
+++ b/Gemfile.checksum
@@ -244,16 +244,16 @@
{"name":"google-cloud-errors","version":"1.3.0","platform":"ruby","checksum":"450b681e24c089a20721a01acc4408bb4a7b0df28c175aaab488da917480d64b"},
{"name":"google-cloud-profiler-v2","version":"0.4.0","platform":"ruby","checksum":"53fc2ab175d08f54233c644310d47798feac996220916815c4fb44c937b5d3e3"},
{"name":"google-cloud-storage","version":"1.44.0","platform":"ruby","checksum":"299a1e055c9277c8120f7c10d21d37e4d8c17c7b963350c0e0bff7e9d9a570ea"},
-{"name":"google-protobuf","version":"3.25.0","platform":"aarch64-linux","checksum":"4455602758a60bd698a57c7210efc440523523fbe0c0c712624e57bb02c6c9d4"},
-{"name":"google-protobuf","version":"3.25.0","platform":"arm64-darwin","checksum":"c1ba0bb5504155f5bd0d11d649316ff52cef5b2a1e7ce876497815f98be3c5a6"},
-{"name":"google-protobuf","version":"3.25.0","platform":"java","checksum":"7006d8485d6c729c081a7eb8592d8c494fd8716863a7fb7ad7c76188eafc41a5"},
-{"name":"google-protobuf","version":"3.25.0","platform":"ruby","checksum":"b51632d900b633fbd6164784351bee93001dfd3f32bd18f6505fc97d64e1a1a1"},
-{"name":"google-protobuf","version":"3.25.0","platform":"x64-mingw-ucrt","checksum":"e4935e41e0f3c32fe96e496803de61d36273474ebb72ac7ee9db3a4ecb4b5cd6"},
-{"name":"google-protobuf","version":"3.25.0","platform":"x64-mingw32","checksum":"42b13346a1be8346e4d62a41ac7150f374ca5d254b3bb4bf3bc817de522ce969"},
-{"name":"google-protobuf","version":"3.25.0","platform":"x86-linux","checksum":"7f391788f013778ffae197a184481ff24265a977d1cb2270b13a5af1ba2f53d5"},
-{"name":"google-protobuf","version":"3.25.0","platform":"x86-mingw32","checksum":"2f42a5738af0a874b35b228a2df8de21a58fa265627cfd0fa57edaea160c1087"},
-{"name":"google-protobuf","version":"3.25.0","platform":"x86_64-darwin","checksum":"c3d4a144d8f4d61193ab1a4c5d52e2d40562ba13e07eeca1fca34bc59212c352"},
-{"name":"google-protobuf","version":"3.25.0","platform":"x86_64-linux","checksum":"c6a76175c921b300ee62b21d36e8a9c07f0a4967a17be0671a83c57d7bf9bd0f"},
+{"name":"google-protobuf","version":"3.25.1","platform":"aarch64-linux","checksum":"ac359f7dff48444fee35b1720d5fe4c3a15e1ce1d1cf2b01720e78e0c3c60e59"},
+{"name":"google-protobuf","version":"3.25.1","platform":"arm64-darwin","checksum":"9db6f8a7185d0109934db2f68defff7cba36b0e5816eb3b7aff8c35c61ac4cb5"},
+{"name":"google-protobuf","version":"3.25.1","platform":"java","checksum":"e02d624fafa42ddd27770ab3824d90fd5833dfc22e5778f4b72f5e33823795cf"},
+{"name":"google-protobuf","version":"3.25.1","platform":"ruby","checksum":"e740e099193f8dc4db638326e23868d6c799dbd5ae2fd7565e78d1530cc6d1a3"},
+{"name":"google-protobuf","version":"3.25.1","platform":"x64-mingw-ucrt","checksum":"33f9ef7fb931d4f9226bf7c5e6dc7965d71be65202ddab5f918e11d2b094c247"},
+{"name":"google-protobuf","version":"3.25.1","platform":"x64-mingw32","checksum":"61aad72c3db95719d39d371127124667f2bf136f09050fe74ca9c5e7b84b70de"},
+{"name":"google-protobuf","version":"3.25.1","platform":"x86-linux","checksum":"621ea865943efb085810dd76f35913aa9a8aff24ea358fd96b58291d9067f2a1"},
+{"name":"google-protobuf","version":"3.25.1","platform":"x86-mingw32","checksum":"94974547d65cf72fa5474dc43e18148d6478f3271fa81531c8333940b07779fd"},
+{"name":"google-protobuf","version":"3.25.1","platform":"x86_64-darwin","checksum":"48324e6f17f4a6b478d9f6c844e333ef4d88d82558c44ef87c588adba3a5ff40"},
+{"name":"google-protobuf","version":"3.25.1","platform":"x86_64-linux","checksum":"956d89256ed61cd0407a4e635a2286b8d478ca98075f4f398c30f91b765e9c54"},
{"name":"googleapis-common-protos","version":"1.4.0","platform":"ruby","checksum":"da2380fb5ab1563580816c74e8d684ac17512c3654c829a3ee84f6d6139de382"},
{"name":"googleapis-common-protos-types","version":"1.5.0","platform":"ruby","checksum":"5769cf7376abc86ef7f5897a4aaca1d5c5a3c49ddabeddd2c251fcf8155f858b"},
{"name":"googleauth","version":"1.3.0","platform":"ruby","checksum":"51dd7362353cf1e90a2d01e1fb94321ae3926c776d4dc4a79db65230217ffcc2"},
diff --git a/Gemfile.lock b/Gemfile.lock
index c083cca8d25..1b9ebfe61b9 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -787,7 +787,7 @@ GEM
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
- google-protobuf (3.25.0)
+ google-protobuf (3.25.1)
googleapis-common-protos (1.4.0)
google-protobuf (~> 3.14)
googleapis-common-protos-types (~> 1.2)
@@ -1899,7 +1899,7 @@ DEPENDENCIES
google-apis-serviceusage_v1 (~> 0.28.0)
google-apis-sqladmin_v1beta4 (~> 0.41.0)
google-cloud-storage (~> 1.44.0)
- google-protobuf (~> 3.25)
+ google-protobuf (~> 3.25, >= 3.25.1)
gpgme (~> 2.0.23)
grape (~> 1.7.1)
grape-entity (~> 0.10.0)
@@ -2098,4 +2098,4 @@ DEPENDENCIES
yajl-ruby (~> 1.4.3)
BUNDLED WITH
- 2.4.21
+ 2.4.22
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/checks/rebase.stories.js b/app/assets/javascripts/vue_merge_request_widget/components/checks/rebase.stories.js
index c0ac1818ffa..a4594409977 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/checks/rebase.stories.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/checks/rebase.stories.js
@@ -63,7 +63,7 @@ const Template = ({
apolloProvider,
check: {
identifier: 'need_rebase',
- status: failed ? 'failed' : 'passed',
+ status: failed ? 'FAILED' : 'SUCCESS',
},
mr: { onlyAllowMergeIfPipelineSucceeds },
canCreatePipelineInTargetProject,
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/checks/rebase.vue b/app/assets/javascripts/vue_merge_request_widget/components/checks/rebase.vue
index 72140c22a89..63fa90fcc7a 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/checks/rebase.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/checks/rebase.vue
@@ -65,8 +65,9 @@ export default {
},
showRebaseWithoutPipeline() {
return (
- !this.mr.onlyAllowMergeIfPipelineSucceeds ||
- (this.mr.onlyAllowMergeIfPipelineSucceeds && this.mr.allowMergeOnSkippedPipeline)
+ this.state.userPermissions.pushToSourceBranch &&
+ (!this.mr.onlyAllowMergeIfPipelineSucceeds ||
+ (this.mr.onlyAllowMergeIfPipelineSucceeds && this.mr.allowMergeOnSkippedPipeline))
);
},
isForkMergeRequest() {
@@ -85,10 +86,8 @@ export default {
);
},
tertiaryActionsButtons() {
- if (this.check.result === 'success') return [];
-
return [
- {
+ this.state.userPermissions.pushToSourceBranch && {
text: s__('mrWidget|Rebase'),
loading: this.isMakingRequest || this.rebaseInProgress,
testId: 'standard-rebase-button',
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
index 3c2d8efaffc..6de041d8f0d 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
@@ -59,6 +59,7 @@ export default {
apollo: {
state: {
query: readyToMergeQuery,
+ fetchPolicy: fetchPolicies.NO_CACHE,
variables() {
return this.mergeRequestQueryVariables;
},
@@ -349,12 +350,6 @@ export default {
eventHub.$on('ApprovalUpdated', this.updateGraphqlState);
eventHub.$on('MRWidgetUpdateRequested', this.updateGraphqlState);
eventHub.$on('mr.discussion.updated', this.updateGraphqlState);
-
- if (this.glFeatures.widgetPipelinePassSubscriptionUpdate) {
- this.$apollo.queries.state.setOptions({
- fetchPolicy: fetchPolicies.NO_CACHE,
- });
- }
},
beforeDestroy() {
eventHub.$off('ApprovalUpdated', this.updateGraphqlState);
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 08bee6cbcf8..ce0c8291eda 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -45,7 +45,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:ci_job_failures_in_mr, project)
push_frontend_feature_flag(:mr_pipelines_graphql, project)
push_frontend_feature_flag(:notifications_todos_buttons, current_user)
- push_frontend_feature_flag(:widget_pipeline_pass_subscription_update, project)
push_frontend_feature_flag(:mr_request_changes, current_user)
end
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 284495a1d97..4b548405bb9 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -705,13 +705,21 @@ module Ci
end
def artifacts_public?
- return true unless Feature.enabled?(:non_public_artifacts, type: :development)
+ return true if Feature.disabled?(:non_public_artifacts, type: :development)
+
+ return true if job_artifacts_archive.nil? # To backward compatibility return true if no artifacts found
+
+ job_artifacts_archive.public_access?
+ end
+
+ def artifact_is_public_in_config?
+ return true if Feature.disabled?(:non_public_artifacts, type: :development)
artifacts_public = options.dig(:artifacts, :public)
return true if artifacts_public.nil? # Default artifacts:public to true
- options.dig(:artifacts, :public)
+ artifacts_public
end
def artifacts_metadata_entry(path, **options)
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index faa79f8f49c..7ee96d6796e 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -415,7 +415,6 @@ module Ci
pipeline.run_after_commit do
next if pipeline.child?
- next unless Feature.enabled?(:widget_pipeline_pass_subscription_update, project) || project.only_allow_merge_if_pipeline_succeeds?(inherit_group_setting: true)
pipeline.all_merge_requests.opened.each do |merge_request|
GraphqlTriggers.merge_request_merge_status_updated(merge_request)
diff --git a/app/services/ci/job_artifacts/create_service.rb b/app/services/ci/job_artifacts/create_service.rb
index c09b0cf81f1..b04e73c69ee 100644
--- a/app/services/ci/job_artifacts/create_service.rb
+++ b/app/services/ci/job_artifacts/create_service.rb
@@ -132,7 +132,7 @@ module Ci
return accessibility if accessibility.present?
- job.artifacts_public? ? :public : :private
+ job.artifact_is_public_in_config? ? :public : :private
end
def parse_artifact(artifact)
diff --git a/config/feature_flags/development/widget_pipeline_pass_subscription_update.yml b/config/feature_flags/development/widget_pipeline_pass_subscription_update.yml
deleted file mode 100644
index 764b0a59291..00000000000
--- a/config/feature_flags/development/widget_pipeline_pass_subscription_update.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: widget_pipeline_pass_subscription_update
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/132353
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/428633
-milestone: '16.6'
-type: development
-group: group::code review
-default_enabled: false
diff --git a/doc/architecture/blueprints/new_diffs.md b/doc/architecture/blueprints/new_diffs.md
index 57e84b722e2..91c568517da 100644
--- a/doc/architecture/blueprints/new_diffs.md
+++ b/doc/architecture/blueprints/new_diffs.md
@@ -118,6 +118,108 @@ To measure our success, we need to set meaningful metrics. These metrics should
---
<sup>1</sup>: [The Performance Inequality Gap, 2023](https://infrequently.org/2022/12/performance-baseline-2023/)
+### Front end
+
+Ideally, we would meet our definition of done and our accountability metrics on our first try.
+We also need to continue to stay within those boundaries as we move forward. To ensure this,
+we need to design an application architecture that:
+
+1. Is:
+ 1. Scalable.
+ 1. Malleable.
+ 1. Flexible.
+1. Considers itself a mission-critical part of the overall GitLab product.
+1. Treats itself as a complex, unique application with concerns that cannot be addressed
+ as side effects of other parts of the product.
+1. Can handle data access/format changes without making UI changes.
+1. Can handle UI changes without making data access/format changes.
+1. Provides a hookable, inspectable API and avoids code coupling.
+1. Separates:
+ - State and application data.
+ - Application behavior and UI.
+ - Data access and network access.
+
+#### High-level implementation
+
+(See [New Diffs: Technical Architecture Design](https://gitlab.com/gitlab-org/gitlab/-/issues/431276) for nicer visuals of this chart)
+
+```mermaid
+flowchart TB
+ classDef sticky fill:#d0cabf, color:black
+ stickyMetricsA>"Metrics 3, 4, & 5 apply to<br>the entire front end application"]
+
+ stickyMetricsA -.- fe
+ fe
+
+ Socket((WebSocket))
+
+ be
+
+subgraph fe [Front End]
+ stickyMetricsB>"Metrics 1 & 2 apply<br>to all UI elements"]
+ stickyInbound>"All data is formatted precisely<br>how the UI needs to interact with it"]
+ stickyOutbound>"All data is formatted precisely<br>how the back end expects it"]
+ stickyIdb>"Long-term.
+
+ e.g. diffs, MRs, emoji, notes, drafts, user-only data<br>like file reviews, collapse states, etc."]
+ stickySession>"Session-term.
+
+ e.g. selected tab, scroll position,<br>temporary changes to user settings, etc."]
+
+ Events([Event Hub])
+ UI[UI]
+ uiState((Local State))
+ Logic[Application Logic]
+ Normalizer[Data Normalizer]
+ Inbound{{Inbound Contract}}
+ Outbound{{Outbound Contract}}
+ Data[Data Access]
+ idb((indexedDB))
+ session((sessionStorage))
+ Network[Network Access]
+end
+
+subgraph be [Back End]
+ stickyApi>"A large list of defined actions a<br>Diffs/Merge Request UI could perform.
+
+ e.g.: <code>mergeRequest:notes:saveDraft</code> or<br><code>mergeRequest:changeStatus</code> (with <br><code>status: 'draft'</code> or <code>status: 'ready'</code>, etc.).
+
+ Must not expose any implementation detail,<br>like models, storage structure, etc."]
+ API[Activities API]
+ unk[\"?"/]
+
+ API -.- stickyApi
+end
+
+ %% Make stickies look like paper sort of?
+ class stickyMetricsA,stickyMetricsB,stickyInbound,stickyOutbound,stickyIdb,stickySession,stickyApi sticky
+
+ UI <--> uiState
+ stickyMetricsB -.- UI
+ Network ~~~ stickyMetricsB
+
+ Logic <--> Normalizer
+
+ Normalizer --> Outbound
+ Outbound --> Data
+ Inbound --> Normalizer
+ Data --> Inbound
+
+ Inbound -.- stickyInbound
+ Outbound -.- stickyOutbound
+
+ Data <--> idb
+ Data <--> session
+ idb -.- stickyIdb
+ session -.- stickySession
+
+ Events <--> UI
+ Events <--> Logic
+ Events <--> Data
+ Events <--> Network
+
+ Network --> Socket --> API --> unk
+```
<!--
This section should contain enough information that the specifics of your
change are understandable. This may include API specs (though not always
diff --git a/doc/development/ai_features/duo_chat.md b/doc/development/ai_features/duo_chat.md
index 2fde672aa7e..dfaad73220f 100644
--- a/doc/development/ai_features/duo_chat.md
+++ b/doc/development/ai_features/duo_chat.md
@@ -109,28 +109,17 @@ make sure a new fixture is generated and committed together with the change.
## Running the rspecs tagged with `real_ai_request`
-The following CI jobs for GitLab project run the rspecs tagged with `real_ai_request`:
-
-- `rspec-ee unit gitlab-duo-chat-zeroshot`:
- the job runs `ee/spec/lib/gitlab/llm/chain/agents/zero_shot/executor_real_requests_spec.rb`.
- The job is optionally triggered and allowed to fail.
-
-- `rspec-ee unit gitlab-duo-chat-qa`:
- The job runs the QA evaluation tests in
- `ee/spec/lib/gitlab/llm/chain/agents/zero_shot/qa_evaluation_spec.rb`.
- The job is optionally triggered and allowed to fail.
-
-- `rspec-ee unit gitlab-duo-chat-qa-fast`:
- The job runs a single QA evaluation test from `ee/spec/lib/gitlab/llm/chain/agents/zero_shot/qa_evaluation_spec.rb`.
- The job is always run and not allowed to fail. Although there's a chance that the QA test still might fail,
- it is cheap and fast to run and intended to prevent a regression in the QA test helpers.
+The rspecs tagged with the metadata `real_ai_request` can be run in GitLab project's CI by triggering
+`rspec-ee unit gitlab-duo-chat`.
+The former runs with Vertex APIs enabled. The CI jobs are optional and allowed to fail to account for
+the non-deterministic nature of LLM responses.
### Management of credentials and API keys for CI jobs
All API keys required to run the rspecs should be [masked](../../ci/variables/index.md#mask-a-cicd-variable)
The exception is GCP credentials as they contain characters that prevent them from being masked.
-Because the CI jobs need to run on MR branches, GCP credentials cannot be added as a protected variable
+Because `rspec-ee unit gitlab-duo-chat` needs to run on MR branches, GCP credentials cannot be added as a protected variable
and must be added as a regular CI variable.
For security, the GCP credentials and the associated project added to
GitLab project's CI must not be able to access any production infrastructure and sandboxed.
diff --git a/doc/editor_extensions/visual_studio_code/index.md b/doc/editor_extensions/visual_studio_code/index.md
index 70d0c79cfbf..ed56bed0be9 100644
--- a/doc/editor_extensions/visual_studio_code/index.md
+++ b/doc/editor_extensions/visual_studio_code/index.md
@@ -37,6 +37,7 @@ you can [configure](https://marketplace.visualstudio.com/items?itemName=GitLab.g
- [Features to display or hide](https://gitlab.com/gitlab-org/gitlab-vscode-extension#extension-settings).
- [Self-signed certificate](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#self-signed-certificates) information.
- [Code Suggestions](../../user/project/repository/code_suggestions/index.md).
+- [GitLab Duo Chat](../../user/gitlab_duo_chat.md#gitlab-workflow-extension-for-vs-code).
## Report issues with the extension
diff --git a/doc/user/gitlab_duo_chat.md b/doc/user/gitlab_duo_chat.md
index b763cd2bd27..92d46aae550 100644
--- a/doc/user/gitlab_duo_chat.md
+++ b/doc/user/gitlab_duo_chat.md
@@ -58,6 +58,30 @@ To use this feature, at least one group you're a member of must:
NOTE:
Only the last 50 messages are retained in the chat history. The chat history expires 3 days after last use.
+## Use GitLab Duo Chat in the Web IDE and VSCode **(ULTIMATE SAAS EXPERIMENT)**
+
+> Introduced in GitLab 16.6 as an [EXPERIMENT](../policy/experiment-beta-support.md#experiment).
+
+### Web IDE
+
+To use GitLab Duo Chat in the Web IDE:
+
+1. On the left sidebar, select **Search or go to** and find your project.
+1. Select a file. Then in the upper right, select **Edit > Open in Web IDE**.
+1. On the left sidebar, select **GitLab Duo Chat**. A drawer opens.
+1. In the text box, enter your question and press **Enter** or select **Send**. It may take a few seconds for the interactive AI chat to produce an answer.
+
+### GitLab Workflow extension for VS Code
+
+To disable GitLab Duo Chat in VS Code, go to the VS Code extension settings and clear the **Enable GitLab Duo Chat assistant** checkbox.
+
+To use GitLab Duo Chat in VS Code:
+
+1. Install the [GitLab Workflow extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow) in VS Code.
+1. In VS Code, open your GitLab project.
+1. On the left side of the toolbar, select **GitLab Duo Chat**. A drawer opens.
+1. In the text box, enter your question and press **Enter** or select **Send**. It may take a few seconds for the interactive AI chat to produce an answer.
+
## Give Feedback
Your feedback is important to us as we continually enhance your GitLab Duo Chat experience:
diff --git a/doc/user/group/saml_sso/group_sync.md b/doc/user/group/saml_sso/group_sync.md
index 3ff0668f436..587da517be9 100644
--- a/doc/user/group/saml_sso/group_sync.md
+++ b/doc/user/group/saml_sso/group_sync.md
@@ -77,11 +77,19 @@ example configurations for [Azure AD](../../../user/group/saml_sso/example_saml_
## Configure SAML Group Links
-When SAML is enabled, users with the Maintainer or Owner role
-see a new menu item in group **Settings > SAML Group Links**. You can configure one or more **SAML Group Links** to map
-a SAML identity provider group name to a GitLab role. This can be done for a top-level group or any subgroup.
-
-SAML Group Sync only manages a group if that group has one or more SAML group links. If a SAML group link is created then removed, the user remains in the group until they are removed from the group in the identity provider.
+When SAML is enabled, users with the Maintainer or Owner role see a new menu
+item in group **Settings > SAML Group Links**.
+
+- You can configure one or more **SAML Group Links** to map a SAML identity
+provider group name to a GitLab role.
+- Members of the SAML identity provider group are added as members of the GitLab
+group on their next SAML sign-in.
+- Group membership is evaluated each time a user signs in using SAML.
+- SAML Group Links can be configured for a top-level group or any subgroup.
+- SAML Group Sync only manages a group if that group has one or more SAML group
+links.
+ - If a SAML group link is created then removed, the user remains in the
+group until they are removed from the group in the identity provider.
Prerequisites:
@@ -109,8 +117,6 @@ Users granted:
- A lower or the same role with Group Sync are displayed as having
[inherited membership](../../project/members/index.md#display-inherited-members) of the group.
-SAML group membership is evaluated each time a user signs in.
-
### Use the API
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/290367) in GitLab 15.3.
diff --git a/doc/user/project/web_ide/index.md b/doc/user/project/web_ide/index.md
index fb2bd707c56..f2548806137 100644
--- a/doc/user/project/web_ide/index.md
+++ b/doc/user/project/web_ide/index.md
@@ -244,3 +244,7 @@ When you type in the Web IDE, you might get a four-character offset. To resolve
- Modify your `"editor.font"` setting.
For more information, see [VS Code issue 80170](https://github.com/microsoft/vscode/issues/80170).
+
+## Related topics
+
+- [Use GitLab Duo Chat in the Web IDE](../../gitlab_duo_chat.md#web-ide).
diff --git a/lefthook.yml b/lefthook.yml
index 8ba1f335906..c5b9ccf3392 100644
--- a/lefthook.yml
+++ b/lefthook.yml
@@ -63,7 +63,7 @@ pre-push:
tags: backend frontend view haml
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD | while read file;do git diff --unified=1 $(git merge-base origin/master HEAD)..HEAD $file | grep -Fqe '_(' && echo $file;done; true
glob: '*.{haml,rb,js,vue}'
- run: tooling/bin/gettext_extractor /dev/stdout --silent | diff - locale/gitlab.pot
+ run: tooling/bin/gettext_extractor /dev/stdout --silent | diff - locale/gitlab.pot || ( echo "\nPO files need to be updated. Try running bin/rake gettext:regenerate" && exit 1 )
docs-metadata: # See https://docs.gitlab.com/ee/development/documentation/#metadata
tags: documentation style
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
diff --git a/scripts/duo_chat/reporter.rb b/scripts/duo_chat/reporter.rb
index e72a393694f..686a49164a7 100755
--- a/scripts/duo_chat/reporter.rb
+++ b/scripts/duo_chat/reporter.rb
@@ -5,7 +5,7 @@ require 'gitlab'
require 'json'
class Reporter
- IDENTIFIABLE_NOTE_TAG = 'gitlab-org/ai-powered/ai-framework:duo-chat-qa-evaluation'
+ IDENTIFIABLE_NOTE_TAG = 'gitlab-org/ai-powered/ai-framework:duo-chat-qa-evaluation-'
GRADE_TO_EMOJI_MAPPING = {
correct: ":white_check_mark:",
@@ -25,7 +25,7 @@ class Reporter
.merge_request_notes(ci_project_id, merge_request_iid)
.auto_paginate
.select do |note|
- note.body.include? IDENTIFIABLE_NOTE_TAG
+ note.body.include? note_identifier_tag
end
note = report_notes.max_by { |note| Time.parse(note.created_at) }
@@ -47,13 +47,17 @@ class Reporter
private
def report_filename
- ENV['QA_EVAL_REPORT_FILENAME']
+ "#{ENV['DUO_RSPEC']}.md"
end
def artifact_path
File.join(ENV['CI_PROJECT_DIR'], report_filename)
end
+ def note_identifier_tag
+ "#{IDENTIFIABLE_NOTE_TAG}#{ENV['DUO_RSPEC']}"
+ end
+
def com_gitlab_client
@com_gitlab_client ||= Gitlab.client(
endpoint: "https://gitlab.com/api/v4",
@@ -63,7 +67,7 @@ class Reporter
def report_note
report = <<~MARKDOWN
- <!-- #{IDENTIFIABLE_NOTE_TAG} -->
+ <!-- #{note_identifier_tag} -->
## GitLab Duo Chat QA evaluation
@@ -101,7 +105,7 @@ class Reporter
if report.length > 1000000
return <<~MARKDOWN
- <!-- #{IDENTIFIABLE_NOTE_TAG} -->
+ <!-- #{note_identifier_tag} -->
## GitLab Duo Chat QA evaluation
@@ -121,7 +125,7 @@ class Reporter
def report_data
@report_data ||= Dir[File.join(ENV['CI_PROJECT_DIR'], "tmp/duo_chat/qa*.json")]
- .flat_map { |file| JSON.parse(File.read(file)) }
+ .map { |file| JSON.parse(File.read(file)) }
end
def eval_content
diff --git a/spec/frontend/vue_merge_request_widget/components/checks/rebase_spec.js b/spec/frontend/vue_merge_request_widget/components/checks/rebase_spec.js
index d6c01aee3b1..d621999337d 100644
--- a/spec/frontend/vue_merge_request_widget/components/checks/rebase_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/checks/rebase_spec.js
@@ -28,7 +28,7 @@ const mockPipelineNodes = [
const mockQueryHandler = ({
rebaseInProgress = false,
targetBranch = '',
- pushToSourceBranch = false,
+ pushToSourceBranch = true,
nodes = mockPipelineNodes,
} = {}) =>
jest.fn().mockResolvedValue({
@@ -279,7 +279,7 @@ describe('Merge request merge checks rebase component', () => {
await waitForPromises();
- expect(findRebaseWithoutCiButton().exists()).toBe(true);
+ expect(findRebaseWithoutCiButton().exists()).toBe(false);
});
});
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 2e552c8d524..07052113d5d 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -987,6 +987,70 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
describe '#artifacts_public?' do
subject { build.artifacts_public? }
+ context 'when non_public_artifacts flag is disabled' do
+ before do
+ stub_feature_flags(non_public_artifacts: false)
+ end
+
+ context 'artifacts with defaults - public' do
+ let(:build) { create(:ci_build, :artifacts, pipeline: pipeline) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'non public artifacts' do
+ let(:build) { create(:ci_build, :private_artifacts, pipeline: pipeline) }
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ context 'artifacts with defaults - public' do
+ let(:build) { create(:ci_build, :artifacts, pipeline: pipeline) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'non public artifacts' do
+ let(:build) { create(:ci_build, :private_artifacts, pipeline: pipeline) }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'no artifacts' do
+ let(:build) { create(:ci_build, pipeline: pipeline) }
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ describe '#artifact_is_public_in_config?' do
+ subject { build.artifact_is_public_in_config? }
+
+ context 'when non_public_artifacts flag is disabled' do
+ before do
+ stub_feature_flags(non_public_artifacts: false)
+ end
+
+ context 'artifacts with defaults' do
+ let(:build) { create(:ci_build, :artifacts, pipeline: pipeline) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'non public artifacts' do
+ let(:build) { create(:ci_build, :with_private_artifacts_config, pipeline: pipeline) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'public artifacts' do
+ let(:build) { create(:ci_build, :with_public_artifacts_config, pipeline: pipeline) }
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
context 'artifacts with defaults' do
let(:build) { create(:ci_build, :artifacts, pipeline: pipeline) }
@@ -994,10 +1058,22 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
end
context 'non public artifacts' do
- let(:build) { create(:ci_build, :artifacts, :with_private_artifacts_config, pipeline: pipeline) }
+ let(:build) { create(:ci_build, :with_private_artifacts_config, pipeline: pipeline) }
it { is_expected.to be_falsey }
end
+
+ context 'public artifacts' do
+ let(:build) { create(:ci_build, :with_public_artifacts_config, pipeline: pipeline) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'no artifacts' do
+ let(:build) { create(:ci_build, pipeline: pipeline) }
+
+ it { is_expected.to be_truthy }
+ end
end
describe '#artifacts_expired?' do
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 9696ba7b3ee..61522c1e4dd 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -2028,17 +2028,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep, feature_category:
end
end
- context 'when only_allow_merge_if_pipeline_succeeds? returns false and widget_pipeline_pass_subscription_update disabled' do
- let(:only_allow_merge_if_pipeline_succeeds?) { false }
-
- before do
- stub_feature_flags(widget_pipeline_pass_subscription_update: false)
- end
-
- it_behaves_like 'state transition not triggering GraphQL subscription mergeRequestMergeStatusUpdated'
- end
-
- context 'when only_allow_merge_if_pipeline_succeeds? returns false and widget_pipeline_pass_subscription_update enabled' do
+ context 'when only_allow_merge_if_pipeline_succeeds? returns false' do
let(:only_allow_merge_if_pipeline_succeeds?) { false }
it_behaves_like 'triggers GraphQL subscription mergeRequestMergeStatusUpdated' do
diff --git a/spec/requests/api/ci/job_artifacts_spec.rb b/spec/requests/api/ci/job_artifacts_spec.rb
index b96ba356855..9fb3f7e85ba 100644
--- a/spec/requests/api/ci/job_artifacts_spec.rb
+++ b/spec/requests/api/ci/job_artifacts_spec.rb
@@ -187,7 +187,7 @@ RSpec.describe API::Ci::JobArtifacts, feature_category: :build_artifacts do
end
context 'when project is public with artifacts that are non public' do
- let(:job) { create(:ci_build, :artifacts, :with_private_artifacts_config, pipeline: pipeline) }
+ let(:job) { create(:ci_build, :private_artifacts, :with_private_artifacts_config, pipeline: pipeline) }
it 'rejects access to artifacts' do
project.update_column(:visibility_level, Gitlab::VisibilityLevel::PUBLIC)
@@ -433,7 +433,7 @@ RSpec.describe API::Ci::JobArtifacts, feature_category: :build_artifacts do
context 'when public project guest and artifacts are non public' do
let(:api_user) { guest }
- let(:job) { create(:ci_build, :artifacts, :with_private_artifacts_config, pipeline: pipeline) }
+ let(:job) { create(:ci_build, :private_artifacts, :with_private_artifacts_config, pipeline: pipeline) }
before do
project.update_column(:visibility_level,
@@ -639,7 +639,7 @@ RSpec.describe API::Ci::JobArtifacts, feature_category: :build_artifacts do
end
context 'when project is public with non public artifacts' do
- let(:job) { create(:ci_build, :artifacts, :with_private_artifacts_config, pipeline: pipeline, user: api_user) }
+ let(:job) { create(:ci_build, :private_artifacts, :with_private_artifacts_config, pipeline: pipeline, user: api_user) }
let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC }
let(:public_builds) { true }
diff --git a/spec/serializers/build_details_entity_spec.rb b/spec/serializers/build_details_entity_spec.rb
index 874bcbfceaf..9ef1e91ebcd 100644
--- a/spec/serializers/build_details_entity_spec.rb
+++ b/spec/serializers/build_details_entity_spec.rb
@@ -281,7 +281,7 @@ RSpec.describe BuildDetailsEntity do
end
context 'when the build has non public archive type artifacts' do
- let(:build) { create(:ci_build, :artifacts, :with_private_artifacts_config, pipeline: pipeline) }
+ let(:build) { create(:ci_build, :private_artifacts, :with_private_artifacts_config, pipeline: pipeline) }
it 'does not expose non public artifacts' do
expect(subject.keys).not_to include(:artifact)
diff --git a/spec/services/ci/job_artifacts/create_service_spec.rb b/spec/services/ci/job_artifacts/create_service_spec.rb
index a23ba250daf..ffb6bd9d145 100644
--- a/spec/services/ci/job_artifacts/create_service_spec.rb
+++ b/spec/services/ci/job_artifacts/create_service_spec.rb
@@ -139,12 +139,18 @@ RSpec.describe Ci::JobArtifacts::CreateService, :clean_gitlab_redis_shared_state
shared_examples_for 'handling accessibility' do
shared_examples 'public accessibility' do
it 'sets accessibility to public level' do
+ subject
+
+ expect(job.job_artifacts).not_to be_empty
expect(job.job_artifacts).to all be_public_accessibility
end
end
shared_examples 'private accessibility' do
it 'sets accessibility to private level' do
+ subject
+
+ expect(job.job_artifacts).not_to be_empty
expect(job.job_artifacts).to all be_private_accessibility
end
end