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>2022-12-15 06:08:16 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-12-15 06:08:16 +0300
commitc40b7517717b0d23893a92527819fd05c2531b93 (patch)
tree186f2d6d6ec0f794898f4d1011e8fd9b740c24f4
parent17c478bc8096b22f22a4b1d8573540d2dfddf6ba (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--db/post_migrate/20221205170310_add_index_for_active_members.rb18
-rw-r--r--db/schema_migrations/202212051703101
-rw-r--r--db/structure.sql2
-rw-r--r--doc/administration/packages/container_registry.md3
-rw-r--r--doc/architecture/blueprints/_template.md2
-rw-r--r--doc/architecture/blueprints/pods/pods-feature-contributions-forks.md95
-rw-r--r--doc/user/group/import/index.md3
-rw-r--r--lib/gitlab/ci/config/external/file/remote.rb2
-rw-r--r--locale/gitlab.pot6
-rw-r--r--spec/frontend/fixtures/runner_instructions.rb43
-rw-r--r--spec/frontend/vue_shared/components/runner_instructions/mock_data.js122
-rw-r--r--spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js87
-rw-r--r--spec/lib/gitlab/ci/config/external/file/remote_spec.rb13
14 files changed, 227 insertions, 172 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index e4c321643bb..6da14cff2b6 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-edca8ea99b1670990281775a5d99429c4492fd8e
+7a889a316623eeeb5c8ba0499da59fe3fc4b2a81
diff --git a/db/post_migrate/20221205170310_add_index_for_active_members.rb b/db/post_migrate/20221205170310_add_index_for_active_members.rb
new file mode 100644
index 00000000000..c52b8ccfd04
--- /dev/null
+++ b/db/post_migrate/20221205170310_add_index_for_active_members.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddIndexForActiveMembers < Gitlab::Database::Migration[2.0]
+ INDEX_NAME = 'index_members_on_source_state_type_access_level_and_user_id'
+
+ disable_ddl_transaction!
+
+ def up
+ where_clause = 'requested_at is null and invite_token is null'
+
+ add_concurrent_index :members, [:source_id, :source_type, :state, :type, :access_level, :user_id],
+ name: INDEX_NAME, where: where_clause
+ end
+
+ def down
+ remove_concurrent_index_by_name :members, INDEX_NAME
+ end
+end
diff --git a/db/schema_migrations/20221205170310 b/db/schema_migrations/20221205170310
new file mode 100644
index 00000000000..08365068b43
--- /dev/null
+++ b/db/schema_migrations/20221205170310
@@ -0,0 +1 @@
+6501b62569b96e2be3afc2c79fe438fffc6b45485b04f6b2989ae35f0cf9a4b9 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index b0793369b4f..89f7ad47e43 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -29816,6 +29816,8 @@ CREATE INDEX index_members_on_requested_at ON members USING btree (requested_at)
CREATE INDEX index_members_on_source_id_and_source_type ON members USING btree (source_id, source_type);
+CREATE INDEX index_members_on_source_state_type_access_level_and_user_id ON members USING btree (source_id, source_type, state, type, access_level, user_id) WHERE ((requested_at IS NULL) AND (invite_token IS NULL));
+
CREATE INDEX index_members_on_user_id_and_access_level_requested_at_is_null ON members USING btree (user_id, access_level) WHERE (requested_at IS NULL);
CREATE INDEX index_members_on_user_id_created_at ON members USING btree (user_id, created_at) WHERE ((ldap = true) AND ((type)::text = 'GroupMember'::text) AND ((source_type)::text = 'Namespace'::text));
diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md
index 6a58a1e60e0..d76c728fb78 100644
--- a/doc/administration/packages/container_registry.md
+++ b/doc/administration/packages/container_registry.md
@@ -343,6 +343,9 @@ these deleted temporary upload artifacts are kept as non-current versions, there
storage bucket size. To ensure that non-current versions are deleted after a given amount of time,
you should configure an object lifecycle policy with your storage provider.
+WARNING:
+Do not directly modify the files or objects stored by the container registry. Anything other than the registry writing or deleting these entries can lead to instance-wide data consistency and instability issues from which recovery may not be possible.
+
You can configure the Container Registry to use various storage backends by
configuring a storage driver. By default the GitLab Container Registry
is configured to use the [file system driver](#use-file-system)
diff --git a/doc/architecture/blueprints/_template.md b/doc/architecture/blueprints/_template.md
index a803969f7a9..e39c2b51a5b 100644
--- a/doc/architecture/blueprints/_template.md
+++ b/doc/architecture/blueprints/_template.md
@@ -1,6 +1,6 @@
---
status: proposed
-creation-date: yyyy-mm-dd
+creation-date: "yyyy-mm-dd"
authors: [ "@username" ]
coach: "@username"
approvers: [ "@product-manager", "@engineering-manager" ]
diff --git a/doc/architecture/blueprints/pods/pods-feature-contributions-forks.md b/doc/architecture/blueprints/pods/pods-feature-contributions-forks.md
index 623b41bc5af..566ae50ec49 100644
--- a/doc/architecture/blueprints/pods/pods-feature-contributions-forks.md
+++ b/doc/architecture/blueprints/pods/pods-feature-contributions-forks.md
@@ -14,13 +14,104 @@ we can document the reasons for not choosing this approach.
# Pods: Contributions: Forks
-> TL;DR
+[Forking workflow](../../../user/project/repository/forking_workflow.md) allows users
+to copy existing project sources into their own namespace of choice (personal or group).
## 1. Definition
+[Forking workflow](../../../user/project/repository/forking_workflow.md) is common workflow
+with various usage patterns:
+
+- allows users to contribute back to upstream project
+- persist repositories into their personal namespace
+- copy to make changes and release as modified project
+
+Forks allow users not having write access to parent project to make changes. The forking workflow
+is especially important for the Open Source community which is able to contribute back
+to public projects. However, it is equally important in some companies which prefer the strong split
+of responsibilites and tighter access control. The access to project is restricted
+to designated list of developers.
+
+Forks enable:
+
+- tigther control of who can modify the upstream project
+- split of the responsibilites: parent project might use CI configuration connecting to production systems
+- run CI pipelines in context of fork in much more restrictive environment
+- consider all forks to be unveted which reduces risks of leaking secrets, or any other information
+ tied with the project
+
+The forking model is problematic in Pods architecture for following reasons:
+
+- Forks are clones of existing repositories, forks could be created across different organizations, Pods and Gitaly shards.
+- User can create merge request and contribute back to upstream project, this upstream project might in a different organization and Pod.
+- The merge request CI pipeline is to executed in a context of source project, but presented in a context of target project.
+
## 2. Data flow
-## 3. Proposal
+## 3. Proposals
+
+### 3.1. Intra-Cluster forks
+
+This proposal makes us to implement forks as a intra-ClusterPod forks where communication is done via API
+between all trusted Pods of a cluster:
+
+- Forks when created, they are created always in context of user choice of group.
+- Forks are isolated from Organization.
+- Organization or group owner could disable forking across organizations or forking in general.
+- When a Merge Request is created it is created in context of target project, referencing
+ external project on another Pod.
+- To target project the merge reference is transfered that is used for presenting information
+ in context of target project.
+- CI pipeline is fetched in context of source project as it-is today, the result is fetched into
+ Merge Request of target project.
+- The Pod holding target project internally uses GraphQL to fetch status of source project
+ and include in context of the information for merge request.
+
+Upsides:
+
+- All existing forks continue to work as-is, as they are treated as intra-Cluster forks.
+
+Downsides:
+
+- The purpose of Organizations is to provide strong isolation between organizations
+ allowing to fork across does break security boundaries.
+- However, this is no different to ability of users today to clone repository to local computer
+ and push it to any repository of choice.
+- Access control of source project can be lower than those of target project. System today
+ requires that in order to contribute back the access level needs to be the same for fork and upstream.
+
+### 3.2. Forks are created in a personal namespace of the current organization
+
+Instead of creating projects across organizations, the forks are created in a user personal namespace
+tied with the organization. Example:
+
+- Each user that is part of organization receives their personal namespace. For example for `GitLab Inc.`
+ it could be `gitlab.com/organization/gitlab-inc/@ayufan`.
+- The user has to fork into it's own personal namespace of the organization.
+- The user has that many personal namespaces as many organizations it belongs to.
+- The personal namespace behaves similar to currently offered personal namespace.
+- The user can manage and create projects within a personal namespace.
+- The organization can prevent or disable usage of personal namespaces disallowing forks.
+- All current forks are migrated into personal namespace of user in Organization.
+- All forks are part of to the organization.
+- The forks are not federated features.
+- The personal namespace and forked project do not share configuration with parent project.
+
+### 3.3. Forks are created as internal projects under current project
+
+Instead of creating projects across organizations, the forks are attachments to existing projects.
+Each user forking a project receives their unique project. Example:
+
+- For project: `gitlab.com/gitlab-org/gitlab`, forks would be created in `gitlab.com/gitlab-org/gitlab/@kamil-gitlab`.
+- Forks are created in a context of current organization, they do not cross organization boundaries
+ and are managed by the organization.
+- Tied to the user (or any other user-provided name of the fork).
+- The forks are not federated features.
+
+Downsides:
+
+- Does not answer how to handle and migrate all exisiting forks.
+- Might share current group / project settings - breaking some security boundaries.
## 4. Evaluation
diff --git a/doc/user/group/import/index.md b/doc/user/group/import/index.md
index 02921210f01..477ac8ddc4b 100644
--- a/doc/user/group/import/index.md
+++ b/doc/user/group/import/index.md
@@ -59,8 +59,9 @@ Not all group and project resources are imported. See list of migrated resources
GitLab maps users and their contributions correctly provided:
-- Users already exists on the target GitLab instance.
+- Users already exist on the target GitLab instance.
- Users have a public email on the source GitLab instance that matches their primary email on the target GitLab instance.
+- Users' primary email addresses on the target GitLab instance are confirmed. Most users receives an email asking them to confirm their email address.
- When using an OmniAuth provider like SAML, GitLab and SAML accounts of users on GitLab must be linked. All users on the target GitLab instance must sign in
and verify their account on the target GitLab instance.
diff --git a/lib/gitlab/ci/config/external/file/remote.rb b/lib/gitlab/ci/config/external/file/remote.rb
index b0c540685d4..ed37357dc53 100644
--- a/lib/gitlab/ci/config/external/file/remote.rb
+++ b/lib/gitlab/ci/config/external/file/remote.rb
@@ -53,7 +53,7 @@ module Gitlab
errors.push("Remote file `#{masked_location}` could not be fetched because of a timeout error!")
rescue Gitlab::HTTP::Error
errors.push("Remote file `#{masked_location}` could not be fetched because of HTTP error!")
- rescue Gitlab::HTTP::BlockedUrlError => e
+ rescue Errno::ECONNREFUSED, Gitlab::HTTP::BlockedUrlError => e
errors.push("Remote file could not be fetched because #{e}!")
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 4ee98b3623e..26a07c17c27 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -40296,6 +40296,9 @@ msgstr ""
msgid "SuperSonics|Cloud licensing is now available. It's an easier way to activate instances and manage subscriptions. Read more about it in our %{blogPostLinkStart}blog post%{blogPostLinkEnd}. Activation codes are available in the %{portalLinkStart}Customers Portal%{portalLinkEnd}."
msgstr ""
+msgid "SuperSonics|Customers Portal"
+msgstr ""
+
msgid "SuperSonics|Enter activation code"
msgstr ""
@@ -40317,9 +40320,6 @@ msgstr ""
msgid "SuperSonics|Licensed to"
msgstr ""
-msgid "SuperSonics|Manage"
-msgstr ""
-
msgid "SuperSonics|Maximum users"
msgstr ""
diff --git a/spec/frontend/fixtures/runner_instructions.rb b/spec/frontend/fixtures/runner_instructions.rb
new file mode 100644
index 00000000000..90a01c37479
--- /dev/null
+++ b/spec/frontend/fixtures/runner_instructions.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Runner Instructions (JavaScript fixtures)', feature_category: :runner do
+ include ApiHelpers
+ include JavaScriptFixturesHelpers
+ include GraphqlHelpers
+
+ query_path = 'vue_shared/components/runner_instructions/graphql/queries'
+
+ describe GraphQL::Query do
+ describe 'get_runner_platforms.query.graphql', type: :request do
+ let_it_be(:query) do
+ get_graphql_query_as_string("#{query_path}/get_runner_platforms.query.graphql")
+ end
+
+ it 'graphql/runner_instructions/get_runner_platforms.query.graphql.json' do
+ post_graphql(query)
+
+ expect_graphql_errors_to_be_empty
+ end
+ end
+
+ describe 'get_runner_setup.query.graphql', type: :request do
+ let_it_be(:query) do
+ get_graphql_query_as_string("#{query_path}/get_runner_setup.query.graphql")
+ end
+
+ it 'graphql/runner_instructions/get_runner_setup.query.graphql.json' do
+ post_graphql(query, variables: { platform: 'linux', architecture: 'amd64' })
+
+ expect_graphql_errors_to_be_empty
+ end
+
+ it 'graphql/runner_instructions/get_runner_setup.query.graphql.windows.json' do
+ post_graphql(query, variables: { platform: 'windows', architecture: 'amd64' })
+
+ expect_graphql_errors_to_be_empty
+ end
+ end
+ end
+end
diff --git a/spec/frontend/vue_shared/components/runner_instructions/mock_data.js b/spec/frontend/vue_shared/components/runner_instructions/mock_data.js
index bc1545014d7..79cacadd6af 100644
--- a/spec/frontend/vue_shared/components/runner_instructions/mock_data.js
+++ b/spec/frontend/vue_shared/components/runner_instructions/mock_data.js
@@ -1,119 +1,5 @@
-export const mockGraphqlRunnerPlatforms = {
- data: {
- runnerPlatforms: {
- nodes: [
- {
- name: 'linux',
- humanReadableName: 'Linux',
- architectures: {
- nodes: [
- {
- name: 'amd64',
- downloadLocation:
- 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64',
- __typename: 'RunnerArchitecture',
- },
- {
- name: '386',
- downloadLocation:
- 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-386',
- __typename: 'RunnerArchitecture',
- },
- {
- name: 'arm',
- downloadLocation:
- 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-arm',
- __typename: 'RunnerArchitecture',
- },
- {
- name: 'arm64',
- downloadLocation:
- 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-arm64',
- __typename: 'RunnerArchitecture',
- },
- ],
- __typename: 'RunnerArchitectureConnection',
- },
- __typename: 'RunnerPlatform',
- },
- {
- name: 'osx',
- humanReadableName: 'macOS',
- architectures: {
- nodes: [
- {
- name: 'amd64',
- downloadLocation:
- 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64',
- __typename: 'RunnerArchitecture',
- },
- ],
- __typename: 'RunnerArchitectureConnection',
- },
- __typename: 'RunnerPlatform',
- },
- {
- name: 'windows',
- humanReadableName: 'Windows',
- architectures: {
- nodes: [
- {
- name: 'amd64',
- downloadLocation:
- 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-windows-amd64.exe',
- __typename: 'RunnerArchitecture',
- },
- {
- name: '386',
- downloadLocation:
- 'https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-windows-386.exe',
- __typename: 'RunnerArchitecture',
- },
- ],
- __typename: 'RunnerArchitectureConnection',
- },
- __typename: 'RunnerPlatform',
- },
- {
- name: 'docker',
- humanReadableName: 'Docker',
- architectures: null,
- __typename: 'RunnerPlatform',
- },
- {
- name: 'kubernetes',
- humanReadableName: 'Kubernetes',
- architectures: null,
- __typename: 'RunnerPlatform',
- },
- ],
- __typename: 'RunnerPlatformConnection',
- },
- project: { id: 'gid://gitlab/Project/1', __typename: 'Project' },
- group: null,
- },
-};
+import mockGraphqlRunnerPlatforms from 'test_fixtures/graphql/runner_instructions/get_runner_platforms.query.graphql.json';
+import mockGraphqlInstructions from 'test_fixtures/graphql/runner_instructions/get_runner_setup.query.graphql.json';
+import mockGraphqlInstructionsWindows from 'test_fixtures/graphql/runner_instructions/get_runner_setup.query.graphql.windows.json';
-export const mockGraphqlInstructions = {
- data: {
- runnerSetup: {
- installInstructions:
- '# Install and run as service\nsudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner\nsudo gitlab-runner start',
- registerInstructions:
- 'sudo gitlab-runner register --url http://gdk.test:3000/ --registration-token $REGISTRATION_TOKEN',
- __typename: 'RunnerSetup',
- },
- },
-};
-
-export const mockGraphqlInstructionsWindows = {
- data: {
- runnerSetup: {
- installInstructions:
- '# Windows runner, then run\n.gitlab-runner.exe install\n.gitlab-runner.exe start',
- registerInstructions:
- './gitlab-runner.exe register --url http://gdk.test:3000/ --registration-token $REGISTRATION_TOKEN',
- __typename: 'RunnerSetup',
- },
- },
-};
+export { mockGraphqlRunnerPlatforms, mockGraphqlInstructions, mockGraphqlInstructionsWindows };
diff --git a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js
index 7c5fc63856a..ae9157591c5 100644
--- a/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js
+++ b/spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js
@@ -113,10 +113,7 @@ describe('RunnerInstructionsModal component', () => {
});
describe('should display default instructions', () => {
- const {
- installInstructions,
- registerInstructions,
- } = mockGraphqlInstructions.data.runnerSetup;
+ const { installInstructions } = mockGraphqlInstructions.data.runnerSetup;
it('runner instructions are requested', () => {
expect(runnerSetupInstructionsHandler).toHaveBeenCalledWith({
@@ -128,53 +125,16 @@ describe('RunnerInstructionsModal component', () => {
it('binary instructions are shown', async () => {
const instructions = findBinaryInstructions().text();
- expect(instructions).toBe(installInstructions);
+ expect(instructions).toBe(installInstructions.trim());
});
it('register command is shown with a replaced token', async () => {
const command = findRegisterCommand().text();
expect(command).toBe(
- 'sudo gitlab-runner register --url http://gdk.test:3000/ --registration-token MY_TOKEN',
+ 'sudo gitlab-runner register --url http://localhost/ --registration-token MY_TOKEN',
);
});
-
- describe('when a register token is not shown', () => {
- beforeEach(async () => {
- createComponent({ props: { registrationToken: undefined } });
- await waitForPromises();
- });
-
- it('register command is shown without a defined registration token', () => {
- const instructions = findRegisterCommand().text();
-
- expect(instructions).toBe(registerInstructions);
- });
- });
-
- describe('when providing a defaultPlatformName', () => {
- beforeEach(async () => {
- createComponent({ props: { defaultPlatformName: 'osx' } });
- await waitForPromises();
- });
-
- it('runner instructions for the default selected platform are requested', () => {
- expect(runnerSetupInstructionsHandler).toHaveBeenCalledWith({
- platform: 'osx',
- architecture: 'amd64',
- });
- });
-
- it('sets the focus on the default selected platform', () => {
- const findOsxPlatformButton = () => wrapper.findComponent({ ref: 'osx' });
-
- findOsxPlatformButton().element.focus = jest.fn();
-
- findModal().vm.$emit('shown');
-
- expect(findOsxPlatformButton().element.focus).toHaveBeenCalled();
- });
- });
});
describe('after a platform and architecture are selected', () => {
@@ -207,14 +167,14 @@ describe('RunnerInstructionsModal component', () => {
it('other binary instructions are shown', () => {
const instructions = findBinaryInstructions().text();
- expect(instructions).toBe(installInstructions);
+ expect(instructions).toBe(installInstructions.trim());
});
it('register command is shown', () => {
const command = findRegisterCommand().text();
expect(command).toBe(
- './gitlab-runner.exe register --url http://gdk.test:3000/ --registration-token MY_TOKEN',
+ './gitlab-runner.exe register --url http://localhost/ --registration-token MY_TOKEN',
);
});
@@ -246,6 +206,43 @@ describe('RunnerInstructionsModal component', () => {
});
});
+ describe('when a register token is not known', () => {
+ beforeEach(async () => {
+ createComponent({ props: { registrationToken: undefined } });
+ await waitForPromises();
+ });
+
+ it('register command is shown without a defined registration token', () => {
+ const instructions = findRegisterCommand().text();
+
+ expect(instructions).toBe(mockGraphqlInstructions.data.runnerSetup.registerInstructions);
+ });
+ });
+
+ describe('with a defaultPlatformName', () => {
+ beforeEach(async () => {
+ createComponent({ props: { defaultPlatformName: 'osx' } });
+ await waitForPromises();
+ });
+
+ it('runner instructions for the default selected platform are requested', () => {
+ expect(runnerSetupInstructionsHandler).toHaveBeenLastCalledWith({
+ platform: 'osx',
+ architecture: 'amd64',
+ });
+ });
+
+ it('sets the focus on the default selected platform', () => {
+ const findOsxPlatformButton = () => wrapper.findComponent({ ref: 'osx' });
+
+ findOsxPlatformButton().element.focus = jest.fn();
+
+ findModal().vm.$emit('shown');
+
+ expect(findOsxPlatformButton().element.focus).toHaveBeenCalled();
+ });
+ });
+
describe('when the modal is not shown', () => {
beforeEach(async () => {
createComponent({ shown: false });
diff --git a/spec/lib/gitlab/ci/config/external/file/remote_spec.rb b/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
index c22afb32756..8d93cdcf378 100644
--- a/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
@@ -188,6 +188,19 @@ RSpec.describe Gitlab::Ci::Config::External::File::Remote do
'is blocked: Requests to localhost are not allowed!'
end
end
+
+ context 'when connection refused error has been raised' do
+ let(:location) { 'http://127.0.0.1/some/path/to/config.yaml' }
+ let(:exception) { Errno::ECONNREFUSED.new }
+
+ before do
+ stub_full_request(location).to_raise(exception)
+ end
+
+ it 'returns details about connection failure' do
+ expect(subject).to eq "Remote file could not be fetched because Connection refused!"
+ end
+ end
end
describe '#expand_context' do