diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-07-20 00:08:57 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-07-20 00:08:57 +0300 |
commit | 22f0adb0e722aab66281a572008e01816b90af5b (patch) | |
tree | 59a79e16093c455394a515d74d70e9e451b75da3 | |
parent | 3f0db3db2ad99a74c3969bf2e930814004ccf1ec (diff) |
Add latest changes from gitlab-org/gitlab@master
-rw-r--r-- | .gitlab/issue_templates/Feature Proposal - basic.md | 5 | ||||
-rw-r--r-- | app/assets/javascripts/pages/admin/abuse_reports/index.js | 2 | ||||
-rw-r--r-- | app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/index.js | 2 | ||||
-rw-r--r-- | app/assets/javascripts/pages/admin/integrations/edit/index.js | 6 | ||||
-rw-r--r-- | app/assets/javascripts/pages/admin/jobs/index/index.js | 6 | ||||
-rw-r--r-- | app/assets/javascripts/pages/admin/labels/index/index.js | 6 | ||||
-rw-r--r-- | app/assets/javascripts/pages/admin/spam_logs/index.js | 2 | ||||
-rw-r--r-- | app/graphql/types/project_type.rb | 12 | ||||
-rw-r--r-- | app/models/project.rb | 2 | ||||
-rw-r--r-- | app/services/projects/lfs_pointers/lfs_download_service.rb | 10 | ||||
-rw-r--r-- | doc/api/graphql/reference/index.md | 2 | ||||
-rw-r--r-- | doc/api/projects.md | 3 | ||||
-rw-r--r-- | doc/user/permissions.md | 44 | ||||
-rw-r--r-- | lib/api/helpers/projects_helpers.rb | 2 | ||||
-rw-r--r-- | spec/graphql/types/project_type_spec.rb | 55 | ||||
-rw-r--r-- | spec/requests/api/projects_spec.rb | 26 | ||||
-rw-r--r-- | spec/services/projects/lfs_pointers/lfs_download_service_spec.rb | 20 |
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 } |