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:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-07-20 00:08:57 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-07-20 00:08:57 +0300
commit22f0adb0e722aab66281a572008e01816b90af5b (patch)
tree59a79e16093c455394a515d74d70e9e451b75da3
parent3f0db3db2ad99a74c3969bf2e930814004ccf1ec (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/issue_templates/Feature Proposal - basic.md5
-rw-r--r--app/assets/javascripts/pages/admin/abuse_reports/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/integrations/edit/index.js6
-rw-r--r--app/assets/javascripts/pages/admin/jobs/index/index.js6
-rw-r--r--app/assets/javascripts/pages/admin/labels/index/index.js6
-rw-r--r--app/assets/javascripts/pages/admin/spam_logs/index.js2
-rw-r--r--app/graphql/types/project_type.rb12
-rw-r--r--app/models/project.rb2
-rw-r--r--app/services/projects/lfs_pointers/lfs_download_service.rb10
-rw-r--r--doc/api/graphql/reference/index.md2
-rw-r--r--doc/api/projects.md3
-rw-r--r--doc/user/permissions.md44
-rw-r--r--lib/api/helpers/projects_helpers.rb2
-rw-r--r--spec/graphql/types/project_type_spec.rb55
-rw-r--r--spec/requests/api/projects_spec.rb26
-rw-r--r--spec/services/projects/lfs_pointers/lfs_download_service_spec.rb20
17 files changed, 162 insertions, 43 deletions
diff --git a/.gitlab/issue_templates/Feature Proposal - basic.md b/.gitlab/issue_templates/Feature Proposal - basic.md
index 099243c05ca..0c05b7a0165 100644
--- a/.gitlab/issue_templates/Feature Proposal - basic.md
+++ b/.gitlab/issue_templates/Feature Proposal - basic.md
@@ -5,7 +5,6 @@
<!-- Use this section to explain the feature and how it will work. It can be helpful to add technical details, design proposals, and links to related epics or issues. -->
<!-- Consider adding related issues and epics to this issue. You can also reference the Feature Proposal Template (https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20proposal%20-%20detailed.md) for additional details to consider adding to this issue. Additionally, as a data oriented organization, when your feature exits planning breakdown, consider adding the `What does success look like, and how can we measure that?` section.
-
-/label ~"group::" ~"section::" ~"Category::" ~"GitLab Core"/~"GitLab Premium"/~"GitLab Ultimate"
-
-->
+
+/label ~feature::addition ~"group::" ~"section::" ~"Category:" ~"GitLab Core"/~"GitLab Premium"/~"GitLab Ultimate"
diff --git a/app/assets/javascripts/pages/admin/abuse_reports/index.js b/app/assets/javascripts/pages/admin/abuse_reports/index.js
index a88d35796f7..ab29f9149f7 100644
--- a/app/assets/javascripts/pages/admin/abuse_reports/index.js
+++ b/app/assets/javascripts/pages/admin/abuse_reports/index.js
@@ -5,4 +5,4 @@ import AbuseReports from './abuse_reports';
new AbuseReports(); /* eslint-disable-line no-new */
new UsersSelect(); /* eslint-disable-line no-new */
-document.addEventListener('DOMContentLoaded', initDeprecatedRemoveRowBehavior);
+initDeprecatedRemoveRowBehavior();
diff --git a/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/index.js b/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/index.js
index a2fca238613..a5305777dd5 100644
--- a/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/index.js
+++ b/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/index.js
@@ -1,3 +1,3 @@
import setup from '~/admin/application_settings/setup_metrics_and_profiling';
-document.addEventListener('DOMContentLoaded', setup);
+setup();
diff --git a/app/assets/javascripts/pages/admin/integrations/edit/index.js b/app/assets/javascripts/pages/admin/integrations/edit/index.js
index ba4b271f09e..8002fa8bf78 100644
--- a/app/assets/javascripts/pages/admin/integrations/edit/index.js
+++ b/app/assets/javascripts/pages/admin/integrations/edit/index.js
@@ -1,7 +1,7 @@
import IntegrationSettingsForm from '~/integrations/integration_settings_form';
import PrometheusMetrics from '~/prometheus_metrics/prometheus_metrics';
-document.addEventListener('DOMContentLoaded', () => {
+function initIntegrations() {
const prometheusSettingsWrapper = document.querySelector('.js-prometheus-metrics-monitoring');
const integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
integrationSettingsForm.init();
@@ -10,4 +10,6 @@ document.addEventListener('DOMContentLoaded', () => {
const prometheusMetrics = new PrometheusMetrics('.js-prometheus-metrics-monitoring');
prometheusMetrics.loadActiveMetrics();
}
-});
+}
+
+initIntegrations();
diff --git a/app/assets/javascripts/pages/admin/jobs/index/index.js b/app/assets/javascripts/pages/admin/jobs/index/index.js
index 46ddb95299d..a4d89889d57 100644
--- a/app/assets/javascripts/pages/admin/jobs/index/index.js
+++ b/app/assets/javascripts/pages/admin/jobs/index/index.js
@@ -5,7 +5,7 @@ import stopJobsModal from './components/stop_jobs_modal.vue';
Vue.use(Translate);
-document.addEventListener('DOMContentLoaded', () => {
+function initJobs() {
const buttonId = 'js-stop-jobs-button';
const modalId = 'stop-jobs-modal';
const stopJobsButton = document.getElementById(buttonId);
@@ -31,4 +31,6 @@ document.addEventListener('DOMContentLoaded', () => {
},
});
}
-});
+}
+
+initJobs();
diff --git a/app/assets/javascripts/pages/admin/labels/index/index.js b/app/assets/javascripts/pages/admin/labels/index/index.js
index 17ee7c03ed6..0ceab3b922f 100644
--- a/app/assets/javascripts/pages/admin/labels/index/index.js
+++ b/app/assets/javascripts/pages/admin/labels/index/index.js
@@ -1,4 +1,4 @@
-document.addEventListener('DOMContentLoaded', () => {
+function initLabels() {
const pagination = document.querySelector('.labels .gl-pagination');
const emptyState = document.querySelector('.labels .nothing-here-block.hidden');
@@ -18,4 +18,6 @@ document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.js-remove-label').forEach((row) => {
row.addEventListener('ajax:success', removeLabelSuccessCallback);
});
-});
+}
+
+initLabels();
diff --git a/app/assets/javascripts/pages/admin/spam_logs/index.js b/app/assets/javascripts/pages/admin/spam_logs/index.js
index e5ab5d43bbf..ac850a6467b 100644
--- a/app/assets/javascripts/pages/admin/spam_logs/index.js
+++ b/app/assets/javascripts/pages/admin/spam_logs/index.js
@@ -1,3 +1,3 @@
import initDeprecatedRemoveRowBehavior from '~/behaviors/deprecated_remove_row_behavior';
-document.addEventListener('DOMContentLoaded', initDeprecatedRemoveRowBehavior);
+initDeprecatedRemoveRowBehavior();
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index 7e4c0c03dd6..968635f9e6e 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -59,8 +59,6 @@ module Types
field :visibility, GraphQL::STRING_TYPE, null: true,
description: 'Visibility of the project.'
- field :container_registry_enabled, GraphQL::BOOLEAN_TYPE, null: true,
- description: 'Indicates if the project stores Docker container images in a container registry.'
field :shared_runners_enabled, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Indicates if shared runners are enabled for the project.'
field :lfs_enabled, GraphQL::BOOLEAN_TYPE, null: true,
@@ -77,9 +75,15 @@ module Types
field :avatar_url, GraphQL::STRING_TYPE, null: true, calls_gitaly: true,
description: 'URL to avatar image file of the project.'
- %i[issues merge_requests wiki snippets].each do |feature|
+ {
+ issues: "Issues are",
+ merge_requests: "Merge Requests are",
+ wiki: 'Wikis are',
+ snippets: 'Snippets are',
+ container_registry: 'Container Registry is'
+ }.each do |feature, name_string|
field "#{feature}_enabled", GraphQL::BOOLEAN_TYPE, null: true,
- description: "Indicates if #{feature.to_s.titleize.pluralize} are enabled for the current user"
+ description: "Indicates if #{name_string} enabled for the current user"
define_method "#{feature}_enabled" do
object.feature_available?(feature, context[:current_user])
diff --git a/app/models/project.rb b/app/models/project.rb
index 6d99fa31c3d..9e6e29aadda 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -417,7 +417,7 @@ class Project < ApplicationRecord
delegate :scheduled?, :started?, :in_progress?, :failed?, :finished?,
prefix: :import, to: :import_state, allow_nil: true
delegate :squash_always?, :squash_never?, :squash_enabled_by_default?, :squash_readonly?, to: :project_setting
- delegate :squash_option, to: :project_setting
+ delegate :squash_option, :squash_option=, to: :project_setting
delegate :previous_default_branch, :previous_default_branch=, to: :project_setting
delegate :no_import?, to: :import_state, allow_nil: true
delegate :name, to: :owner, allow_nil: true, prefix: true
diff --git a/app/services/projects/lfs_pointers/lfs_download_service.rb b/app/services/projects/lfs_pointers/lfs_download_service.rb
index cf52b47a15e..fe9dce26029 100644
--- a/app/services/projects/lfs_pointers/lfs_download_service.rb
+++ b/app/services/projects/lfs_pointers/lfs_download_service.rb
@@ -61,8 +61,10 @@ module Projects
def download_and_save_file!(file)
digester = Digest::SHA256.new
fetch_file do |fragment|
- digester << fragment
- file.write(fragment)
+ if digest_fragment?(fragment)
+ digester << fragment
+ file.write(fragment)
+ end
raise_size_error! if file.size > lfs_size
end
@@ -71,6 +73,10 @@ module Projects
raise_oid_error! if digester.hexdigest != lfs_oid
end
+ def digest_fragment?(fragment)
+ fragment.http_response.is_a?(Net::HTTPSuccess)
+ end
+
def download_options
http_options = { headers: lfs_headers, stream_body: true }
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 8d622371257..db93accc86a 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -11402,7 +11402,7 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="projectcodecoveragesummary"></a>`codeCoverageSummary` | [`CodeCoverageSummary`](#codecoveragesummary) | Code coverage summary associated with the project. |
| <a id="projectcomplianceframeworks"></a>`complianceFrameworks` | [`ComplianceFrameworkConnection`](#complianceframeworkconnection) | Compliance frameworks associated with the project. (see [Connections](#connections)) |
| <a id="projectcontainerexpirationpolicy"></a>`containerExpirationPolicy` | [`ContainerExpirationPolicy`](#containerexpirationpolicy) | The container expiration policy of the project. |
-| <a id="projectcontainerregistryenabled"></a>`containerRegistryEnabled` | [`Boolean`](#boolean) | Indicates if the project stores Docker container images in a container registry. |
+| <a id="projectcontainerregistryenabled"></a>`containerRegistryEnabled` | [`Boolean`](#boolean) | Indicates if Container Registry is enabled for the current user. |
| <a id="projectcontainerrepositoriescount"></a>`containerRepositoriesCount` | [`Int!`](#int) | Number of container repositories in the project. |
| <a id="projectcreatedat"></a>`createdAt` | [`Time`](#time) | Timestamp of the project creation. |
| <a id="projectdastprofiles"></a>`dastProfiles` | [`DastProfileConnection`](#dastprofileconnection) | DAST Profiles associated with the project. (see [Connections](#connections)) |
diff --git a/doc/api/projects.md b/doc/api/projects.md
index dc9e59f0cad..72de8ab6844 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -1215,6 +1215,7 @@ POST /projects
| `show_default_award_emojis` | boolean | **{dotted-circle}** No | Show default award emojis. |
| `snippets_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `snippets_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable snippets for this project. Use `snippets_access_level` instead. |
+| `squash_option` | string | **{dotted-circle}** No | One of `never`, `always`, `default_on`, or `default_off`. |
| `tag_list` | array | **{dotted-circle}** No | _([Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/328226) in GitLab 14.0)_ The list of tags for a project; put array of tags, that should be finally assigned to a project. Use `topics` instead. |
| `template_name` | string | **{dotted-circle}** No | When used without `use_custom_template`, name of a [built-in project template](../user/project/working_with_projects.md#built-in-templates). When used with `use_custom_template`, name of a custom project template. |
| `template_project_id` **(PREMIUM)** | integer | **{dotted-circle}** No | When used with `use_custom_template`, project ID of a custom project template. This is preferable to using `template_name` since `template_name` may be ambiguous. |
@@ -1290,6 +1291,7 @@ POST /projects/user/:user_id
| `show_default_award_emojis` | boolean | **{dotted-circle}** No | Show default award emojis. |
| `snippets_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `snippets_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable snippets for this project. Use `snippets_access_level` instead. |
+| `squash_option` | string | **{dotted-circle}** No | One of `never`, `always`, `default_on`, or `default_off`. |
| `suggestion_commit_message` | string | **{dotted-circle}** No | The commit message used to apply merge request [suggestions](../user/project/merge_requests/reviews/suggestions.md). |
| `tag_list` | array | **{dotted-circle}** No | _([Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/328226) in GitLab 14.0)_ The list of tags for a project; put array of tags, that should be finally assigned to a project. Use `topics` instead. |
| `template_name` | string | **{dotted-circle}** No | When used without `use_custom_template`, name of a [built-in project template](../user/project/working_with_projects.md#built-in-templates). When used with `use_custom_template`, name of a custom project template. |
@@ -1369,6 +1371,7 @@ PUT /projects/:id
| `show_default_award_emojis` | boolean | **{dotted-circle}** No | Show default award emojis. |
| `snippets_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `snippets_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable snippets for this project. Use `snippets_access_level` instead. |
+| `squash_option` | string | **{dotted-circle}** No | One of `never`, `always`, `default_on`, or `default_off`. |
| `suggestion_commit_message` | string | **{dotted-circle}** No | The commit message used to apply merge request suggestions. |
| `tag_list` | array | **{dotted-circle}** No | _([Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/328226) in GitLab 14.0)_ The list of tags for a project; put array of tags, that should be finally assigned to a project. Use `topics` instead. |
| `topics` | array | **{dotted-circle}** No | The list of topics for the project. This replaces any existing topics that are already added to the project. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/328226) in GitLab 14.0.)_ |
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 45d516c4f49..0c3428ee7ee 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -265,50 +265,50 @@ The following table lists group permissions available for each role:
| Action | Guest | Reporter | Developer | Maintainer | Owner |
|--------------------------------------------------------|-------|----------|-----------|------------|-------|
| Browse group | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Edit SAML SSO Billing **(PREMIUM SAAS)** | ✓ | ✓ | ✓ | ✓ | ✓ (4) |
+| View Contribution analytics | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View group epic **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
| View group wiki pages **(PREMIUM)** | ✓ (6) | ✓ | ✓ | ✓ | ✓ |
+| View Insights **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
| View Insights charts **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
-| View group epic **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View Issue analytics **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
+| View Value Stream analytics | ✓ | ✓ | ✓ | ✓ | ✓ |
| Create/edit group epic **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
| Create/edit/delete epic boards **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
| Manage group labels | | ✓ | ✓ | ✓ | ✓ |
-| See a container registry | | ✓ | ✓ | ✓ | ✓ |
| Pull [packages](packages/index.md) | | ✓ | ✓ | ✓ | ✓ |
-| Publish [packages](packages/index.md) | | | ✓ | ✓ | ✓ |
+| View a container registry | | ✓ | ✓ | ✓ | ✓ |
+| View Group DevOps Adoption **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
| View metrics dashboard annotations | | ✓ | ✓ | ✓ | ✓ |
+| View Productivity analytics **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
+| Create and edit group wiki pages **(PREMIUM)** | | | ✓ | ✓ | ✓ |
| Create project in group | | | ✓ (3)(5) | ✓ (3) | ✓ (3) |
-| Share (invite) groups with groups | | | | | ✓ |
| Create/edit/delete group milestones | | | ✓ | ✓ | ✓ |
| Create/edit/delete iterations | | | ✓ | ✓ | ✓ |
+| Create/edit/delete metrics dashboard annotations | | | ✓ | ✓ | ✓ |
| Enable/disable a dependency proxy | | | ✓ | ✓ | ✓ |
-| Create and edit group wiki pages **(PREMIUM)** | | | ✓ | ✓ | ✓ |
+| Publish [packages](packages/index.md) | | | ✓ | ✓ | ✓ |
| Use security dashboard **(ULTIMATE)** | | | ✓ | ✓ | ✓ |
-| Create/edit/delete metrics dashboard annotations | | | ✓ | ✓ | ✓ |
-| View/manage group-level Kubernetes cluster | | | | ✓ | ✓ |
+| View group Audit Events | | | ✓ (7) | ✓ (7) | ✓ |
| Create subgroup | | | | ✓ (1) | ✓ |
| Delete group wiki pages **(PREMIUM)** | | | | ✓ | ✓ |
| Edit epic comments (posted by any user) **(ULTIMATE)** | | | | ✓ (2) | ✓ (2) |
-| Edit group settings | | | | | ✓ |
-| Manage group level CI/CD variables | | | | | ✓ |
| List group deploy tokens | | | | ✓ | ✓ |
+| Manage [group push rules](group/index.md#group-push-rules) **(PREMIUM)** | | | | ✓ | ✓ |
+| View/manage group-level Kubernetes cluster | | | | ✓ | ✓ |
+| Administer project compliance frameworks | | | | | ✓ |
| Create/Delete group deploy tokens | | | | | ✓ |
-| Manage group members | | | | | ✓ |
| Delete group | | | | | ✓ |
| Delete group epic **(PREMIUM)** | | | | | ✓ |
-| Edit SAML SSO Billing **(PREMIUM SAAS)** | ✓ | ✓ | ✓ | ✓ | ✓ (4) |
-| View group Audit Events | | | ✓ (7) | ✓ (7) | ✓ |
| Disable notification emails | | | | | ✓ |
-| View Contribution analytics | ✓ | ✓ | ✓ | ✓ | ✓ |
-| View Group DevOps Adoption **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ |
-| View Insights **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
-| View Issue analytics **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ |
-| View Productivity analytics **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ |
-| View Value Stream analytics | ✓ | ✓ | ✓ | ✓ | ✓ |
+| Edit group settings | | | | | ✓ |
+| Filter members by 2FA status | | | | | ✓ |
+| Manage group level CI/CD variables | | | | | ✓ |
+| Manage group members | | | | | ✓ |
+| Share (invite) groups with groups | | | | | ✓ |
+| View 2FA status of members | | | | | ✓ |
| View Billing **(FREE SAAS)** | | | | | ✓ (4) |
| View Usage Quotas **(FREE SAAS)** | | | | | ✓ (4) |
-| Manage [group push rules](group/index.md#group-push-rules) **(PREMIUM)** | | | | ✓ | ✓ |
-| View 2FA status of members | | | | | ✓ |
-| Filter members by 2FA status | | | | | ✓ |
-| Administer project compliance frameworks | | | | | ✓ |
1. Groups can be set to [allow either Owners or Owners and
Maintainers to create subgroups](group/subgroups/index.md#creating-a-subgroup)
diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb
index 69a83043617..272452bd8db 100644
--- a/lib/api/helpers/projects_helpers.rb
+++ b/lib/api/helpers/projects_helpers.rb
@@ -66,6 +66,7 @@ module API
optional :autoclose_referenced_issues, type: Boolean, desc: 'Flag indication if referenced issues auto-closing is enabled'
optional :repository_storage, type: String, desc: 'Which storage shard the repository is on. Available only to admins'
optional :packages_enabled, type: Boolean, desc: 'Enable project packages feature'
+ optional :squash_option, type: String, values: %w(never always default_on default_off), desc: 'Squash default for project. One of `never`, `always`, `default_on`, or `default_off`.'
end
params :optional_project_params_ee do
@@ -145,6 +146,7 @@ module API
:request_access_enabled,
:resolve_outdated_diff_discussions,
:restrict_user_defined_variables,
+ :squash_option,
:shared_runners_enabled,
:snippets_access_level,
:tag_list,
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index 8a1a4b17cc6..a22110e8338 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -39,6 +39,61 @@ RSpec.describe GitlabSchema.types['Project'] do
expect(described_class).to include_graphql_fields(*expected_fields)
end
+ describe 'container_registry_enabled' do
+ let_it_be(:project, reload: true) { create(:project, :public) }
+ let_it_be(:user) { create(:user) }
+
+ let(:query) do
+ %(
+ query {
+ project(fullPath: "#{project.full_path}") {
+ containerRegistryEnabled
+ }
+ }
+ )
+ end
+
+ subject { GitlabSchema.execute(query, context: { current_user: user }).as_json }
+
+ context 'with `enabled` visibility' do
+ before do
+ project.project_feature.update_column(:container_registry_access_level, ProjectFeature::ENABLED)
+ end
+
+ context 'with non member user' do
+ it 'returns true' do
+ expect(subject.dig('data', 'project', 'containerRegistryEnabled')).to eq(true)
+ end
+ end
+ end
+
+ context 'with `private` visibility' do
+ before do
+ project.project_feature.update_column(:container_registry_access_level, ProjectFeature::PRIVATE)
+ end
+
+ context 'with reporter user' do
+ before do
+ project.add_reporter(user)
+ end
+
+ it 'returns true' do
+ expect(subject.dig('data', 'project', 'containerRegistryEnabled')).to eq(true)
+ end
+ end
+
+ context 'with guest user' do
+ before do
+ project.add_guest(user)
+ end
+
+ it 'returns false' do
+ expect(subject.dig('data', 'project', 'containerRegistryEnabled')).to eq(false)
+ end
+ end
+ end
+ end
+
describe 'sast_ci_configuration' do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 2f0997b632d..a869866c698 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -999,7 +999,8 @@ RSpec.describe API::Projects do
request_access_enabled: true,
only_allow_merge_if_all_discussions_are_resolved: false,
ci_config_path: 'a/custom/path',
- merge_method: 'ff'
+ merge_method: 'ff',
+ squash_option: 'always'
}).tap do |attrs|
attrs[:operations_access_level] = 'disabled'
attrs[:analytics_access_level] = 'disabled'
@@ -3136,6 +3137,29 @@ RSpec.describe API::Projects do
expect(json_response['topics']).to eq(%w[topic2])
end
+
+ it 'updates squash_option' do
+ project3.update!(squash_option: 'always')
+
+ project_param = { squash_option: "default_on" }
+
+ expect { put api("/projects/#{project3.id}", user), params: project_param }
+ .to change { project3.reload.squash_option }
+ .from('always')
+ .to('default_on')
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['squash_option']).to eq("default_on")
+ end
+
+ it 'does not update an invalid squash_option' do
+ project_param = { squash_option: "jawn" }
+
+ expect { put api("/projects/#{project3.id}", user), params: project_param }
+ .not_to change { project3.reload.squash_option }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
end
context 'when authenticated as project maintainer' do
diff --git a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
index 8f6aab84664..f27ebb2e19e 100644
--- a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
+++ b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
@@ -106,6 +106,26 @@ RSpec.describe Projects::LfsPointers::LfsDownloadService do
end
end
+ context 'when file download returns a redirect' do
+ let(:redirect_link) { 'http://external-link' }
+
+ before do
+ stub_full_request(download_link).to_return(status: 301, body: 'You are being redirected', headers: { 'Location' => redirect_link } )
+ stub_full_request(redirect_link).to_return(body: lfs_content)
+ end
+
+ it_behaves_like 'lfs object is created'
+
+ it 'correctly stores lfs object' do
+ subject.execute
+
+ new_lfs_object = LfsObject.first
+
+ expect(new_lfs_object).to have_attributes(oid: oid, size: size)
+ expect(File.binread(new_lfs_object.file.file.file)).to eq lfs_content
+ end
+ end
+
context 'when downloaded lfs file has a different size' do
let(:size) { 1 }