diff options
48 files changed, 419 insertions, 90 deletions
diff --git a/app/views/admin/application_settings/general.html.haml b/app/views/admin/application_settings/general.html.haml index 4f836789389..6d8428d1aa6 100644 --- a/app/views/admin/application_settings/general.html.haml +++ b/app/views/admin/application_settings/general.html.haml @@ -119,7 +119,7 @@ = render_if_exists 'admin/application_settings/feishu_integration' = render 'admin/application_settings/third_party_offers' = render 'admin/application_settings/snowplow' -= render_if_exists 'admin/application_settings/product_analytics' if Feature.enabled?(:cube_api_proxy) += render_if_exists 'admin/application_settings/product_analytics' = render 'admin/application_settings/error_tracking' if Feature.enabled?(:gitlab_error_tracking) = render 'admin/application_settings/eks' = render 'admin/application_settings/floc' diff --git a/config/feature_flags/development/cube_api_proxy.yml b/config/feature_flags/development/cube_api_proxy.yml deleted file mode 100644 index 06dcefb1303..00000000000 --- a/config/feature_flags/development/cube_api_proxy.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: cube_api_proxy -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96250 -rollout_issue_url: -milestone: '15.4' -type: development -group: group::product_analytics -default_enabled: false diff --git a/db/docs/experiment_users.yml b/db/docs/experiment_users.yml deleted file mode 100644 index 38e6c57a283..00000000000 --- a/db/docs/experiment_users.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -table_name: experiment_users -classes: -- ExperimentUser -feature_categories: -- experimentation_conversion -description: TODO -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38397 -milestone: '13.3' diff --git a/db/post_migrate/20221027203556_delete_experiment_user_foreign_keys.rb b/db/post_migrate/20221027203556_delete_experiment_user_foreign_keys.rb new file mode 100644 index 00000000000..564dc3d4899 --- /dev/null +++ b/db/post_migrate/20221027203556_delete_experiment_user_foreign_keys.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class DeleteExperimentUserForeignKeys < Gitlab::Database::Migration[2.0] + disable_ddl_transaction! + + def up + with_lock_retries do + remove_foreign_key_if_exists :experiment_users, :experiments, name: 'fk_rails_56d4708b4a' + end + + with_lock_retries do + remove_foreign_key_if_exists :experiment_users, :users, name: 'fk_rails_fd805f771a' + end + end + + def down + add_concurrent_foreign_key :experiment_users, :experiments, column: :experiment_id, name: 'fk_rails_56d4708b4a' + add_concurrent_foreign_key :experiment_users, :users, column: :user_id, name: 'fk_rails_fd805f771a' + end +end diff --git a/db/post_migrate/20221027203951_drop_experiment_users_table.rb b/db/post_migrate/20221027203951_drop_experiment_users_table.rb new file mode 100644 index 00000000000..95455db98e5 --- /dev/null +++ b/db/post_migrate/20221027203951_drop_experiment_users_table.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class DropExperimentUsersTable < Gitlab::Database::Migration[2.0] + def up + drop_table :experiment_users + end + + def down + create_table :experiment_users do |t| # rubocop:disable Migration/SchemaAdditionMethodsNoPost + t.bigint :experiment_id, null: false + t.bigint :user_id, null: false + t.integer :group_type, limit: 2, null: false, default: 0 + t.timestamps_with_timezone null: false + t.datetime_with_timezone :converted_at + t.jsonb :context, null: false, default: {} + end + + add_index :experiment_users, :experiment_id + add_index :experiment_users, :user_id + end +end diff --git a/db/post_migrate/20221108222015_remove_temp_index_on_project_features_where_releases_access_level_gt_repository.rb b/db/post_migrate/20221108222015_remove_temp_index_on_project_features_where_releases_access_level_gt_repository.rb new file mode 100644 index 00000000000..e7cc6786b4b --- /dev/null +++ b/db/post_migrate/20221108222015_remove_temp_index_on_project_features_where_releases_access_level_gt_repository.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class RemoveTempIndexOnProjectFeaturesWhereReleasesAccessLevelGtRepository < Gitlab::Database::Migration[2.0] + disable_ddl_transaction! + + INDEX_NAME = 'tmp_idx_project_features_on_releases_al_and_repo_al_partial' + + def up + remove_concurrent_index_by_name :project_features, INDEX_NAME + end + + def down + add_concurrent_index :project_features, + [:releases_access_level, :repository_access_level], + name: INDEX_NAME, + where: 'releases_access_level > repository_access_level' + end +end diff --git a/db/schema_migrations/20221027203556 b/db/schema_migrations/20221027203556 new file mode 100644 index 00000000000..e386f0e6bbb --- /dev/null +++ b/db/schema_migrations/20221027203556 @@ -0,0 +1 @@ +9ea13068b90797013677ec390de4222e00e80076080cf4e5335e9f90e2e59f2d
\ No newline at end of file diff --git a/db/schema_migrations/20221027203951 b/db/schema_migrations/20221027203951 new file mode 100644 index 00000000000..866ccf8c208 --- /dev/null +++ b/db/schema_migrations/20221027203951 @@ -0,0 +1 @@ +5f4fd4e64d398208e2d32573273a70106c9a4fd5ab350d75fcf7a6f4c824e00a
\ No newline at end of file diff --git a/db/schema_migrations/20221108222015 b/db/schema_migrations/20221108222015 new file mode 100644 index 00000000000..2b9ce458ce9 --- /dev/null +++ b/db/schema_migrations/20221108222015 @@ -0,0 +1 @@ +555c69896e457b0b41c00926007b422ef34869e45fc0bde89b87ecc2df51de00
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 349af43dc91..2b63a904d11 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -15365,26 +15365,6 @@ CREATE SEQUENCE experiment_subjects_id_seq ALTER SEQUENCE experiment_subjects_id_seq OWNED BY experiment_subjects.id; -CREATE TABLE experiment_users ( - id bigint NOT NULL, - experiment_id bigint NOT NULL, - user_id bigint NOT NULL, - group_type smallint DEFAULT 0 NOT NULL, - created_at timestamp with time zone NOT NULL, - updated_at timestamp with time zone NOT NULL, - converted_at timestamp with time zone, - context jsonb DEFAULT '{}'::jsonb NOT NULL -); - -CREATE SEQUENCE experiment_users_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - -ALTER SEQUENCE experiment_users_id_seq OWNED BY experiment_users.id; - CREATE TABLE experiments ( id bigint NOT NULL, name text NOT NULL, @@ -23775,8 +23755,6 @@ ALTER TABLE ONLY evidences ALTER COLUMN id SET DEFAULT nextval('evidences_id_seq ALTER TABLE ONLY experiment_subjects ALTER COLUMN id SET DEFAULT nextval('experiment_subjects_id_seq'::regclass); -ALTER TABLE ONLY experiment_users ALTER COLUMN id SET DEFAULT nextval('experiment_users_id_seq'::regclass); - ALTER TABLE ONLY experiments ALTER COLUMN id SET DEFAULT nextval('experiments_id_seq'::regclass); ALTER TABLE ONLY external_approval_rules ALTER COLUMN id SET DEFAULT nextval('external_approval_rules_id_seq'::regclass); @@ -25675,9 +25653,6 @@ ALTER TABLE ONLY evidences ALTER TABLE ONLY experiment_subjects ADD CONSTRAINT experiment_subjects_pkey PRIMARY KEY (id); -ALTER TABLE ONLY experiment_users - ADD CONSTRAINT experiment_users_pkey PRIMARY KEY (id); - ALTER TABLE ONLY experiments ADD CONSTRAINT experiments_pkey PRIMARY KEY (id); @@ -29041,10 +29016,6 @@ CREATE INDEX index_experiment_subjects_on_project_id ON experiment_subjects USIN CREATE INDEX index_experiment_subjects_on_user_id ON experiment_subjects USING btree (user_id); -CREATE INDEX index_experiment_users_on_experiment_id ON experiment_users USING btree (experiment_id); - -CREATE INDEX index_experiment_users_on_user_id ON experiment_users USING btree (user_id); - CREATE UNIQUE INDEX index_experiments_on_name ON experiments USING btree (name); CREATE INDEX index_expired_and_not_notified_personal_access_tokens ON personal_access_tokens USING btree (id, expires_at) WHERE ((impersonation = false) AND (revoked = false) AND (expire_notification_delivered = false)); @@ -31219,8 +31190,6 @@ CREATE UNIQUE INDEX taggings_idx ON taggings USING btree (tag_id, taggable_id, t CREATE UNIQUE INDEX term_agreements_unique_index ON term_agreements USING btree (user_id, term_id); -CREATE INDEX tmp_idx_project_features_on_releases_al_and_repo_al_partial ON project_features USING btree (releases_access_level, repository_access_level) WHERE (releases_access_level > repository_access_level); - CREATE INDEX tmp_idx_vulnerabilities_on_id_where_report_type_7_99 ON vulnerabilities USING btree (id) WHERE (report_type = ANY (ARRAY[7, 99])); CREATE INDEX tmp_idx_where_user_details_fields_filled ON users USING btree (id) WHERE (((COALESCE(linkedin, ''::character varying))::text IS DISTINCT FROM ''::text) OR ((COALESCE(twitter, ''::character varying))::text IS DISTINCT FROM ''::text) OR ((COALESCE(skype, ''::character varying))::text IS DISTINCT FROM ''::text) OR ((COALESCE(website_url, ''::character varying))::text IS DISTINCT FROM ''::text) OR ((COALESCE(location, ''::character varying))::text IS DISTINCT FROM ''::text) OR ((COALESCE(organization, ''::character varying))::text IS DISTINCT FROM ''::text)); @@ -34144,9 +34113,6 @@ ALTER TABLE ONLY issuable_metric_images ALTER TABLE ONLY group_deploy_keys ADD CONSTRAINT fk_rails_5682fc07f8 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE RESTRICT; -ALTER TABLE ONLY experiment_users - ADD CONSTRAINT fk_rails_56d4708b4a FOREIGN KEY (experiment_id) REFERENCES experiments(id) ON DELETE CASCADE; - ALTER TABLE ONLY issue_user_mentions ADD CONSTRAINT fk_rails_57581fda73 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE; @@ -35209,9 +35175,6 @@ ALTER TABLE ONLY customer_relations_contacts ALTER TABLE ONLY external_approval_rules ADD CONSTRAINT fk_rails_fd4f9ac573 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; -ALTER TABLE ONLY experiment_users - ADD CONSTRAINT fk_rails_fd805f771a FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE; - ALTER TABLE ONLY cluster_groups ADD CONSTRAINT fk_rails_fdb8648a96 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE; diff --git a/doc/architecture/blueprints/pods/iteration0-organizations-introduction.png b/doc/architecture/blueprints/pods/images/iteration0-organizations-introduction.png Binary files differindex 5725b0fa71f..5725b0fa71f 100644 --- a/doc/architecture/blueprints/pods/iteration0-organizations-introduction.png +++ b/doc/architecture/blueprints/pods/images/iteration0-organizations-introduction.png diff --git a/doc/architecture/blueprints/pods/pods-and-fulfillment.png b/doc/architecture/blueprints/pods/images/pods-and-fulfillment.png Binary files differindex aab8556a5d3..aab8556a5d3 100644 --- a/doc/architecture/blueprints/pods/pods-and-fulfillment.png +++ b/doc/architecture/blueprints/pods/images/pods-and-fulfillment.png diff --git a/doc/architecture/blueprints/pods/term-cluster.png b/doc/architecture/blueprints/pods/images/term-cluster.png Binary files differindex 87e4d631551..87e4d631551 100644 --- a/doc/architecture/blueprints/pods/term-cluster.png +++ b/doc/architecture/blueprints/pods/images/term-cluster.png diff --git a/doc/architecture/blueprints/pods/term-organization.png b/doc/architecture/blueprints/pods/images/term-organization.png Binary files differindex 4c82c62b8f4..4c82c62b8f4 100644 --- a/doc/architecture/blueprints/pods/term-organization.png +++ b/doc/architecture/blueprints/pods/images/term-organization.png diff --git a/doc/architecture/blueprints/pods/term-pod.png b/doc/architecture/blueprints/pods/images/term-pod.png Binary files differindex d8f79df2f29..d8f79df2f29 100644 --- a/doc/architecture/blueprints/pods/term-pod.png +++ b/doc/architecture/blueprints/pods/images/term-pod.png diff --git a/doc/architecture/blueprints/pods/term-top-level-namespace.png b/doc/architecture/blueprints/pods/images/term-top-level-namespace.png Binary files differindex c1cd317d878..c1cd317d878 100644 --- a/doc/architecture/blueprints/pods/term-top-level-namespace.png +++ b/doc/architecture/blueprints/pods/images/term-top-level-namespace.png diff --git a/doc/architecture/blueprints/pods/index.md b/doc/architecture/blueprints/pods/index.md index 15f1dba6daf..220b6348037 100644 --- a/doc/architecture/blueprints/pods/index.md +++ b/doc/architecture/blueprints/pods/index.md @@ -24,7 +24,7 @@ We use the following terms to describe components and properties of the Pods arc A Pod is a set of infrastructure components that contains multiple top-level namespaces that belong to different organizations. The components include both datastores (PostgreSQL, Redis etc.) and stateless services (web etc.). The infrastructure components provided within a Pod are shared among organizations and their top-level namespaces but not shared with other Pods. This isolation of infrastructure components means that Pods are independent from each other. -![Term Pod](term-pod.png) +![Term Pod](images/term-pod.png) #### Pod properties @@ -42,7 +42,7 @@ Discouraged synonyms: GitLab instance, cluster, shard A cluster is a collection of Pods. -![Term Cluster](term-cluster.png) +![Term Cluster](images/term-cluster.png) #### Cluster properties @@ -66,7 +66,7 @@ Organizations work under the following assumptions: 1. Users understand that the majority of pages they view are only scoped to a single organization at a time. 1. Organizations are located on a single pod. -![Term Organization](term-organization.png) +![Term Organization](images/term-organization.png) #### Organization properties @@ -94,7 +94,7 @@ Top-level namespaces may [be replaced by workspaces](https://gitlab.com/gitlab-o Discouraged synonyms: Root-level namespace -![Term Top-level Namespace](term-top-level-namespace.png) +![Term Top-level Namespace](images/term-top-level-namespace.png) #### Top-level namespace properties @@ -207,7 +207,7 @@ We synced with Fulfillment ([recording](https://youtu.be/FkQF3uF7vTY)) to discus A rough representation of this is: -![Pods and Fulfillment](pods-and-fulfillment.png) +![Pods and Fulfillment](images/pods-and-fulfillment.png) #### Potential conflicts with Pods @@ -242,7 +242,7 @@ Organizations solve the following problems: 1. Self-managed instances would set a default organization. 1. Organizations can control user-profiles in a central way. This could be achieved by having an organization specific user-profile. Such a profile makes it possible for the organization administrators to control the user role in a company, enforce user emails, or show a graphical indicator of a user being part of the organization. An example would be a "GitLab Employee stamp" on comments. -![Move to Organizations](iteration0-organizations-introduction.png) +![Move to Organizations](images/iteration0-organizations-introduction.png) #### Why would customers opt-in to Organizations? @@ -313,6 +313,13 @@ This section links all different technical proposals that are being evaluated. - [Stateless Router That Uses a Cache to Pick Pod and pre-flight `/api/v4/pods/learn`](proposal-stateless-router-with-routes-learning.md) +## Impacted features + +The Pods architecture will impact many features requiring some of them to be rewritten, or changed significantly. +This is the list of known affected features with the proposed solutions. + +- [Pods: Git Access](pods-feature-git-access.md) + ## Links - [Internal Pods presentation](https://docs.google.com/presentation/d/1x1uIiN8FR9fhL7pzFh9juHOVcSxEY7d2_q4uiKKGD44/edit#slide=id.ge7acbdc97a_0_155) diff --git a/doc/architecture/blueprints/pods/pods-feature-git-access.md b/doc/architecture/blueprints/pods/pods-feature-git-access.md new file mode 100644 index 00000000000..c949a7bc6e5 --- /dev/null +++ b/doc/architecture/blueprints/pods/pods-feature-git-access.md @@ -0,0 +1,172 @@ +--- +stage: enablement +group: pods +comments: false +description: 'Pods: Git Access' +--- + +DISCLAIMER: +This page may contain information related to upcoming products, features and +functionality. It is important to note that the information presented is for +informational purposes only, so please do not rely on the information for +purchasing or planning purposes. Just like with all projects, the items +mentioned on the page are subject to change or delay, and the development, +release, and timing of any products, features, or functionality remain at the +sole discretion of GitLab Inc. + +This document is a work-in-progress and represents a very early state of the +Pods design. Significant aspects are not documented, though we expect to add +them in the future. This is one possible architecture for Pods, and we intend to +contrast this with alternatives before deciding which approach to implement. +This documentation will be kept even if we decide not to implement this so that +we can document the reasons for not choosing this approach. + +# Pods: Git Access + +This document describes impact of Pods architecture on all Git access (over HTTPS and SSH) +patterns providing explanantion of how potentially those features should be changed +to work well with Pods. + +## 1. Definition + +Git access is done through out the application. It can be an operation performed by the system +(read Git repository) or by user (create a new file via Web IDE, `git clone` or `git push` via command line). + +The Pods architecture defines that all Git repositories will be local to the Pod, +so no repository could be shared with another Pod. + +The Pods architecture will require that any Git operation done can only be handled by a Pod holding +the data. It means that any operation either via Web interface, API, or GraphQL needs to be routed +to the correct Pod. It means that any `git clone` or `git push` operation can only be performed +in a context of a Pod. + +## 2. Data flow + +The are various operations performed today by the GitLab on a Git repository. This describes +the data flow how they behave today to better represent the impact. + +It appears that Git access does require changes only to a few endpoints that are scoped to project. +There appear to be different types of repositories: + +- Project: assigned to Group +- Wiki: additional repository assigned to Project +- Design: similar to Wiki, additional repository assigned to Project +- Snippet: creates a virtual project to hold repository, likely tied to the User + +### 2.1. Git clone over HTTPS + +Execution of: `git clone` over HTTPS + +```mermaid +sequenceDiagram + User ->> Workhorse: GET /gitlab-org/gitlab.git/info/refs?service=git-upload-pack + Workhorse ->> Rails: GET /gitlab-org/gitlab.git/info/refs?service=git-upload-pack + Rails ->> Workhorse: 200 OK + Workhorse ->> Gitaly: RPC InfoRefsUploadPack + Gitaly ->> User: Response + User ->> Workhorse: POST /gitlab-org/gitlab.git/git-upload-pack + Workhorse ->> Gitaly: RPC PostUploadPackWithSidechannel + Gitaly ->> User: Response +``` + +### 2.2. Git clone over SSH + +Execution of: `git clone` over SSH + +```mermaid +sequenceDiagram + User ->> Git SSHD: ssh git@gitlab.com + Git SSHD ->> Rails: GET /api/v4/internal/authorized_keys + Rails ->> Git SSHD: 200 OK (list of accepted SSH keys) + Git SSHD ->> User: Accept SSH + User ->> Git SSHD: git clone over SSH + Git SSHD ->> Rails: POST /api/v4/internal/allowed?project=/gitlab-org/gitlab.git&service=git-upload-pack + Rails ->> Git SSHD: 200 OK + Git SSHD ->> Gitaly: RPC SSHUploadPackWithSidechannel + Gitaly ->> User: Response +``` + +### 2.3. Git push over HTTPS + +Execution of: `git push` over HTTPS + +```mermaid +sequenceDiagram + User ->> Workhorse: GET /gitlab-org/gitlab.git/info/refs?service=git-receive-pack + Workhorse ->> Rails: GET /gitlab-org/gitlab.git/info/refs?service=git-receive-pack + Rails ->> Workhorse: 200 OK + Workhorse ->> Gitaly: RPC PostReceivePack + Gitaly ->> Rails: POST /api/v4/internal/allowed?gl_repository=project-111&service=git-receive-pack + Gitaly ->> Rails: POST /api/v4/internal/pre_receive?gl_repository=project-111 + Gitaly ->> Rails: POST /api/v4/internal/post_receive?gl_repository=project-111 + Gitaly ->> User: Response +``` + +### 2.4. Git push over SSHD + +Execution of: `git clone` over SSH + +```mermaid +sequenceDiagram + User ->> Git SSHD: ssh git@gitlab.com + Git SSHD ->> Rails: GET /api/v4/internal/authorized_keys + Rails ->> Git SSHD: 200 OK (list of accepted SSH keys) + Git SSHD ->> User: Accept SSH + User ->> Git SSHD: git clone over SSH + Git SSHD ->> Rails: POST /api/v4/internal/allowed?project=/gitlab-org/gitlab.git&service=git-receive-pack + Rails ->> Git SSHD: 200 OK + Git SSHD ->> Gitaly: RPC ReceivePack + Gitaly ->> Rails: POST /api/v4/internal/allowed?gl_repository=project-111 + Gitaly ->> Rails: POST /api/v4/internal/pre_receive?gl_repository=project-111 + Gitaly ->> Rails: POST /api/v4/internal/post_receive?gl_repository=project-111 + Gitaly ->> User: Response +``` + +### 2.5. Create commit via Web + +Execution of `Add CHANGELOG` to repository: + +```mermaid +sequenceDiagram + Web ->> Puma: POST /gitlab-org/gitlab/-/create/main + Puma ->> Gitaly: RPC TreeEntry + Gitaly ->> Rails: POST /api/v4/internal/allowed?gl_repository=project-111 + Gitaly ->> Rails: POST /api/v4/internal/pre_receive?gl_repository=project-111 + Gitaly ->> Rails: POST /api/v4/internal/post_receive?gl_repository=project-111 + Gitaly ->> Puma: Response + Puma ->> Web: See CHANGELOG +``` + +## 3. Proposal + +The Pods stateless router proposal requires that any ambigious path (that is not routable) +will be made to be routable. It means that at least the following paths will have to be updated +do introduce a routable entity (project, group, or organization). + +Change: + +- `/api/v4/internal/allowed` => `/api/v4/internal/projects/<gl_repository>/allowed` +- `/api/v4/internal/pre_receive` => `/api/v4/internal/projects/<gl_repository>/pre_receive` +- `/api/v4/internal/post_receive` => `/api/v4/internal/projects/<gl_repository>/post_receive` +- `/api/v4/internal/lfs_authenticate` => `/api/v4/internal/projects/<gl_repository>/lfs_authenticate` + +Where: + +- `gl_repository` can be `project-1111` (`Gitlab::GlRepository`) +- `gl_repository` in some cases might be a full path to repository as executed by GitLab Shell (`/gitlab-org/gitlab.git`) + +## 4. Evaluation + +Supporting Git repositories if a Pod can access only its own repositories does not appear to be complex. + +The one major complication is supporting snippets, but this likely falls in the same category as for the approach +to support user's personal namespaces. + +## 4.1. Pros + +1. The API used for supporting HTTPS/SSH and Hooks are well defined and can easily be made routable. + +## 4.2. Cons + +1. The sharing of repositories objects is limited to the given Pod and Gitaly node. +1. The across-Pods forks are likely impossible to be supported (discover: how this work today across different Gitaly node). diff --git a/doc/architecture/blueprints/pods/pods-feature-template.md b/doc/architecture/blueprints/pods/pods-feature-template.md new file mode 100644 index 00000000000..3ed63942210 --- /dev/null +++ b/doc/architecture/blueprints/pods/pods-feature-template.md @@ -0,0 +1,38 @@ +--- +stage: enablement +group: pods +comments: false +description: 'Pods architecture: Problem A' +--- + +DISCLAIMER: +This page may contain information related to upcoming products, features and +functionality. It is important to note that the information presented is for +informational purposes only, so please do not rely on the information for +purchasing or planning purposes. Just like with all projects, the items +mentioned on the page are subject to change or delay, and the development, +release, and timing of any products, features, or functionality remain at the +sole discretion of GitLab Inc. + +This document is a work-in-progress and represents a very early state of the +Pods design. Significant aspects are not documented, though we expect to add +them in the future. This is one possible architecture for Pods, and we intend to +contrast this with alternatives before deciding which approach to implement. +This documentation will be kept even if we decide not to implement this so that +we can document the reasons for not choosing this approach. + +# Pods: Problem A + +> TL;DR + +## 1. Definition + +## 2. Data flow + +## 3. Proposal + +## 4. Evaluation + +## 4.1. Pros + +## 4.2. Cons diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md index fddf4178559..6fc01a716b2 100644 --- a/doc/user/application_security/container_scanning/index.md +++ b/doc/user/application_security/container_scanning/index.md @@ -259,7 +259,7 @@ including a large number of false positives. | `CS_IMAGE_SUFFIX` | `""` | Suffix added to `CS_ANALYZER_IMAGE`. If set to `-fips`, `FIPS-enabled` image is used for scan. See [FIPS-enabled images](#fips-enabled-images) for more details. [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/7630) in GitLab 14.10. | All | | `CS_IGNORE_UNFIXED` | `"false"` | Ignore vulnerabilities that are not fixed. | All | | `CS_REGISTRY_INSECURE` | `"false"` | Allow access to insecure registries (HTTP only). Should only be set to `true` when testing the image locally. Works with all scanners, but the registry must listen on port `80/tcp` for Trivy to work. | All | -| `CS_SEVERITY_THRESHOLD` | `UNKNOWN` | Severity level threshold. The scanner outputs vulnerabilities with severity level higher than or equal to this threshold. Supported levels are Unknown, Low, Medium, High, and Critical. | Trivy | +| `CS_SEVERITY_THRESHOLD` | `UNKNOWN` | Severity level threshold. The scanner outputs vulnerabilities with severity level higher than or equal to this threshold. Supported levels are `UNKNOWN`, `LOW`, `MEDIUM`, `HIGH`, and `CRITICAL`. | Trivy | | <!-- start_remove The following content will be removed on remove_date: '2023-08-22' --> `DOCKER_IMAGE` | `$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG` | **Deprecated** will be removed in GitLab 16.0. Replaced by `CS_IMAGE`. The Docker image to be scanned. If set, this variable overrides the `$CI_APPLICATION_REPOSITORY` and `$CI_APPLICATION_TAG` variables. | All | | `DOCKER_PASSWORD` | `$CI_REGISTRY_PASSWORD` | **Deprecated** will be removed in GitLab 16.0. Replaced by `CS_REGISTRY_PASSWORD`. Password for accessing a Docker registry requiring authentication. The default is only set if `$DOCKER_IMAGE` resides at [`$CI_REGISTRY`](../../../ci/variables/predefined_variables.md). Not supported when [FIPS mode](../../../development/fips_compliance.md#enable-fips-mode) is enabled. | All | | `DOCKER_USER` | `$CI_REGISTRY_USER` | **Deprecated** will be removed in GitLab 16.0. Replaced by `CS_REGISTRY_USER`. Username for accessing a Docker registry requiring authentication. The default is only set if `$DOCKER_IMAGE` resides at [`$CI_REGISTRY`](../../../ci/variables/predefined_variables.md). Not supported when [FIPS mode](../../../development/fips_compliance.md#enable-fips-mode) is enabled. | All | diff --git a/lib/api/ci/secure_files.rb b/lib/api/ci/secure_files.rb index e04718b72f0..dd628a3413f 100644 --- a/lib/api/ci/secure_files.rb +++ b/lib/api/ci/secure_files.rb @@ -61,7 +61,7 @@ module API desc 'Upload a Secure File' params do requires :name, type: String, desc: 'The name of the file' - requires :file, types: [Rack::Multipart::UploadedFile, ::API::Validations::Types::WorkhorseFile], desc: 'The secure file to be uploaded' + requires :file, types: [Rack::Multipart::UploadedFile, ::API::Validations::Types::WorkhorseFile], desc: 'The secure file to be uploaded', documentation: { type: 'file' } end route_setting :authentication, basic_auth_personal_access_token: true, job_token_allowed: true post ':id/secure_files' do diff --git a/lib/api/concerns/packages/conan_endpoints.rb b/lib/api/concerns/packages/conan_endpoints.rb index d8c2eb4ff33..fdbffb1689b 100644 --- a/lib/api/concerns/packages/conan_endpoints.rb +++ b/lib/api/concerns/packages/conan_endpoints.rb @@ -29,7 +29,7 @@ module API CONAN_REVISION_REGEX = Gitlab::Regex.conan_revision_regex CONAN_REVISION_USER_CHANNEL_REGEX = Gitlab::Regex.conan_recipe_user_channel_regex - CONAN_FILES = (Gitlab::Regex::Packages::CONAN_RECIPE_FILES + Gitlab::Regex::Packages::CONAN_PACKAGE_FILES).freeze + CONAN_FILES = (Gitlab::Regex::Packages::CONAN_RECIPE_FILES + Gitlab::Regex::Packages::CONAN_PACKAGE_FILES).uniq.freeze included do feature_category :package_registry @@ -307,7 +307,7 @@ module API end params do - requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)' + requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)', documentation: { type: 'file' } end route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true @@ -358,7 +358,7 @@ module API end params do - requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)' + requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)', documentation: { type: 'file' } end route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true diff --git a/lib/api/debian_project_packages.rb b/lib/api/debian_project_packages.rb index 1c7b29ab0b9..df3b6e774ae 100644 --- a/lib/api/debian_project_packages.rb +++ b/lib/api/debian_project_packages.rb @@ -64,7 +64,7 @@ module API # PUT {projects|groups}/:id/packages/debian/:file_name params do - requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)' + requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)', documentation: { type: 'file' } end route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth, authenticate_non_public: true diff --git a/lib/api/generic_packages.rb b/lib/api/generic_packages.rb index f7785cb8b52..3584f8d025a 100644 --- a/lib/api/generic_packages.rb +++ b/lib/api/generic_packages.rb @@ -54,7 +54,7 @@ module API requires :package_version, type: String, desc: 'Package version', regexp: Gitlab::Regex.generic_package_version_regex requires :file_name, type: String, desc: 'Package file name', regexp: Gitlab::Regex.generic_package_file_name_regex, file_path: true optional :status, type: String, values: ALLOWED_STATUSES, desc: 'Package status' - requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)' + requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)', documentation: { type: 'file' } optional :select, type: String, values: %w[package_file] end diff --git a/lib/api/maven_packages.rb b/lib/api/maven_packages.rb index e5799352fe9..63b6749e9ce 100644 --- a/lib/api/maven_packages.rb +++ b/lib/api/maven_packages.rb @@ -268,7 +268,7 @@ module API params do requires :path, type: String, desc: 'Package path' requires :file_name, type: String, desc: 'Package file name', regexp: Gitlab::Regex.maven_file_name_regex - requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)' + requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)', documentation: { type: 'file' } end route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true put ':id/packages/maven/*path/:file_name', requirements: MAVEN_ENDPOINT_REQUIREMENTS do diff --git a/lib/api/nuget_project_packages.rb b/lib/api/nuget_project_packages.rb index cc4e9777b07..d549a8be035 100644 --- a/lib/api/nuget_project_packages.rb +++ b/lib/api/nuget_project_packages.rb @@ -35,7 +35,7 @@ module API helpers do params :file_params do - requires :package, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)' + requires :package, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)', documentation: { type: 'file' } end def project_or_group diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 81ccd6ba349..ffe4b15f941 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -654,7 +654,7 @@ module API desc 'Upload a file' params do - requires :file, types: [Rack::Multipart::UploadedFile, ::API::Validations::Types::WorkhorseFile], desc: 'The attachment file to be uploaded' + requires :file, types: [Rack::Multipart::UploadedFile, ::API::Validations::Types::WorkhorseFile], desc: 'The attachment file to be uploaded', documentation: { type: 'file' } end post ":id/uploads", feature_category: :not_owned do # rubocop:todo Gitlab/AvoidFeatureCategoryNotOwned log_if_upload_exceed_max_size(user_project, params[:file]) diff --git a/lib/api/pypi_packages.rb b/lib/api/pypi_packages.rb index ffc88d1c1cf..6c649483da1 100644 --- a/lib/api/pypi_packages.rb +++ b/lib/api/pypi_packages.rb @@ -214,7 +214,7 @@ module API end params do - requires :content, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)' + requires :content, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)', documentation: { type: 'file' } requires :name, type: String requires :version, type: String optional :requires_python, type: String diff --git a/lib/api/rubygem_packages.rb b/lib/api/rubygem_packages.rb index b4d02613e4c..87cf1f66223 100644 --- a/lib/api/rubygem_packages.rb +++ b/lib/api/rubygem_packages.rb @@ -93,7 +93,7 @@ module API detail 'This feature was introduced in GitLab 13.9' end params do - requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)' + requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)', documentation: { type: 'file' } end post 'gems' do authorize_upload!(user_project) diff --git a/lib/api/terraform/modules/v1/packages.rb b/lib/api/terraform/modules/v1/packages.rb index 267d41e5fb9..a48a49f9ba7 100644 --- a/lib/api/terraform/modules/v1/packages.rb +++ b/lib/api/terraform/modules/v1/packages.rb @@ -203,7 +203,7 @@ module API end params do - requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)' + requires :file, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)', documentation: { type: 'file' } end put do diff --git a/lib/gitlab/database/gitlab_schemas.yml b/lib/gitlab/database/gitlab_schemas.yml index 15dba48b8ba..ebd15d99ab6 100644 --- a/lib/gitlab/database/gitlab_schemas.yml +++ b/lib/gitlab/database/gitlab_schemas.yml @@ -207,7 +207,6 @@ events: :gitlab_main evidences: :gitlab_main experiments: :gitlab_main experiment_subjects: :gitlab_main -experiment_users: :gitlab_main external_approval_rules: :gitlab_main external_approval_rules_protected_branches: :gitlab_main external_pull_requests: :gitlab_ci diff --git a/lib/gitlab/database/lock_writes_manager.rb b/lib/gitlab/database/lock_writes_manager.rb index fe75cd763b4..2594ee04b35 100644 --- a/lib/gitlab/database/lock_writes_manager.rb +++ b/lib/gitlab/database/lock_writes_manager.rb @@ -5,6 +5,11 @@ module Gitlab class LockWritesManager TRIGGER_FUNCTION_NAME = 'gitlab_schema_prevent_write' + # Triggers to block INSERT / UPDATE / DELETE + # Triggers on TRUNCATE are not added to the information_schema.triggers + # See https://www.postgresql.org/message-id/16934.1568989957%40sss.pgh.pa.us + EXPECTED_TRIGGER_RECORD_COUNT = 3 + def initialize(table_name:, connection:, database_name:, logger: nil, dry_run: false) @table_name = table_name @connection = connection @@ -20,7 +25,7 @@ module Gitlab AND trigger_name = '#{write_trigger_name(table_name)}' SQL - connection.select_value(query) == 3 + connection.select_value(query) == EXPECTED_TRIGGER_RECORD_COUNT end def lock_writes diff --git a/lib/gitlab/project_template.rb b/lib/gitlab/project_template.rb index 6673940ccf3..51a5bedc44b 100644 --- a/lib/gitlab/project_template.rb +++ b/lib/gitlab/project_template.rb @@ -28,6 +28,14 @@ module Gitlab "#{preview}.git" end + def project_host + return unless preview + + uri = URI.parse(preview) + uri.path = "" + uri.to_s + end + def project_path URI.parse(preview).path.delete_prefix('/') end diff --git a/lib/tasks/contracts/pipelines.rake b/lib/tasks/contracts/pipelines.rake index 3163791460f..5a8d7791233 100644 --- a/lib/tasks/contracts/pipelines.rake +++ b/lib/tasks/contracts/pipelines.rake @@ -24,9 +24,13 @@ namespace :contracts do end Pact::VerificationTask.new(:get_pipeline_header_data) do |pact| + # pact.uri( + # "http://localhost:9292/pacts/provider/GET%20pipeline%20header%20data/consumer/Pipelines%23show/latest", + # pact_helper: "#{provider}/pact_helpers/project/pipeline/show/get_pipeline_header_data_helper.rb" + # ) pact.uri( "#{contracts}/show/pipelines#show-get_pipeline_header_data.json", - pact_helper: "#{provider}/pact_helpers/project/pipeline/show/get_pipeline_header_data_helper.rb" + pact_helper: "#{provider}/pact_helpers/project/pipeline/show/get_pipeline_header_data_helper.rb" ) end diff --git a/lib/tasks/gitlab/update_templates.rake b/lib/tasks/gitlab/update_templates.rake index 07dd5ebeacb..d67ad340007 100644 --- a/lib/tasks/gitlab/update_templates.rake +++ b/lib/tasks/gitlab/update_templates.rake @@ -58,14 +58,14 @@ namespace :gitlab do # extract a concrete commit for signing off what we actually downloaded # this way we do the right thing even if the repository gets updated in the meantime - get_commits_response = Gitlab::HTTP.get("https://gitlab.com/api/v4/projects/#{uri_encoded_project_path}/repository/commits", + get_commits_response = Gitlab::HTTP.get("#{template.project_host}/api/v4/projects/#{uri_encoded_project_path}/repository/commits", query: { page: 1, per_page: 1 } ) raise "Failed to retrieve latest commit for template '#{template.name}'" unless get_commits_response.success? commit_sha = get_commits_response.parsed_response.dig(0, 'id') - project_archive_uri = "https://gitlab.com/api/v4/projects/#{uri_encoded_project_path}/repository/archive.tar.gz?sha=#{commit_sha}" + project_archive_uri = "#{template.project_host}/api/v4/projects/#{uri_encoded_project_path}/repository/archive.tar.gz?sha=#{commit_sha}" commit_message = <<~MSG Initialized from '#{template.title}' project template diff --git a/spec/contracts/provider/helpers/publish_contract_helper.rb b/spec/contracts/provider/helpers/publish_contract_helper.rb new file mode 100644 index 00000000000..102a73d87ee --- /dev/null +++ b/spec/contracts/provider/helpers/publish_contract_helper.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module Provider + module PublishContractHelper + PROVIDER_VERSION = ENV['GIT_COMMIT'] || `git rev-parse --verify HEAD`.strip + PROVIDER_BRANCH = ENV['GIT_BRANCH'] || `git name-rev --name-only HEAD`.strip + PUBLISH_FLAG = true + + def self.publish_contract_setup + @setup ||= -> { + app_version PROVIDER_VERSION + app_version_branch PROVIDER_BRANCH + publish_verification_results PUBLISH_FLAG + } + end + end +end diff --git a/spec/contracts/provider/pact_helpers/project/merge_request/show/diffs_batch_helper.rb b/spec/contracts/provider/pact_helpers/project/merge_request/show/diffs_batch_helper.rb index f94ce47b1f3..71f302f2c44 100644 --- a/spec/contracts/provider/pact_helpers/project/merge_request/show/diffs_batch_helper.rb +++ b/spec/contracts/provider/pact_helpers/project/merge_request/show/diffs_batch_helper.rb @@ -11,6 +11,8 @@ module Provider honours_pact_with 'MergeRequest#show' do pact_uri '../contracts/project/merge_request/show/mergerequest#show-merge_request_diffs_batch_endpoint.json' end + + Provider::PublishContractHelper.publish_contract_setup.call end end end diff --git a/spec/contracts/provider/pact_helpers/project/merge_request/show/diffs_metadata_helper.rb b/spec/contracts/provider/pact_helpers/project/merge_request/show/diffs_metadata_helper.rb index 61567214b7a..60a3abea5ae 100644 --- a/spec/contracts/provider/pact_helpers/project/merge_request/show/diffs_metadata_helper.rb +++ b/spec/contracts/provider/pact_helpers/project/merge_request/show/diffs_metadata_helper.rb @@ -11,6 +11,10 @@ module Provider honours_pact_with 'MergeRequest#show' do pact_uri '../contracts/project/merge_request/show/mergerequest#show-merge_request_diffs_metadata_endpoint.json' end + + app_version Provider::PublishContractHelper::PROVIDER_VERSION + app_version_branch Provider::PublishContractHelper::PROVIDER_BRANCH + publish_verification_results Provider::PublishContractHelper::PUBLISH_FLAG end end end diff --git a/spec/contracts/provider/pact_helpers/project/merge_request/show/discussions_helper.rb b/spec/contracts/provider/pact_helpers/project/merge_request/show/discussions_helper.rb index fa76ce8889a..b9308af0a1a 100644 --- a/spec/contracts/provider/pact_helpers/project/merge_request/show/discussions_helper.rb +++ b/spec/contracts/provider/pact_helpers/project/merge_request/show/discussions_helper.rb @@ -11,6 +11,10 @@ module Provider honours_pact_with 'MergeRequest#show' do pact_uri '../contracts/project/merge_request/show/mergerequest#show-merge_request_discussions_endpoint.json' end + + app_version Provider::PublishContractHelper::PROVIDER_VERSION + app_version_branch Provider::PublishContractHelper::PROVIDER_BRANCH + publish_verification_results Provider::PublishContractHelper::PUBLISH_FLAG end end end diff --git a/spec/contracts/provider/pact_helpers/project/pipeline/index/create_a_new_pipeline_helper.rb b/spec/contracts/provider/pact_helpers/project/pipeline/index/create_a_new_pipeline_helper.rb index 247a7c4ca8e..2af960bc9fd 100644 --- a/spec/contracts/provider/pact_helpers/project/pipeline/index/create_a_new_pipeline_helper.rb +++ b/spec/contracts/provider/pact_helpers/project/pipeline/index/create_a_new_pipeline_helper.rb @@ -11,6 +11,10 @@ module Provider honours_pact_with 'Pipelines#new' do pact_uri '../contracts/project/pipeline/new/pipelines#new-post_create_a_new_pipeline.json' end + + app_version Provider::PublishContractHelper::PROVIDER_VERSION + app_version_branch Provider::PublishContractHelper::PROVIDER_BRANCH + publish_verification_results Provider::PublishContractHelper::PUBLISH_FLAG end end end diff --git a/spec/contracts/provider/pact_helpers/project/pipeline/index/get_list_project_pipelines_helper.rb b/spec/contracts/provider/pact_helpers/project/pipeline/index/get_list_project_pipelines_helper.rb index 80cbbe3b4dd..37cddd1b80e 100644 --- a/spec/contracts/provider/pact_helpers/project/pipeline/index/get_list_project_pipelines_helper.rb +++ b/spec/contracts/provider/pact_helpers/project/pipeline/index/get_list_project_pipelines_helper.rb @@ -11,6 +11,10 @@ module Provider honours_pact_with 'Pipelines#index' do pact_uri '../contracts/project/project/pipeline/index/pipelines#index-get_list_project_pipelines.json' end + + app_version Provider::PublishContractHelper::PROVIDER_VERSION + app_version_branch Provider::PublishContractHelper::PROVIDER_BRANCH + publish_verification_results Provider::PublishContractHelper::PUBLISH_FLAG end end end diff --git a/spec/contracts/provider/pact_helpers/project/pipeline/show/delete_pipeline_helper.rb b/spec/contracts/provider/pact_helpers/project/pipeline/show/delete_pipeline_helper.rb index 2d29fabfeca..0455281fcd7 100644 --- a/spec/contracts/provider/pact_helpers/project/pipeline/show/delete_pipeline_helper.rb +++ b/spec/contracts/provider/pact_helpers/project/pipeline/show/delete_pipeline_helper.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require_relative '../../../../spec_helper' +require_relative '../../../../helpers/publish_contract_helper' require_relative '../../../../states/project/pipeline/show_state' module Provider @@ -11,6 +12,10 @@ module Provider honours_pact_with 'Pipelines#show' do pact_uri '../contracts/project/pipeline/show/pipelines#show-delete_pipeline.json' end + + app_version Provider::PublishContractHelper::PROVIDER_VERSION + app_version_branch Provider::PublishContractHelper::PROVIDER_BRANCH + publish_verification_results Provider::PublishContractHelper::PUBLISH_FLAG end end end diff --git a/spec/contracts/provider/pact_helpers/project/pipeline/show/get_pipeline_header_data_helper.rb b/spec/contracts/provider/pact_helpers/project/pipeline/show/get_pipeline_header_data_helper.rb index bc8c04cc455..bce1c4ab3f4 100644 --- a/spec/contracts/provider/pact_helpers/project/pipeline/show/get_pipeline_header_data_helper.rb +++ b/spec/contracts/provider/pact_helpers/project/pipeline/show/get_pipeline_header_data_helper.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require_relative '../../../../spec_helper' +require_relative '../../../../helpers/publish_contract_helper' require_relative '../../../../states/project/pipeline/show_state' module Provider @@ -10,7 +11,12 @@ module Provider honours_pact_with 'Pipelines#show' do pact_uri '../contracts/project/pipeline/show/pipelines#show-get_project_pipeline_header_data.json' + # pact_uri 'http://localhost:9292/pacts/provider/GET%20pipeline%20header%20data/consumer/Pipelines%23show/latest' end + + app_version Provider::PublishContractHelper::PROVIDER_VERSION + app_version_branch Provider::PublishContractHelper::PROVIDER_BRANCH + publish_verification_results Provider::PublishContractHelper::PUBLISH_FLAG end end end diff --git a/spec/contracts/provider/pact_helpers/project/pipeline_schedule/update_pipeline_schedule_helper.rb b/spec/contracts/provider/pact_helpers/project/pipeline_schedule/update_pipeline_schedule_helper.rb index a83aa9524dc..d95a09abd8d 100644 --- a/spec/contracts/provider/pact_helpers/project/pipeline_schedule/update_pipeline_schedule_helper.rb +++ b/spec/contracts/provider/pact_helpers/project/pipeline_schedule/update_pipeline_schedule_helper.rb @@ -11,6 +11,10 @@ module Provider honours_pact_with 'PipelineSchedule#edit' do pact_uri '../contracts/project/pipeline_schedule/edit/pipelineschedules#edit-put_edit_a_pipeline_schedule.json' end + + app_version Provider::PublishContractHelper::PROVIDER_VERSION + app_version_branch Provider::PublishContractHelper::PROVIDER_BRANCH + publish_verification_results Provider::PublishContractHelper::PUBLISH_FLAG end end end diff --git a/spec/contracts/publish-contracts.sh b/spec/contracts/publish-contracts.sh new file mode 100644 index 00000000000..f20cc43e258 --- /dev/null +++ b/spec/contracts/publish-contracts.sh @@ -0,0 +1,23 @@ +LATEST_SHA=$(git rev-parse HEAD) +GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD) +BROKER_BASE_URL="http://localhost:9292" + +CONTRACTS=$(find ./contracts -name "*.json") +ERROR=0 + +trap 'catch' ERR + +function catch() { + printf "\e[31mAn error occured while trying to publish the pact.\033[0m\n" + ERROR=1 +} + +for contract in $CONTRACTS +do + printf "\e[32mPublishing ${contract}...\033[0m\n" + pact-broker publish $contract --consumer-app-version $LATEST_SHA --branch $GIT_BRANCH --broker-base-url $BROKER_BASE_URL --output json +done + +if [ ${ERROR} = 1 ]; then + exit 1; +fi
\ No newline at end of file diff --git a/spec/lib/gitlab/project_template_spec.rb b/spec/lib/gitlab/project_template_spec.rb index 630369977ff..998fff12e94 100644 --- a/spec/lib/gitlab/project_template_spec.rb +++ b/spec/lib/gitlab/project_template_spec.rb @@ -12,6 +12,20 @@ RSpec.describe Gitlab::ProjectTemplate do end end + describe '#project_host' do + context "when `preview` is valid" do + subject { described_class.new('name', 'title', 'description', 'https://gitlab.com/some/project/path').project_host } + + it { is_expected.to eq 'https://gitlab.com' } + end + + context "when `preview` is `nil`" do + subject { described_class.new('name', 'title', 'description', nil).project_host } + + it { is_expected.to eq nil } + end + end + describe '#project_path' do subject { described_class.new('name', 'title', 'description', 'https://gitlab.com/some/project/path').project_path } diff --git a/spec/models/jira_connect_installation_spec.rb b/spec/models/jira_connect_installation_spec.rb index e57d3e78a4e..09a4a7a488c 100644 --- a/spec/models/jira_connect_installation_spec.rb +++ b/spec/models/jira_connect_installation_spec.rb @@ -71,7 +71,7 @@ RSpec.describe JiraConnectInstallation do end describe '#oauth_authorization_url' do - let_it_be(:installation) { create(:jira_connect_installation) } + let(:installation) { build(:jira_connect_installation) } subject { installation.oauth_authorization_url } @@ -82,7 +82,7 @@ RSpec.describe JiraConnectInstallation do it { is_expected.to eq('http://test.host') } context 'with instance_url' do - let_it_be(:installation) { create(:jira_connect_installation, instance_url: 'https://gitlab.example.com') } + let(:installation) { build(:jira_connect_installation, instance_url: 'https://gitlab.example.com') } it { is_expected.to eq('https://gitlab.example.com') } @@ -97,42 +97,42 @@ RSpec.describe JiraConnectInstallation do end describe 'audience_url' do - let_it_be(:installation) { create(:jira_connect_installation) } + let(:installation) { build(:jira_connect_installation) } subject(:audience) { installation.audience_url } it { is_expected.to eq(nil) } context 'when proxy installation' do - let_it_be(:installation) { create(:jira_connect_installation, instance_url: 'https://example.com') } + let(:installation) { build(:jira_connect_installation, instance_url: 'https://example.com') } it { is_expected.to eq('https://example.com/-/jira_connect') } end end describe 'audience_installed_event_url' do - let_it_be(:installation) { create(:jira_connect_installation) } + let(:installation) { build(:jira_connect_installation) } subject(:audience) { installation.audience_installed_event_url } it { is_expected.to eq(nil) } context 'when proxy installation' do - let_it_be(:installation) { create(:jira_connect_installation, instance_url: 'https://example.com') } + let(:installation) { build(:jira_connect_installation, instance_url: 'https://example.com') } it { is_expected.to eq('https://example.com/-/jira_connect/events/installed') } end end describe 'proxy?' do - let_it_be(:installation) { create(:jira_connect_installation) } + let(:installation) { build(:jira_connect_installation) } subject { installation.proxy? } it { is_expected.to eq(false) } context 'when instance_url is present' do - let_it_be(:installation) { create(:jira_connect_installation, instance_url: 'https://example.com') } + let(:installation) { build(:jira_connect_installation, instance_url: 'https://example.com') } it { is_expected.to eq(true) } end diff --git a/spec/tasks/gitlab/update_templates_rake_spec.rb b/spec/tasks/gitlab/update_templates_rake_spec.rb index 7eccdf22a1f..85da490f718 100644 --- a/spec/tasks/gitlab/update_templates_rake_spec.rb +++ b/spec/tasks/gitlab/update_templates_rake_spec.rb @@ -4,6 +4,7 @@ require 'rake_helper' RSpec.describe 'gitlab:update_project_templates rake task', :silence_stdout do let!(:tmpdir) { Dir.mktmpdir } + let(:template) { Gitlab::ProjectTemplate.find(:rails) } before do Rake.application.rake_require 'tasks/gitlab/update_templates' @@ -14,7 +15,7 @@ RSpec.describe 'gitlab:update_project_templates rake task', :silence_stdout do .and_return(Pathname.new(tmpdir)) # Gitlab::HTTP resolves the domain to an IP prior to WebMock taking effect, hence the wildcard - stub_request(:get, %r{^https://.*/api/v4/projects/gitlab-org%2Fproject-templates%2Frails/repository/commits\?page=1&per_page=1}) + stub_request(:get, %r{^https://.*/api/v4/projects/#{template.uri_encoded_project_path}/repository/commits\?page=1&per_page=1}) .to_return( status: 200, body: [{ id: '67812735b83cb42710f22dc98d73d42c8bf4d907' }].to_json, @@ -27,8 +28,8 @@ RSpec.describe 'gitlab:update_project_templates rake task', :silence_stdout do end it 'updates valid project templates' do - expect { run_rake_task('gitlab:update_project_templates', ['rails']) } + expect { run_rake_task('gitlab:update_project_templates', [template.name]) } .to change { Dir.entries(tmpdir) } - .by(['rails.tar.gz']) + .by(["#{template.name}.tar.gz"]) end end |