Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
0a7deb30e2
commit
e7dc35bfd6
|
|
@ -54,6 +54,10 @@ module Organizations
|
|||
organization_users.exists?(user: user)
|
||||
end
|
||||
|
||||
def owner?(user)
|
||||
organization_users.owners.exists?(user: user)
|
||||
end
|
||||
|
||||
def web_url(only_path: nil)
|
||||
Gitlab::UrlBuilder.build(self, only_path: only_path)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,5 +4,17 @@ module Organizations
|
|||
class OrganizationUser < ApplicationRecord
|
||||
belongs_to :organization, inverse_of: :organization_users, optional: false
|
||||
belongs_to :user, inverse_of: :organization_users, optional: false
|
||||
|
||||
validates :user, uniqueness: { scope: :organization_id }
|
||||
validates :access_level, presence: true
|
||||
|
||||
enum access_level: {
|
||||
# Until we develop more access_levels, we really don't know if the default access_level will be what we think of
|
||||
# as a guest. For now, we'll set to same value as guest, but call it default to denote the current ambivalence.
|
||||
default: Gitlab::Access::GUEST,
|
||||
owner: Gitlab::Access::OWNER
|
||||
}
|
||||
|
||||
scope :owners, -> { where(access_level: Gitlab::Access::OWNER) }
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,13 +7,21 @@ module Organizations
|
|||
|
||||
organization = Organization.create(params)
|
||||
|
||||
return error_creating(organization) unless organization.persisted?
|
||||
if organization.persisted?
|
||||
add_organization_owner(organization)
|
||||
|
||||
ServiceResponse.success(payload: { organization: organization })
|
||||
ServiceResponse.success(payload: { organization: organization })
|
||||
else
|
||||
error_creating(organization)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_organization_owner(organization)
|
||||
organization.organization_users.create(user: current_user, access_level: :owner)
|
||||
end
|
||||
|
||||
def error_no_permissions
|
||||
ServiceResponse.error(message: [_('You have insufficient permissions to create organizations')])
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
- title: "License Scanning support for sbt 1.0.X"
|
||||
removal_milestone: "17.0"
|
||||
announcement_milestone: "16.8"
|
||||
breaking_change: true
|
||||
reporter: thiagocsf
|
||||
stage: Secure
|
||||
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/437591
|
||||
body: | # (required) Don't change this line.
|
||||
GitLab 17.0 removes License Scanning support for sbt 1.0.x.
|
||||
|
||||
Users are advised to upgrade from sbt 1.0.x.
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddAccessLevelToOrganizationUsers < Gitlab::Database::Migration[2.2]
|
||||
milestone '16.8'
|
||||
|
||||
def change
|
||||
add_column :organization_users, :access_level, :integer, default: 10, limit: 2, null: false
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemoveStartDateColumnFromVulnerabilities < Gitlab::Database::Migration[2.2]
|
||||
milestone '16.8'
|
||||
|
||||
enable_lock_retries!
|
||||
|
||||
def up
|
||||
remove_column :vulnerabilities, :start_date
|
||||
end
|
||||
|
||||
def down
|
||||
add_column :vulnerabilities, :start_date, :date
|
||||
end
|
||||
end
|
||||
|
|
@ -3,10 +3,9 @@
|
|||
class ValidateForeignKeyCiBuildTraceMetadata < Gitlab::Database::Migration[2.2]
|
||||
milestone '16.8'
|
||||
|
||||
FK_NAME = :fk_21d25cac1a_p
|
||||
|
||||
# We first need to introduce this FK for self-managed
|
||||
def up
|
||||
validate_foreign_key(:ci_build_trace_metadata, [:partition_id, :trace_artifact_id], name: FK_NAME)
|
||||
# no-op
|
||||
end
|
||||
|
||||
def down
|
||||
|
|
|
|||
|
|
@ -3,10 +3,9 @@
|
|||
class ValidateForeignKeyCiJobArtifactState < Gitlab::Database::Migration[2.2]
|
||||
milestone '16.8'
|
||||
|
||||
FK_NAME = :fk_rails_80a9cba3b2_p
|
||||
|
||||
# We first need to introduce this FK for self-managed
|
||||
def up
|
||||
validate_foreign_key(:ci_job_artifact_states, [:partition_id, :job_artifact_id], name: FK_NAME)
|
||||
# no-op
|
||||
end
|
||||
|
||||
def down
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
61b8bed56b1aa5fbce448cc8b90ec863801fbffb0a81f857ce512052f47ba1cb
|
||||
|
|
@ -0,0 +1 @@
|
|||
6afdff39b79900760124493eaa5a7ab8c15f81e77f024338352eeff731479e34
|
||||
|
|
@ -20102,7 +20102,8 @@ CREATE TABLE organization_users (
|
|||
organization_id bigint NOT NULL,
|
||||
user_id bigint NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
access_level smallint DEFAULT 10 NOT NULL
|
||||
);
|
||||
|
||||
CREATE SEQUENCE organization_users_id_seq
|
||||
|
|
@ -24904,7 +24905,6 @@ CREATE TABLE vulnerabilities (
|
|||
epic_id bigint,
|
||||
project_id bigint NOT NULL,
|
||||
author_id bigint NOT NULL,
|
||||
start_date date,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
title character varying(255) NOT NULL,
|
||||
|
|
@ -37468,7 +37468,7 @@ ALTER TABLE ONLY ci_build_trace_metadata
|
|||
ADD CONSTRAINT fk_21d25cac1a FOREIGN KEY (trace_artifact_id) REFERENCES ci_job_artifacts(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY ci_build_trace_metadata
|
||||
ADD CONSTRAINT fk_21d25cac1a_p FOREIGN KEY (partition_id, trace_artifact_id) REFERENCES ci_job_artifacts(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE;
|
||||
ADD CONSTRAINT fk_21d25cac1a_p FOREIGN KEY (partition_id, trace_artifact_id) REFERENCES ci_job_artifacts(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID;
|
||||
|
||||
ALTER TABLE ONLY users_star_projects
|
||||
ADD CONSTRAINT fk_22cd27ddfc FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
|
||||
|
|
@ -39406,7 +39406,7 @@ ALTER TABLE ONLY ci_job_artifact_states
|
|||
ADD CONSTRAINT fk_rails_80a9cba3b2 FOREIGN KEY (job_artifact_id) REFERENCES ci_job_artifacts(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY ci_job_artifact_states
|
||||
ADD CONSTRAINT fk_rails_80a9cba3b2_p FOREIGN KEY (partition_id, job_artifact_id) REFERENCES ci_job_artifacts(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE;
|
||||
ADD CONSTRAINT fk_rails_80a9cba3b2_p FOREIGN KEY (partition_id, job_artifact_id) REFERENCES ci_job_artifacts(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE NOT VALID;
|
||||
|
||||
ALTER TABLE ONLY approval_merge_request_rules_users
|
||||
ADD CONSTRAINT fk_rails_80e6801803 FOREIGN KEY (approval_merge_request_rule_id) REFERENCES approval_merge_request_rules(id) ON DELETE CASCADE;
|
||||
|
|
|
|||
|
|
@ -800,6 +800,22 @@ The table below lists the deprecated metrics and their respective replacements.
|
|||
|
||||
<div class="deprecation breaking-change" data-milestone="17.0">
|
||||
|
||||
### License Scanning support for sbt 1.0.X
|
||||
|
||||
<div class="deprecation-notes">
|
||||
- Announced in GitLab <span class="milestone">16.8</span>
|
||||
- Removal in GitLab <span class="milestone">17.0</span> ([breaking change](https://docs.gitlab.com/ee/update/terminology.html#breaking-change))
|
||||
- To discuss this change or learn more, see the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/437591).
|
||||
</div>
|
||||
|
||||
GitLab 17.0 removes License Scanning support for sbt 1.0.x.
|
||||
|
||||
Users are advised to upgrade from sbt 1.0.x.
|
||||
|
||||
</div>
|
||||
|
||||
<div class="deprecation breaking-change" data-milestone="17.0">
|
||||
|
||||
### List repository directories Rake task
|
||||
|
||||
<div class="deprecation-notes">
|
||||
|
|
|
|||
|
|
@ -277,7 +277,10 @@ The following languages and dependency managers are supported:
|
|||
<li>
|
||||
<a id="notes-regarding-supported-languages-and-package-managers-7"></a>
|
||||
<p>
|
||||
Support for <a href="https://www.scala-sbt.org/">sbt</a> 1.3 and above was added in GitLab 13.9.
|
||||
<ul>
|
||||
<li>Support for <a href="https://www.scala-sbt.org/">sbt</a> 1.3 and above was added in GitLab 13.9.</li>
|
||||
<li>Support for sbt 1.0.x was <a href="https://gitlab.com/gitlab-org/gitlab/-/issues/415835">deprecated in GitLab 16.8</a>.</li>
|
||||
</ul>
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,84 @@
|
|||
# Gitlab::Housekeeper
|
||||
|
||||
Housekeeping following https://gitlab.com/gitlab-org/gitlab/-/merge_requests/134487
|
||||
This is a gem which can be run locally or in CI to do static and dynamic
|
||||
analysis of the GitLab codebase and, using a list of predefined "keeps", it will
|
||||
automatically create merge requests for things that developers would have
|
||||
otherwise needed to remember to do themselves.
|
||||
|
||||
It is analogous to a mix of `rubocop -a` and GitLab Dependency Bot.
|
||||
|
||||
The word "keep" is used to describe a specific rule to apply to the code to
|
||||
match a required change and actually edit the code. The word "keep" was chosen
|
||||
as it sounds like "cop" and is very similar to implementing a rubocop rule as
|
||||
well as code to autocorrect the rule.
|
||||
|
||||
You can see the existing keeps in
|
||||
https://gitlab.com/gitlab-org/gitlab/-/tree/master/keeps .
|
||||
|
||||
## How the code is organized
|
||||
|
||||
The code is organized in a very similar way to RuboCop in that we have an
|
||||
overall gem called `gitlab-housekeeper` that contains the generic logic of
|
||||
looping over all `keeps` (analogous to Cops) which are rules for how to detect
|
||||
changes that can be made to the code and then actually how to correct them.
|
||||
|
||||
Then users of this gem are expected to add a `keeps` directory in their project
|
||||
with all the keeps specific to their project. This gem may at some point
|
||||
include keeps that are generic enough to be used by other projects.
|
||||
|
||||
## How to implement a keep
|
||||
|
||||
The only thing you need to implement is an `each_change` method. The method
|
||||
should yield changes in the form of a `::Gitlab::Housekeeper::Change` object,
|
||||
where each change object represents a merge request that will be created.
|
||||
The object describes the files that should be commited and other metadata
|
||||
should be added to the merge request. Before yielding the `Change` the keep
|
||||
should also edit the files locally.
|
||||
|
||||
Here is an example of a very simple keep that creates 3 new files called
|
||||
`new_file1.txt`, `new_file2.txt` and `new_file3.txt`:
|
||||
|
||||
```ruby
|
||||
# keeps/pretty_useless_keep.rb
|
||||
|
||||
module Keeps
|
||||
class PrettyUselessKeep < ::Gitlab::Housekeeper::Keep
|
||||
def each_change
|
||||
(1..3).each do |i|
|
||||
file_name = "new_file#{i}.txt"
|
||||
|
||||
`touch #{file_name}`
|
||||
|
||||
identifiers = [self.class.name.demodulize, "new_file#{i}"]
|
||||
|
||||
title = "Make new file #{file_name}"
|
||||
|
||||
description = <<~MARKDOWN
|
||||
## New files
|
||||
|
||||
This MR makes a new file #{file_name}
|
||||
MARKDOWN
|
||||
|
||||
changed_files = [file_name]
|
||||
|
||||
yield(::Gitlab::Housekeeper::Change.new(
|
||||
identifiers, title, description, changed_files
|
||||
))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
You can dry-run this locally with the following command:
|
||||
|
||||
```
|
||||
bundle exec gitlab-housekeeper -r keeps/pretty_useless_keep.rb -k Keeps::PrettyUselessKeep -d -m 3
|
||||
```
|
||||
|
||||
The `-d` just prints the contents of the merge request. Removing this will
|
||||
actually create merge requests and requires setting a few environment
|
||||
variables described below.
|
||||
|
||||
## Running
|
||||
|
||||
|
|
@ -14,7 +92,7 @@ a mistake. The alternative of using your own API token with it's permissions to
|
|||
1. Create a project access token for that project
|
||||
1. Set `housekeeper` remote to the fork you created
|
||||
```
|
||||
git remote add housekeeper git@gitlab.com:DylanGriffith/gitlab.git
|
||||
git remote add housekeeper <FORK_GIT_URL>
|
||||
```
|
||||
1. Open a Postgres.ai tunnel on localhost port 6305
|
||||
1. Set the Postgres AI env vars matching the tunnel details for your tunnel
|
||||
|
|
@ -24,8 +102,8 @@ a mistake. The alternative of using your own API token with it's permissions to
|
|||
```
|
||||
1. Set the GitLab client details. Will be used to create MR from housekeeper remote:
|
||||
```
|
||||
export HOUSEKEEPER_FORK_PROJECT_ID=52263761 # Same project as housekeeper remote
|
||||
export HOUSEKEEPER_TARGET_PROJECT_ID=52263761 # Can be 278964 (gitlab-org/gitlab) when ready to create real MRs
|
||||
export HOUSEKEEPER_FORK_PROJECT_ID=<FORK_PROJECT_ID> # Same project as housekeeper remote
|
||||
export HOUSEKEEPER_TARGET_PROJECT_ID=<TARGET_PROJECT_ID> # Can be 278964 (gitlab-org/gitlab) when ready to create real MRs
|
||||
export HOUSEKEEPER_GITLAB_API_TOKEN=the-api-token
|
||||
```
|
||||
1. Run it:
|
||||
|
|
|
|||
|
|
@ -4,5 +4,9 @@ FactoryBot.define do
|
|||
factory :organization_user, class: 'Organizations::OrganizationUser' do
|
||||
user
|
||||
organization
|
||||
|
||||
trait :owner do
|
||||
access_level { Gitlab::Access::OWNER }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -204,6 +204,32 @@ RSpec.describe Organizations::Organization, type: :model, feature_category: :cel
|
|||
end
|
||||
end
|
||||
|
||||
describe '#owner?' do
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
subject { organization.owner?(user) }
|
||||
|
||||
context 'when user is an owner' do
|
||||
before do
|
||||
create(:organization_user, :owner, organization: organization, user: user)
|
||||
end
|
||||
|
||||
it { is_expected.to eq true }
|
||||
end
|
||||
|
||||
context 'when user is not an owner' do
|
||||
before do
|
||||
create(:organization_user, organization: organization, user: user)
|
||||
end
|
||||
|
||||
it { is_expected.to eq false }
|
||||
end
|
||||
|
||||
context 'when user is not an organization user' do
|
||||
it { is_expected.to eq false }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#web_url' do
|
||||
it 'returns web url from `Gitlab::UrlBuilder`' do
|
||||
web_url = 'http://127.0.0.1:3000/-/organizations/default'
|
||||
|
|
|
|||
|
|
@ -8,6 +8,18 @@ RSpec.describe Organizations::OrganizationUser, type: :model, feature_category:
|
|||
it { is_expected.to belong_to(:user).inverse_of(:organization_users).required }
|
||||
end
|
||||
|
||||
describe 'validations' do
|
||||
subject { build(:organization_user) }
|
||||
|
||||
it { is_expected.to define_enum_for(:access_level).with_values(described_class.access_levels) }
|
||||
it { is_expected.to validate_presence_of(:access_level) }
|
||||
it { is_expected.to validate_uniqueness_of(:user).scoped_to(:organization_id) }
|
||||
|
||||
it 'does not allow invalid enum value' do
|
||||
expect { build(:organization_user, access_level: '_invalid_') }.to raise_error(ArgumentError)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with loose foreign key on organization_users.organization_id' do
|
||||
it_behaves_like 'cleanup by a loose foreign key' do
|
||||
let_it_be(:parent) { create(:organization) }
|
||||
|
|
@ -21,4 +33,15 @@ RSpec.describe Organizations::OrganizationUser, type: :model, feature_category:
|
|||
let_it_be(:model) { create(:organization_user, user: parent) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.owners' do
|
||||
it 'returns the owners of the organization' do
|
||||
organization_user = create(:organization_user, :owner)
|
||||
create(:organization_user)
|
||||
|
||||
expect(described_class.owners).to match([organization_user])
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'having unique enum values'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -29,11 +29,13 @@ RSpec.describe Organizations::CreateService, feature_category: :cell do
|
|||
shared_examples 'creating an organization' do
|
||||
it 'creates the organization' do
|
||||
expect { response }.to change { Organizations::Organization.count }
|
||||
.and change { Organizations::OrganizationUser.count }.by(1)
|
||||
expect(response).to be_success
|
||||
expect(created_organization.name).to eq(params[:name])
|
||||
expect(created_organization.path).to eq(params[:path])
|
||||
expect(created_organization.description).to eq(params[:description])
|
||||
expect(created_organization.avatar.filename).to eq(avatar_filename)
|
||||
expect(created_organization.owner?(current_user)).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue