diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/ci/pipelines/settings.md | 5 | ||||
-rw-r--r-- | doc/development/database/efficient_in_operator_queries.md | 2 | ||||
-rw-r--r-- | doc/development/directory_structure.md | 97 | ||||
-rw-r--r-- | doc/development/feature_development.md | 2 | ||||
-rw-r--r-- | doc/development/i18n/externalization.md | 8 | ||||
-rw-r--r-- | doc/development/reusing_abstractions.md | 2 | ||||
-rw-r--r-- | doc/development/software_design.md | 141 | ||||
-rw-r--r-- | doc/subscriptions/img/add-license.png | bin | 0 -> 36742 bytes | |||
-rw-r--r-- | doc/subscriptions/index.md | 8 | ||||
-rw-r--r-- | doc/user/project/integrations/slack.md | 4 |
10 files changed, 163 insertions, 106 deletions
diff --git a/doc/ci/pipelines/settings.md b/doc/ci/pipelines/settings.md index a7f3cfb59d3..e99644fb6ee 100644 --- a/doc/ci/pipelines/settings.md +++ b/doc/ci/pipelines/settings.md @@ -284,9 +284,8 @@ when merging a merge request would cause the project's test coverage to decline. Follow these steps to enable the `Coverage-Check` MR approval rule: 1. Set up a [`coverage`](../yaml/index.md#coverage) regular expression for all jobs you want to include in the overall coverage value. -1. Go to your project and select **Settings > General**. -1. Expand **Merge request approvals**. -1. Select **Enable** next to the `Coverage-Check` approval rule. +1. Go to your project and select **Settings > Merge requests**. +1. Under **Merge request approvals**, select **Enable** next to the `Coverage-Check` approval rule. 1. Select the **Target branch**. 1. Set the number of **Approvals required** to greater than zero. 1. Select the users or groups to provide approval. diff --git a/doc/development/database/efficient_in_operator_queries.md b/doc/development/database/efficient_in_operator_queries.md index fb7ff3c1cc2..0f65dcfef9e 100644 --- a/doc/development/database/efficient_in_operator_queries.md +++ b/doc/development/database/efficient_in_operator_queries.md @@ -160,7 +160,7 @@ The technique can only optimize `IN` queries that satisfy the following requirem in the following order: `column_for_the_in_query`, `order by column 1`, and `order by column 2`. - The columns in the `ORDER BY` clause are distinct - (the combination of the columns uniquely identifies one particular column in the table). + (the combination of the columns uniquely identifies one particular row in the table). WARNING: This technique does not improve the performance of the `COUNT(*)` queries. diff --git a/doc/development/directory_structure.md b/doc/development/directory_structure.md index 27384fa559f..34ee86d9ee5 100644 --- a/doc/development/directory_structure.md +++ b/doc/development/directory_structure.md @@ -1,94 +1,11 @@ --- -stage: none -group: unassigned -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +redirect_to: 'software_design.md' +remove_date: '2023-01-24' --- -# Backend directory structure +This document was moved to [another location](software_design.md) -## Use namespaces to define bounded contexts - -A healthy application is divided into macro and sub components that represent the contexts at play, -whether they are related to business domain or infrastructure code. - -As GitLab code has so many features and components it's hard to see what contexts are involved. -We should expect any class to be defined inside a module/namespace that represents the contexts where it operates. - -When we namespace classes inside their domain: - -- Similar terminology becomes unambiguous as the domain clarifies the meaning: - For example, `MergeRequests::Diff` and `Notes::Diff`. -- Top-level namespaces could be associated to one or more groups identified as domain experts. -- We can better identify the interactions and coupling between components. - For example, several classes inside `MergeRequests::` domain interact more with `Ci::` - domain and less with `ImportExport::`. - -```ruby -# bad -class MyClass -end - -# good -module MyDomain - class MyClass - end -end -``` - -### About namespace naming - -A good guideline for naming a top-level namespace (bounded context) is to use the related -[feature category](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/data/categories.yml). For example, `Continuous Integration` feature category maps to `Ci::` namespace. - -Alternatively a new class could be added to `Projects::` or `Groups::` if it's either: - -- Strictly related to one of these domains. For example `Projects::Alias`. -- A new component that does not have yet a more specific domain. In this case, when - a more explicit domain does emerge we would need to move the class to a more specific - namespace. - -Do not use the [stage or group name](https://about.gitlab.com/handbook/product/categories/#devops-stages) -since a feature category could be reassigned to a different group in the future. - -```ruby -# bad -module Create - class Commit - end -end - -# good -module Repositories - class Commit - end -end -``` - -On the other hand, a feature category may sometimes be too granular. Features tend to be -treated differently according to Product and Marketing, while they may share a lot of -domain models and behavior under the hood. In this case, having too many bounded contexts -could make them shallow and more coupled with other contexts. - -Bounded contexts (or top-level namespaces) can be seen as macro-components in the overall app. -Good bounded contexts should be [deep](https://medium.com/@nakabonne/depth-of-module-f62dac3c2fdb) -so consider having nested namespaces to further break down complex parts of the domain. -For example, `Ci::Config::`. - -For example, instead of having separate and granular bounded contexts like: `ContainerScanning::`, -`ContainerHostSecurity::`, `ContainerNetworkSecurity::`, we could have: - -```ruby -module ContainerSecurity - module HostSecurity - end - - module NetworkSecurity - end - - module Scanning - end -end -``` - -If classes that are defined into a namespace have a lot in common with classes in other namespaces, -chances are that these two namespaces are part of the same bounded context. +<!-- This redirect file can be deleted after <2023-01-24>. --> +<!-- Redirects that point to other docs in the same project expire in three months. --> +<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html --> diff --git a/doc/development/feature_development.md b/doc/development/feature_development.md index 2f6a5e25107..d839dcbdf77 100644 --- a/doc/development/feature_development.md +++ b/doc/development/feature_development.md @@ -19,7 +19,7 @@ Consult these topics for information on contributing to specific GitLab features ### General -- [Directory structure](directory_structure.md) +- [Software design guides](software_design.md) - [GitLab EventStore](event_store.md) to publish/subscribe to domain events - [GitLab utilities](utilities.md) - [Newlines style guide](newlines_styleguide.md) diff --git a/doc/development/i18n/externalization.md b/doc/development/i18n/externalization.md index 91e2efcb2a3..2269a28e496 100644 --- a/doc/development/i18n/externalization.md +++ b/doc/development/i18n/externalization.md @@ -284,9 +284,7 @@ expect(wrapper.text()).toEqual(MSG_ALERT_SETTINGS_FORM_ERROR); ### Dynamic translations -Sometimes there are dynamic translations that the parser can't find when running -`bin/rake gettext:find`. For these scenarios you can use the [`N_` method](https://github.com/grosser/gettext_i18n_rails/blob/c09e38d481e0899ca7d3fc01786834fa8e7aab97/Readme.md#unfound-translations-with-rake-gettextfind). -There's also an alternative method to [translate messages from validation errors](https://github.com/grosser/gettext_i18n_rails/blob/c09e38d481e0899ca7d3fc01786834fa8e7aab97/Readme.md#option-a). +For more details you can see how we [keep translations dynamic](#keep-translations-dynamic). ## Working with special content @@ -764,6 +762,10 @@ class MyPresenter end ``` +Sometimes there are dynamic translations that the parser can't find when running +`bin/rake gettext:find`. For these scenarios you can use the [`N_` method](https://github.com/grosser/gettext_i18n_rails/blob/c09e38d481e0899ca7d3fc01786834fa8e7aab97/Readme.md#unfound-translations-with-rake-gettextfind). +There's also an alternative method to [translate messages from validation errors](https://github.com/grosser/gettext_i18n_rails/blob/c09e38d481e0899ca7d3fc01786834fa8e7aab97/Readme.md#option-a). + ### Splitting sentences Never split a sentence, as it assumes the sentence's grammar and structure is the same in all diff --git a/doc/development/reusing_abstractions.md b/doc/development/reusing_abstractions.md index 58d1e20394c..e3f523fc6a7 100644 --- a/doc/development/reusing_abstractions.md +++ b/doc/development/reusing_abstractions.md @@ -198,7 +198,7 @@ Several base classes implement the service classes convention. You may consider - `BaseGroupService` for services scoped to groups. Classes that are not service objects should be -[created elsewhere](directory_structure.md#use-namespaces-to-define-bounded-contexts), +[created elsewhere](software_design.md#use-namespaces-to-define-bounded-contexts), such as in `lib`. #### ServiceResponse diff --git a/doc/development/software_design.md b/doc/development/software_design.md new file mode 100644 index 00000000000..03cbbb13d9f --- /dev/null +++ b/doc/development/software_design.md @@ -0,0 +1,141 @@ +--- +stage: none ++group: Engineering Productivity +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + +# Software design guides + +## Use ubiquitous language instead of CRUD terminology + +The code should use the same [ubiquitous language](https://about.gitlab.com/handbook/communication/#ubiquitous-language) +as used in the product and user documentation. Failure to use ubiquitous language correctly +can be a major cause of confusion for contributors and customers when there is constant translation +or use of multiple terms. +This also goes against our [communication strategy](https://about.gitlab.com/handbook/communication/#mecefu-terms). + +In the example below, [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) +terminology introduces ambiguity. The name says we are creating an `epic_issues` +association record, but we are adding an existing issue to an epic. The name `epic_issues`, +used from Rails convention, leaks to higher abstractions such as service objects. +The code speaks the framework jargon rather than ubiquitous language. + +```ruby +# Bad +EpicIssues::CreateService +``` + +Using ubiquitous language makes the code clear and doesn't introduce any +cognitive load to a reader trying to translate the framework jargon. + +```ruby +# Good +Epic::AddExistingIssueService +``` + +You can use CRUD when representing simple concepts that are not ambiguous, +like creating a project, and when matching the existing ubiquitous language. + +```ruby +# OK: Matches the product language. +Projects::CreateService +``` + +New classes and database tables should use ubiquitous language. In this case the model name +and table name follow the Rails convention. + +Existing classes that don't follow ubiquitous language should be renamed, when possible. +Some low level abstractions such as the database tables don't need to be renamed. +For example, use `self.table_name=` when the model name diverges from the table name. + +We can allow exceptions only when renaming is challenging. For example, when the naming is used +for STI, exposed to the user, or if it would be a breaking change. + +## Use namespaces to define bounded contexts + +A healthy application is divided into macro and sub components that represent the contexts at play, +whether they are related to business domain or infrastructure code. + +As GitLab code has so many features and components it's hard to see what contexts are involved. +We should expect any class to be defined inside a module/namespace that represents the contexts where it operates. + +When we namespace classes inside their domain: + +- Similar terminology becomes unambiguous as the domain clarifies the meaning: + For example, `MergeRequests::Diff` and `Notes::Diff`. +- Top-level namespaces could be associated to one or more groups identified as domain experts. +- We can better identify the interactions and coupling between components. + For example, several classes inside `MergeRequests::` domain interact more with `Ci::` + domain and less with `ImportExport::`. + +A good guideline for naming a top-level namespace (bounded context) is to use the related +[feature category](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/data/categories.yml). +For example, `Continuous Integration` feature category maps to `Ci::` namespace. + +```ruby +# bad +class JobArtifact +end + +# good +module Ci + class JobArtifact + end +end +``` + +Projects and Groups are generally container concepts because they identify tenants. +They allow features to exist at the project or group level, like repositories or runners, +but do not nest such features under `Projects::` or `Groups::`. + +`Projects::` and `Groups::` namespaces should be used only for concepts that are strictly related to them: +for example `Project::CreateService` or `Groups::TransferService`. + +For controllers we allow `app/controllers/projects` and `app/controllers/groups` to be exceptions. +We use this convention to indicate the scope of a given web endpoint. + +Do not use the [stage or group name](https://about.gitlab.com/handbook/product/categories/#devops-stages) +because a feature category could be reassigned to a different group in the future. + +```ruby +# bad +module Create + class Commit + end +end + +# good +module Repositories + class Commit + end +end +``` + +On the other hand, a feature category may sometimes be too granular. Features tend to be +treated differently according to Product and Marketing, while they may share a lot of +domain models and behavior under the hood. In this case, having too many bounded contexts +could make them shallow and more coupled with other contexts. + +Bounded contexts (or top-level namespaces) can be seen as macro-components in the overall app. +Good bounded contexts should be [deep](https://medium.com/@nakabonne/depth-of-module-f62dac3c2fdb) +so consider having nested namespaces to further break down complex parts of the domain. +For example, `Ci::Config::`. + +For example, instead of having separate and granular bounded contexts like: `ContainerScanning::`, +`ContainerHostSecurity::`, `ContainerNetworkSecurity::`, we could have: + +```ruby +module ContainerSecurity + module HostSecurity + end + + module NetworkSecurity + end + + module Scanning + end +end +``` + +If classes that are defined into a namespace have a lot in common with classes in other namespaces, +chances are that these two namespaces are part of the same bounded context. diff --git a/doc/subscriptions/img/add-license.png b/doc/subscriptions/img/add-license.png Binary files differnew file mode 100644 index 00000000000..3efb318971c --- /dev/null +++ b/doc/subscriptions/img/add-license.png diff --git a/doc/subscriptions/index.md b/doc/subscriptions/index.md index aab4c87ce5b..98ce40c9e9b 100644 --- a/doc/subscriptions/index.md +++ b/doc/subscriptions/index.md @@ -155,9 +155,6 @@ For qualifying open source projects, the [GitLab for Open Source Program](https: #### Meeting GitLab for Open Source Program requirements -NOTE: -GitLab for Open Source Program benefits apply to an entire GitLab namespace. To qualify for the GitLab for Open Source Program, all projects in an applicant's namespace must meet program requirements. Applicants submit materials related to one project in the applying namespace, and the open source program team uses that project to verify eligibility of the entire namespace. - To meet GitLab for Open Source Program requirements, first add an OSI-approved open source license to all projects in your namespace. To add a license to a project: @@ -165,8 +162,13 @@ To add a license to a project: 1. On the top bar, select **Main menu > Projects** and find your project. 1. On the overview page, select **Add LICENSE**. If the license you want is not available as a license template, manually copy the entire, unaltered [text of your chosen license](https://opensource.org/licenses/alphabetical) into the `LICENSE` file. Note that GitLab defaults to **All rights reserved** if users do not perform this action. +![Add license](img/add-license.png) + Applicants must add the correct license to each project in their respective groups or namespaces. When you're sure you're using OSI-approved licenses for your projects, you can take your screenshots. +NOTE: +GitLab for Open Source Program benefits apply to an entire GitLab namespace. To qualify for the GitLab for Open Source Program, all projects in an applicant's namespace must meet program requirements. Applicants submit materials related to one project in the applying namespace, and the open source program team uses that project to verify eligibility of the entire namespace. + #### Verification for Open Source Program Next, take screenshots of your project to confirm that project's eligibility. You must upload three screenshots: diff --git a/doc/user/project/integrations/slack.md b/doc/user/project/integrations/slack.md index d34c558ebbc..2ded5799c23 100644 --- a/doc/user/project/integrations/slack.md +++ b/doc/user/project/integrations/slack.md @@ -36,10 +36,6 @@ to control GitLab from Slack. Slash commands are configured separately. - *To send messages to channels,* enter the Slack channel names, separated by commas. - *To send direct messages,* use the Member ID found in the user's Slack profile. - - NOTE: - Usernames and private channels are not supported. - 1. In **Webhook**, enter the webhook URL you copied in the [Slack configuration](#configure-slack) step. 1. Optional. In **Username**, enter the username of the Slack bot that sends |