Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-06-18 09:21:46 +00:00
parent 47c3acc07e
commit 2cec357c4f
10 changed files with 93 additions and 33 deletions

View File

@ -66,21 +66,23 @@ class WorkItem < Issue
end
def work_item_children_keyset_order
keyset_order = Gitlab::Pagination::Keyset::Order.build([
Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
attribute_name: :relative_position,
column_expression: WorkItems::ParentLink.arel_table[:relative_position],
order_expression: WorkItems::ParentLink.arel_table[:relative_position].asc.nulls_last,
nullable: :nulls_last
),
Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
attribute_name: :created_at,
order_expression: WorkItem.arel_table[:created_at].asc,
nullable: :not_nullable
)
])
keyset_order = Gitlab::Pagination::Keyset::Order.build(
[
Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
attribute_name: 'parent_link_relative_position',
column_expression: WorkItems::ParentLink.arel_table[:relative_position],
order_expression: WorkItems::ParentLink.arel_table[:relative_position].asc.nulls_last,
add_to_projections: true,
nullable: :nulls_last
),
Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(
attribute_name: 'work_item_id',
order_expression: WorkItems::ParentLink.arel_table['work_item_id'].asc
)
]
)
includes(:parent_link).order(keyset_order)
keyset_order.apply_cursor_conditions(includes(:parent_link)).reorder(keyset_order)
end
def linked_items_keyset_order

View File

@ -0,0 +1,37 @@
---
owning-stage: "~devops::create"
description: 'GitLab Remote Development ADR 100: New agent authorization strategy'
---
# GitLab Remote Development ADR 001: New agent authorization strategy
## Context
A decision was made to drop the legacy agent authorization strategy in favor of the new agent authorization strategy. As covered in [detailed proposal](https://gitlab.com/gitlab-org/remote-development/gitlab-remote-development-docs/-/blob/main/doc/proposal-for-mapping-projects-to-agents.md?ref_type=heads#problems-with-the-current-solution), the current solution has several issues that make it unsuitable for the long-term needs of the GitLab Remote Development feature. The main problems are:
1. **Limited flexibility**: The legacy agent authorization strategy relies on granting group-level Developer role to potential users. This makes it unsuitable for use in some organisations where users are not granted access at a group level.
1. **Potential security risks**: The legacy approach allows any user with Developer role within a limited scope to spin up a GitLab Agent and have it be potentially used for workspaces by users with relevant access to the project. Since workspaces contain privileged information such as secrets, more control should be enforced on what GitLab Agents may be select for hosting workspaces within a given scope (for e.g a group) as it is with GitLab CI Runners.
## Decision
Taking inspiration from the authorization model for GitLab CI Runners, a new authorization strategy for GitLab Agents will be introduced. In order understand how workspaces can be created using the new authorization strategy, it's important to understand the following rules:
- A user can only create workspaces using a cluster agent that is "available", and which has been configured for remote_development.
- A user must have Developer role to both the agent project and the workspace project.
- An agent is considered "available" for use with a workspace if a group owner or administrator has mapped the cluster agent to any parent group of the workspace project. Another way of looking at it is; a mapping between a cluster agent and a group is inherited by its subgroups.
- Mapping between a cluster agent and a group is a new concept that has been introduced with the revamped authorization strategy. A group owner may create a mapping between the group and any cluster agent residing within the group or its subgroup. **NOTE:** By default, no cluster agent is mapped to a group. Additionally, if a project resides within a group, it does NOT imply that the cluster agents of this project are mapped to the parent group(s).
In addition the above, the first phase of delivery will have the following restrictions:
- A GitLab Agent may only be mapped to a group. In the future, mapping cluster agents to the instance, user namespaces etc. can/should be explored.
- A GitLab Agent may only be mapped to a parent group. The group in question may or may not be a direct parent. For eg. if an agent belongs to a project with path `root-group/nested-group/agent-project`, then the agent may be mapped to either `root-group` and/or `nested-group`. In the future, there may be a need to consider mapping agents to a non-parent group. However, this will increase the scope of the task significantly due to additional considerations: for example, what if some owners/maintainers of a group do not access to the agent being mapped? This is not a problem when the agent is contained within the group. However, this usecase will have to be thought through if such a capability must be supported consistently.
For more details, on the details of the new authorization strategy, please refer to the [detailed technical design](https://gitlab.com/gitlab-org/remote-development/gitlab-remote-development-docs/-/blob/e28003334fda100295ed41bd84eef2b1770d86af/doc/tech-designs/2024-01-23-support-group-agent-authorization.md).
## Consequences
Since the new strategy is incompatible with the legacy authorization strategy, this feature will be put behind a feature flag and rolled out gradually. Additionally, in order to provide a smooth user experience during feature rollout, a one-time data migration will take place to create mappings between root groups and remote development cluster agents within these groups. After this migration, for any changes desired to the list of cluster agents available during workspace creation, users will be required to explicitly create/delete mappings.
## Alternatives
NA

View File

@ -12,6 +12,10 @@ participating-stages: []
# Remote development
## Decisions
- [100: New agent authorization strategy](decisions/100_new_agent_authorization_strategy.md)
## Summary
Remote development is a new architecture for our software-as-a-service platform that provides a more consistent user experience writing code hosted in GitLab. It may also provide additional features in the future, such as a purely browser-based workspace and the ability to connect to an already running VM/Container or to use a GitLab-hosted VM/Container.

View File

@ -133,6 +133,18 @@ RSpec.describe Gitlab::Usage::EventSelectionRule, feature_category: :service_pin
expect(event_selection_rule.redis_keys_for_time_frame('7d'))
.to eq(["{event_counters}_an_event-filter:[label:foo]-2024-21"])
end
context 'when key is overridden' do
before do
stub_file_read(Gitlab::UsageDataCounters::HLLRedisCounter::KEY_OVERRIDES_PATH,
content: 'an_event-filter:[label:foo]: a_legacy_key')
end
it 'uses the legacy key' do
expect(event_selection_rule.redis_keys_for_time_frame('7d'))
.to eq(["{event_counters}_a_legacy_key-2024-21"])
end
end
end
context 'when time_frame is "28d"' do

View File

@ -48,9 +48,9 @@ RSpec.describe WorkItem, feature_category: :portfolio_management do
subject { parent_item.reload.work_item_children_by_relative_position }
let_it_be(:parent_item) { create(:work_item, :objective, project: reusable_project) }
let_it_be(:oldest_item) { create(:work_item, :objective, created_at: 5.hours.ago, project: reusable_project) }
let_it_be(:oldest_item) { create(:work_item, :objective, project: reusable_project) }
let_it_be(:middle_item) { create(:work_item, :objective, project: reusable_project) }
let_it_be(:newest_item) { create(:work_item, :objective, created_at: 5.hours.from_now, project: reusable_project) }
let_it_be(:newest_item) { create(:work_item, :objective, project: reusable_project) }
let_it_be_with_reload(:link_to_oldest_item) do
create(:parent_link, work_item_parent: parent_item, work_item: oldest_item)
@ -64,7 +64,7 @@ RSpec.describe WorkItem, feature_category: :portfolio_management do
create(:parent_link, work_item_parent: parent_item, work_item: newest_item)
end
context 'when ordered by relative position and created_at' do
context 'when ordered by relative position' do
using RSpec::Parameterized::TableSyntax
where(:oldest_item_position, :middle_item_position, :newest_item_position, :expected_order) do
@ -73,6 +73,11 @@ RSpec.describe WorkItem, feature_category: :portfolio_management do
nil | 1 | 2 | lazy { [middle_item, newest_item, oldest_item] }
2 | 3 | 1 | lazy { [newest_item, oldest_item, middle_item] }
1 | 2 | 3 | lazy { [oldest_item, middle_item, newest_item] }
1 | 3 | 2 | lazy { [oldest_item, newest_item, middle_item] }
2 | 1 | 3 | lazy { [middle_item, oldest_item, newest_item] }
3 | 1 | 2 | lazy { [middle_item, newest_item, oldest_item] }
3 | 2 | 1 | lazy { [newest_item, middle_item, oldest_item] }
1 | 2 | 1 | lazy { [oldest_item, newest_item, middle_item] }
end
with_them do

View File

@ -36,9 +36,9 @@ RSpec.describe WorkItems::Widgets::Hierarchy, feature_category: :team_planning d
it { is_expected.to contain_exactly(parent_link1.work_item, parent_link2.work_item) }
context 'when ordered by relative position and created_at' do
let_it_be(:oldest_child) { create(:work_item, :task, project: project, created_at: 5.minutes.ago) }
let_it_be(:newest_child) { create(:work_item, :task, project: project, created_at: 5.minutes.from_now) }
context 'when ordered by relative position and work_item_id' do
let_it_be(:oldest_child) { create(:work_item, :task, project: project) }
let_it_be(:newest_child) { create(:work_item, :task, project: project) }
let_it_be_with_reload(:link_to_oldest_child) do
create(:parent_link, work_item_parent: work_item_parent, work_item: oldest_child)
@ -48,10 +48,10 @@ RSpec.describe WorkItems::Widgets::Hierarchy, feature_category: :team_planning d
create(:parent_link, work_item_parent: work_item_parent, work_item: newest_child)
end
let(:parent_links_ordered) { [link_to_oldest_child, parent_link1, parent_link2, link_to_newest_child] }
let(:parent_links_ordered) { [parent_link1, parent_link2, link_to_oldest_child, link_to_newest_child] }
context 'when children relative positions are nil' do
it 'orders by created_at' do
it 'orders by work_item_id' do
is_expected.to eq(parent_links_ordered.map(&:work_item))
end
end

View File

@ -22,8 +22,8 @@ RSpec.describe 'Query.work_item(id)', feature_category: :team_planning do
)
end
let_it_be(:child_item1) { create(:work_item, :task, project: project) }
let_it_be(:child_item2) { create(:work_item, :task, confidential: true, project: project) }
let_it_be(:child_item1) { create(:work_item, :task, project: project, id: 1200) }
let_it_be(:child_item2) { create(:work_item, :task, confidential: true, project: project, id: 1400) }
let_it_be(:child_link1) { create(:parent_link, work_item_parent: work_item, work_item: child_item1) }
let_it_be(:child_link2) { create(:parent_link, work_item_parent: work_item, work_item: child_item2) }
@ -258,9 +258,9 @@ RSpec.describe 'Query.work_item(id)', feature_category: :team_planning do
end
end
context 'when ordered by default by created_at' do
let_it_be(:newest_child) { create(:work_item, :task, project: project, created_at: 5.minutes.from_now) }
let_it_be(:oldest_child) { create(:work_item, :task, project: project, created_at: 5.minutes.ago) }
context 'when ordered by default by work_item_id' do
let_it_be(:newest_child) { create(:work_item, :task, project: project, id: 2000) }
let_it_be(:oldest_child) { create(:work_item, :task, project: project, id: 1000) }
let_it_be(:newest_link) { create(:parent_link, work_item_parent: work_item, work_item: newest_child) }
let_it_be(:oldest_link) { create(:parent_link, work_item_parent: work_item, work_item: oldest_child) }
@ -276,7 +276,7 @@ RSpec.describe 'Query.work_item(id)', feature_category: :team_planning do
end
context 'when relative position is set' do
let_it_be(:first_child) { create(:work_item, :task, project: project, created_at: 5.minutes.from_now) }
let_it_be(:first_child) { create(:work_item, :task, project: project, id: 3000) }
let_it_be(:first_link) do
create(:parent_link, work_item_parent: work_item, work_item: first_child, relative_position: 1)

View File

@ -127,8 +127,8 @@ describe Sidekiq::Metrics do
assert_equal 2, job_result.series.dig("p", "22:03")
assert_equal 3, job_result.totals["p"]
# Execution time is not consistent, so these assertions are not exact
assert job_result.total_avg("ms").between?(0.5, 2), job_result.total_avg("ms")
assert job_result.series_avg("s")["22:03"].between?(0.0005, 0.002), job_result.series_avg("s")
assert job_result.total_avg("ms").between?(0.5, 8), job_result.total_avg("ms")
assert job_result.series_avg("s")["22:03"].between?(0.0005, 0.008), job_result.series_avg("s")
end
it "fetches job-specific data" do

View File

@ -19,7 +19,7 @@ require (
github.com/jpillora/backoff v1.0.0
github.com/mitchellh/copystructure v1.2.0
github.com/prometheus/client_golang v1.19.1-0.20240328134234-93cf5d4f5f78
github.com/redis/go-redis/v9 v9.5.2
github.com/redis/go-redis/v9 v9.5.3
github.com/sebest/xff v0.0.0-20210106013422-671bd2870b3a
github.com/sirupsen/logrus v1.9.3
github.com/smartystreets/goconvey v1.8.1

View File

@ -418,8 +418,8 @@ github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/prometheus/prometheus v0.50.1 h1:N2L+DYrxqPh4WZStU+o1p/gQlBaqFbcLBTjlp3vpdXw=
github.com/prometheus/prometheus v0.50.1/go.mod h1:FvE8dtQ1Ww63IlyKBn1V4s+zMwF9kHkVNkQBR1pM4CU=
github.com/redis/go-redis/v9 v9.5.2 h1:L0L3fcSNReTRGyZ6AqAEN0K56wYeYAwapBIhkvh0f3E=
github.com/redis/go-redis/v9 v9.5.2/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
github.com/redis/go-redis/v9 v9.5.3 h1:fOAp1/uJG+ZtcITgZOfYFmTKPE7n4Vclj1wZFgRciUU=
github.com/redis/go-redis/v9 v9.5.3/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=