diff --git a/app/controllers/projects/deploy_tokens_controller.rb b/app/controllers/projects/deploy_tokens_controller.rb index 3c890bbafdf..42c2d8b17f1 100644 --- a/app/controllers/projects/deploy_tokens_controller.rb +++ b/app/controllers/projects/deploy_tokens_controller.rb @@ -12,3 +12,5 @@ class Projects::DeployTokensController < Projects::ApplicationController redirect_to project_settings_repository_path(project, anchor: 'js-deploy-tokens') end end + +Projects::DeployTokensController.prepend_mod diff --git a/app/finders/projects/members/effective_access_level_finder.rb b/app/finders/projects/members/effective_access_level_finder.rb index d17609ff59f..90474aba02c 100644 --- a/app/finders/projects/members/effective_access_level_finder.rb +++ b/app/finders/projects/members/effective_access_level_finder.rb @@ -89,11 +89,7 @@ module Projects # OWNER access level def project_owner user_id = project.namespace.owner.id - access_level = if ::Feature.enabled?(:personal_project_owner_with_owner_access, default_enabled: :yaml) - Gitlab::Access::OWNER - else - Gitlab::Access::MAINTAINER - end + access_level = Gitlab::Access::OWNER Member .from(generate_from_statement([[user_id, access_level]])) # rubocop: disable CodeReuse/ActiveRecord diff --git a/app/models/concerns/select_for_project_authorization.rb b/app/models/concerns/select_for_project_authorization.rb index e176e29f9d9..5a7e16eb2c4 100644 --- a/app/models/concerns/select_for_project_authorization.rb +++ b/app/models/concerns/select_for_project_authorization.rb @@ -11,11 +11,7 @@ module SelectForProjectAuthorization # workaround until we migrate Project#owners to have membership with # OWNER access level def select_project_owner_for_project_authorization - if ::Feature.enabled?(:personal_project_owner_with_owner_access, default_enabled: :yaml) - select(["projects.id AS project_id", "#{Gitlab::Access::OWNER} AS access_level"]) - else - select(["projects.id AS project_id", "#{Gitlab::Access::MAINTAINER} AS access_level"]) - end + select(["projects.id AS project_id", "#{Gitlab::Access::OWNER} AS access_level"]) end end end diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb index d75a25942c8..3e19f294253 100644 --- a/app/models/members/project_member.rb +++ b/app/models/members/project_member.rb @@ -94,14 +94,7 @@ class ProjectMember < Member override :access_level_inclusion def access_level_inclusion - allowed_values = if ::Feature.enabled?(:personal_project_owner_with_owner_access, - default_enabled: :yaml) - Gitlab::Access.all_values - else - Gitlab::Access.values - end - - unless access_level.in?(allowed_values) + unless access_level.in?(Gitlab::Access.all_values) errors.add(:access_level, "is not included in the list") end end diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb index ecae90e576d..252e1d76bef 100644 --- a/app/services/projects/create_service.rb +++ b/app/services/projects/create_service.rb @@ -147,11 +147,7 @@ module Projects priority: UserProjectAccessChangedService::LOW_PRIORITY ) else - if ::Feature.enabled?(:personal_project_owner_with_owner_access, default_enabled: :yaml) - @project.add_owner(@project.namespace.owner, current_user: current_user) - else - @project.add_maintainer(@project.namespace.owner, current_user: current_user) - end + @project.add_owner(@project.namespace.owner, current_user: current_user) end end diff --git a/app/services/projects/deploy_tokens/create_service.rb b/app/services/projects/deploy_tokens/create_service.rb index 592198ef241..2486544b150 100644 --- a/app/services/projects/deploy_tokens/create_service.rb +++ b/app/services/projects/deploy_tokens/create_service.rb @@ -13,3 +13,5 @@ module Projects end end end + +Projects::DeployTokens::CreateService.prepend_mod diff --git a/app/services/projects/deploy_tokens/destroy_service.rb b/app/services/projects/deploy_tokens/destroy_service.rb index e063f86a65c..7ac1b52b0af 100644 --- a/app/services/projects/deploy_tokens/destroy_service.rb +++ b/app/services/projects/deploy_tokens/destroy_service.rb @@ -11,3 +11,5 @@ module Projects end end end + +Projects::DeployTokens::DestroyService.prepend_mod diff --git a/config/feature_flags/development/personal_project_owner_with_owner_access.yml b/config/feature_flags/development/personal_project_owner_with_owner_access.yml deleted file mode 100644 index a82521e88e5..00000000000 --- a/config/feature_flags/development/personal_project_owner_with_owner_access.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: personal_project_owner_with_owner_access -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78193 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351919 -milestone: '14.8' -type: development -group: group::workspace -default_enabled: false diff --git a/db/post_migrate/20220222191845_remove_not_null_constraint_for_security_scan_succeeded.rb b/db/post_migrate/20220222191845_remove_not_null_constraint_for_security_scan_succeeded.rb new file mode 100644 index 00000000000..4d4a20b83b3 --- /dev/null +++ b/db/post_migrate/20220222191845_remove_not_null_constraint_for_security_scan_succeeded.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class RemoveNotNullConstraintForSecurityScanSucceeded < Gitlab::Database::Migration[1.0] + def up + change_column_null :analytics_devops_adoption_snapshots, :security_scan_succeeded, true + end + + def down + # There may now be nulls in the table, so we cannot re-add the constraint here. + end +end diff --git a/db/schema_migrations/20220222191845 b/db/schema_migrations/20220222191845 new file mode 100644 index 00000000000..88c15bc87c0 --- /dev/null +++ b/db/schema_migrations/20220222191845 @@ -0,0 +1 @@ +c528d64cafc072554cd1ef1006a1c359a3135896abae2d5ca20fbbc99ff14f8c \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 7c1fd30c2a6..e26f19761df 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -10776,7 +10776,7 @@ CREATE TABLE analytics_devops_adoption_snapshots ( runner_configured boolean NOT NULL, pipeline_succeeded boolean NOT NULL, deploy_succeeded boolean NOT NULL, - security_scan_succeeded boolean NOT NULL, + security_scan_succeeded boolean, end_time timestamp with time zone NOT NULL, total_projects_count integer, code_owners_used_count integer, diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md index 8f6548eb4ff..731772f3270 100644 --- a/doc/administration/audit_events.md +++ b/doc/administration/audit_events.md @@ -160,6 +160,8 @@ From there, you can see the following actions: - Allowing force push to protected branch changed ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/338873) in GitLab 14.3) - Code owner approval requirement on merge requests targeting protected branch changed ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/338873) in GitLab 14.3) - Users and groups allowed to merge and push to protected branch added or removed ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/338873) in GitLab 14.3) +- Project deploy token was successfully created, revoked or deleted ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/353451) in GitLab 14.9) +- Failed attempt to create a project deploy token ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/353451) in GitLab 14.9) Project events can also be accessed via the [Project Audit Events API](../api/audit_events.md#project-audit-events). diff --git a/doc/development/database/multiple_databases.md b/doc/development/database/multiple_databases.md index 1ca2874837f..5ec0fc4382d 100644 --- a/doc/development/database/multiple_databases.md +++ b/doc/development/database/multiple_databases.md @@ -40,7 +40,9 @@ If you are using GDK, you can follow the following steps: ```yaml gitlab: rails: - multiple_databases: true + databases: + ci: + enabled: true ``` 1. Reconfigure GDK: diff --git a/doc/user/permissions.md b/doc/user/permissions.md index 93447274805..829fe1410ec 100644 --- a/doc/user/permissions.md +++ b/doc/user/permissions.md @@ -33,14 +33,8 @@ usernames. A GitLab administrator can configure the GitLab instance to ## Project members permissions -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/219299) in GitLab 14.8, personal namespace owners appear with Owner role in new projects in their namespace. Introduced [with a flag](../administration/feature_flags.md) named `personal_project_owner_with_owner_access`. Disabled by default. -> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/351919) in GitLab 14.9. - -FLAG: -On self-managed GitLab, personal namespace owners appearing with the Owner role in new projects in their namespace is disabled. To make it available, -ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `personal_project_owner_with_owner_access`. -The feature is not ready for production use. -On GitLab.com, this feature is available. +- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/219299) in GitLab 14.8, personal namespace owners appear with Owner role in new projects in their namespace. Introduced [with a flag](../administration/feature_flags.md) named `personal_project_owner_with_owner_access`. Disabled by default. +- [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/351919) in GitLab 14.9. Feature flag `personal_project_owner_with_owner_access` [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/219299). A user's role determines what permissions they have on a project. The Owner role provides all permissions but is available only: @@ -51,7 +45,7 @@ available only: Personal [namespace](group/index.md#namespaces) owners: - Are displayed as having the Maintainer role on projects in the namespace, but have the same permissions as a user with the Owner role. -- (Disabled by default) In GitLab 14.8 and later, for new projects in the namespace, are displayed as having the Owner role. +- In GitLab 14.9 and later, for new projects in the namespace, are displayed as having the Owner role. For more information about how to manage project members, see [members of a project](project/members/index.md). diff --git a/lib/atlassian/jira_connect/client.rb b/lib/atlassian/jira_connect/client.rb index dc37465744b..b8aa2cc8ea0 100644 --- a/lib/atlassian/jira_connect/client.rb +++ b/lib/atlassian/jira_connect/client.rb @@ -127,16 +127,21 @@ module Atlassian def handle_response(response, name, &block) data = response.parsed_response - case response.code - when 200 then yield data - when 400 then { 'errorMessages' => data.map { |e| e['message'] } } - when 401 then { 'errorMessages' => ['Invalid JWT'] } - when 403 then { 'errorMessages' => ["App does not support #{name}"] } - when 413 then { 'errorMessages' => ['Data too large'] + data.map { |e| e['message'] } } - when 429 then { 'errorMessages' => ['Rate limit exceeded'] } - when 503 then { 'errorMessages' => ['Service unavailable'] } + if [200, 202].include?(response.code) + yield data else - { 'errorMessages' => ['Unknown error'], 'response' => data } + message = case response.code + when 400 then { 'errorMessages' => data.map { |e| e['message'] } } + when 401 then { 'errorMessages' => ['Invalid JWT'] } + when 403 then { 'errorMessages' => ["App does not support #{name}"] } + when 413 then { 'errorMessages' => ['Data too large'] + data.map { |e| e['message'] } } + when 429 then { 'errorMessages' => ['Rate limit exceeded'] } + when 503 then { 'errorMessages' => ['Service unavailable'] } + else + { 'errorMessages' => ['Unknown error'], 'response' => data } + end + + message.merge('responseCode' => response.code) end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 8094e6391c9..a411fb13bcc 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -40735,9 +40735,6 @@ msgstr "" msgid "VulnerabilityManagement|An unverified non-confirmed finding" msgstr "" -msgid "VulnerabilityManagement|At least one identifier is required" -msgstr "" - msgid "VulnerabilityManagement|Change status" msgstr "" @@ -40759,6 +40756,9 @@ msgstr "" msgid "VulnerabilityManagement|Fetching linked Jira issues" msgstr "" +msgid "VulnerabilityManagement|Identifier code and URL are required fields" +msgstr "" + msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report." msgstr "" diff --git a/qa/qa/resource/reusable_group.rb b/qa/qa/resource/reusable_group.rb index b75cb0517bf..05ff38249f6 100644 --- a/qa/qa/resource/reusable_group.rb +++ b/qa/qa/resource/reusable_group.rb @@ -8,7 +8,7 @@ module QA def initialize super - @name = @path = 'reusable_group' + @name = @path = QA::Runtime::Env.reusable_group_path @description = "QA reusable group" @reuse_as = :default_group end diff --git a/qa/qa/resource/reusable_project.rb b/qa/qa/resource/reusable_project.rb index b9fca314122..8a12c25b6f0 100644 --- a/qa/qa/resource/reusable_project.rb +++ b/qa/qa/resource/reusable_project.rb @@ -15,7 +15,7 @@ module QA super @add_name_uuid = false - @name = @path = 'reusable_project' + @name = @path = QA::Runtime::Env.reusable_project_path @reuse_as = :default_project @initialize_with_readme = true end diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb index 088822cc2ca..876d3c0b42a 100644 --- a/qa/qa/runtime/env.rb +++ b/qa/qa/runtime/env.rb @@ -404,6 +404,14 @@ module QA ENV.fetch('GITLAB_QA_LOOP_RUNNER_MINUTES', 1).to_i end + def reusable_project_path + ENV.fetch('QA_REUSABLE_PROJECT_PATH', 'reusable_project') + end + + def reusable_group_path + ENV.fetch('QA_REUSABLE_GROUP_PATH', 'reusable_group') + end + def mailhog_hostname ENV['MAILHOG_HOSTNAME'] end diff --git a/qa/spec/spec_helper.rb b/qa/spec/spec_helper.rb index 6e7d5557a88..1e6d39224aa 100644 --- a/qa/spec/spec_helper.rb +++ b/qa/spec/spec_helper.rb @@ -76,7 +76,8 @@ RSpec.configure do |config| QA::Resource::ReusableCollection.validate_resource_reuse if QA::Runtime::Env.validate_resource_reuse? # If any tests failed, leave the resources behind to help troubleshoot, otherwise remove them. - QA::Resource::ReusableCollection.remove_all_via_api! unless suite.reporter.failed_examples.present? + # Do not remove the shared resource on live environments + QA::Resource::ReusableCollection.remove_all_via_api! if !suite.reporter.failed_examples.present? && !QA::Runtime::Env.running_on_dot_com? end config.append_after(:suite) do diff --git a/spec/finders/projects/members/effective_access_level_finder_spec.rb b/spec/finders/projects/members/effective_access_level_finder_spec.rb index 446b0f8f9a2..bec327835f6 100644 --- a/spec/finders/projects/members/effective_access_level_finder_spec.rb +++ b/spec/finders/projects/members/effective_access_level_finder_spec.rb @@ -12,34 +12,15 @@ RSpec.describe Projects::Members::EffectiveAccessLevelFinder, '#execute' do let_it_be(:project) { create(:project) } shared_examples_for 'includes access level of the owner of the project' do - context 'when personal_project_owner_with_owner_access feature flag is enabled' do - it 'includes access level of the owner of the project as Owner' do - expect(subject).to( - contain_exactly( - hash_including( - 'user_id' => project.namespace.owner.id, - 'access_level' => Gitlab::Access::OWNER - ) + it 'includes access level of the owner of the project as Owner' do + expect(subject).to( + contain_exactly( + hash_including( + 'user_id' => project.namespace.owner.id, + 'access_level' => Gitlab::Access::OWNER ) ) - end - end - - context 'when personal_project_owner_with_owner_access feature flag is disabled' do - before do - stub_feature_flags(personal_project_owner_with_owner_access: false) - end - - it 'includes access level of the owner of the project as Maintainer' do - expect(subject).to( - contain_exactly( - hash_including( - 'user_id' => project.namespace.owner.id, - 'access_level' => Gitlab::Access::MAINTAINER - ) - ) - ) - end + ) end end diff --git a/spec/lib/atlassian/jira_connect/client_spec.rb b/spec/lib/atlassian/jira_connect/client_spec.rb index 9201d1c5dcb..dd3130c78bf 100644 --- a/spec/lib/atlassian/jira_connect/client_spec.rb +++ b/spec/lib/atlassian/jira_connect/client_spec.rb @@ -127,11 +127,19 @@ RSpec.describe Atlassian::JiraConnect::Client do end end + context 'the response is 202 accepted' do + let(:response) { double(code: 202, parsed_response: :foo) } + + it 'yields to the block' do + expect(processed).to eq [:data, :foo] + end + end + context 'the response is 400 bad request' do let(:response) { double(code: 400, parsed_response: errors) } it 'extracts the errors messages' do - expect(processed).to eq('errorMessages' => %w(X Y)) + expect(processed).to eq('errorMessages' => %w(X Y), 'responseCode' => 400) end end @@ -139,7 +147,7 @@ RSpec.describe Atlassian::JiraConnect::Client do let(:response) { double(code: 401, parsed_response: nil) } it 'reports that our JWT is wrong' do - expect(processed).to eq('errorMessages' => ['Invalid JWT']) + expect(processed).to eq('errorMessages' => ['Invalid JWT'], 'responseCode' => 401) end end @@ -147,7 +155,7 @@ RSpec.describe Atlassian::JiraConnect::Client do let(:response) { double(code: 403, parsed_response: nil) } it 'reports that the App is misconfigured' do - expect(processed).to eq('errorMessages' => ['App does not support foo']) + expect(processed).to eq('errorMessages' => ['App does not support foo'], 'responseCode' => 403) end end @@ -155,7 +163,7 @@ RSpec.describe Atlassian::JiraConnect::Client do let(:response) { double(code: 413, parsed_response: errors) } it 'extracts the errors messages' do - expect(processed).to eq('errorMessages' => ['Data too large', 'X', 'Y']) + expect(processed).to eq('errorMessages' => ['Data too large', 'X', 'Y'], 'responseCode' => 413) end end @@ -163,7 +171,7 @@ RSpec.describe Atlassian::JiraConnect::Client do let(:response) { double(code: 429, parsed_response: nil) } it 'reports that we exceeded the rate limit' do - expect(processed).to eq('errorMessages' => ['Rate limit exceeded']) + expect(processed).to eq('errorMessages' => ['Rate limit exceeded'], 'responseCode' => 429) end end @@ -171,7 +179,7 @@ RSpec.describe Atlassian::JiraConnect::Client do let(:response) { double(code: 503, parsed_response: nil) } it 'reports that the service is unavailable' do - expect(processed).to eq('errorMessages' => ['Service unavailable']) + expect(processed).to eq('errorMessages' => ['Service unavailable'], 'responseCode' => 503) end end @@ -179,7 +187,7 @@ RSpec.describe Atlassian::JiraConnect::Client do let(:response) { double(code: 1000, parsed_response: :something) } it 'reports that this was unanticipated' do - expect(processed).to eq('errorMessages' => ['Unknown error'], 'response' => :something) + expect(processed).to eq('errorMessages' => ['Unknown error'], 'responseCode' => 1000, 'response' => :something) end end end diff --git a/spec/lib/gitlab/project_authorizations_spec.rb b/spec/lib/gitlab/project_authorizations_spec.rb index 8630762e06f..640cf9be453 100644 --- a/spec/lib/gitlab/project_authorizations_spec.rb +++ b/spec/lib/gitlab/project_authorizations_spec.rb @@ -34,28 +34,12 @@ RSpec.describe Gitlab::ProjectAuthorizations do .to include(owned_project.id, other_project.id, group_project.id) end - context 'when personal_project_owner_with_owner_access feature flag is enabled' do - it 'includes the correct access levels' do - mapping = map_access_levels(authorizations) + it 'includes the correct access levels' do + mapping = map_access_levels(authorizations) - expect(mapping[owned_project.id]).to eq(Gitlab::Access::OWNER) - expect(mapping[other_project.id]).to eq(Gitlab::Access::REPORTER) - expect(mapping[group_project.id]).to eq(Gitlab::Access::DEVELOPER) - end - end - - context 'when personal_project_owner_with_owner_access feature flag is disabled' do - before do - stub_feature_flags(personal_project_owner_with_owner_access: false) - end - - it 'includes the correct access levels' do - mapping = map_access_levels(authorizations) - - expect(mapping[owned_project.id]).to eq(Gitlab::Access::MAINTAINER) - expect(mapping[other_project.id]).to eq(Gitlab::Access::REPORTER) - expect(mapping[group_project.id]).to eq(Gitlab::Access::DEVELOPER) - end + expect(mapping[owned_project.id]).to eq(Gitlab::Access::OWNER) + expect(mapping[other_project.id]).to eq(Gitlab::Access::REPORTER) + expect(mapping[group_project.id]).to eq(Gitlab::Access::DEVELOPER) end end diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb index 5c867b4580b..561d81f9860 100644 --- a/spec/requests/api/members_spec.rb +++ b/spec/requests/api/members_spec.rb @@ -675,30 +675,13 @@ RSpec.describe API::Members do end context 'adding owner to project' do - context 'when personal_project_owner_with_owner_access feature flag is enabled' do - it 'returns created status' do - expect do - post api("/projects/#{project.id}/members", maintainer), - params: { user_id: stranger.id, access_level: Member::OWNER } + it 'returns created status' do + expect do + post api("/projects/#{project.id}/members", maintainer), + params: { user_id: stranger.id, access_level: Member::OWNER } - expect(response).to have_gitlab_http_status(:created) - end.to change { project.members.count }.by(1) - end - end - - context 'when personal_project_owner_with_owner_access feature flag is disabled' do - before do - stub_feature_flags(personal_project_owner_with_owner_access: false) - end - - it 'returns created status' do - expect do - post api("/projects/#{project.id}/members", maintainer), - params: { user_id: stranger.id, access_level: Member::OWNER } - - expect(response).to have_gitlab_http_status(:bad_request) - end.not_to change { project.members.count } - end + expect(response).to have_gitlab_http_status(:created) + end.to change { project.members.count }.by(1) end end diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb index 03f66256487..96a50b26871 100644 --- a/spec/services/projects/create_service_spec.rb +++ b/spec/services/projects/create_service_spec.rb @@ -116,34 +116,15 @@ RSpec.describe Projects::CreateService, '#execute' do end context 'user namespace' do - context 'when personal_project_owner_with_owner_access feature flag is enabled' do - it 'creates a project in user namespace' do - project = create_project(user, opts) + it 'creates a project in user namespace' do + project = create_project(user, opts) - expect(project).to be_valid - expect(project.first_owner).to eq(user) - expect(project.team.maintainers).not_to include(user) - expect(project.team.owners).to contain_exactly(user) - expect(project.namespace).to eq(user.namespace) - expect(project.project_namespace).to be_in_sync_with_project(project) - end - end - - context 'when personal_project_owner_with_owner_access feature flag is disabled' do - before do - stub_feature_flags(personal_project_owner_with_owner_access: false) - end - - it 'creates a project in user namespace' do - project = create_project(user, opts) - - expect(project).to be_valid - expect(project.first_owner).to eq(user) - expect(project.team.maintainers).to contain_exactly(user) - expect(project.team.owners).to contain_exactly(user) - expect(project.namespace).to eq(user.namespace) - expect(project.project_namespace).to be_in_sync_with_project(project) - end + expect(project).to be_valid + expect(project.first_owner).to eq(user) + expect(project.team.maintainers).not_to include(user) + expect(project.team.owners).to contain_exactly(user) + expect(project.namespace).to eq(user.namespace) + expect(project.project_namespace).to be_in_sync_with_project(project) end end