debian-mirror-gitlab/doc/development/contributing/style_guides.md

293 lines
12 KiB
Markdown
Raw Normal View History

2021-01-03 14:25:43 +05:30
---
type: reference, dev
stage: none
group: Development
2022-11-25 23:54:43 +05:30
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
2021-01-03 14:25:43 +05:30
---
2018-12-13 13:39:08 +05:30
# Style guides
2020-04-08 14:13:33 +05:30
## Editor/IDE styling standardization
We use [EditorConfig](https://editorconfig.org/) to automatically apply certain styling
standards before files are saved locally. Most editors/IDEs will honor the `.editorconfig`
settings automatically by default. If your editor/IDE does not automatically support `.editorconfig`,
we suggest investigating to see if a plugin exists. For instance here is the
[plugin for vim](https://github.com/editorconfig/editorconfig-vim).
2021-03-11 19:13:27 +05:30
## Pre-push static analysis with Lefthook
2020-03-13 15:44:24 +05:30
2021-03-11 19:13:27 +05:30
[Lefthook](https://github.com/Arkweid/lefthook) is a Git hooks manager that allows
custom logic to be executed prior to Git committing or pushing. GitLab comes with
Lefthook configuration (`lefthook.yml`), but it must be installed.
2020-03-13 15:44:24 +05:30
2021-03-11 19:13:27 +05:30
We have a `lefthook.yml` checked in but it is ignored until Lefthook is installed.
2020-03-13 15:44:24 +05:30
2021-03-11 19:13:27 +05:30
### Uninstall Overcommit
We were using Overcommit prior to Lefthook, so you may want to uninstall it first with `overcommit --uninstall`.
### Install Lefthook
1. Install the `lefthook` Ruby gem:
```shell
bundle install
```
1. Install Lefthook managed Git hooks:
```shell
bundle exec lefthook install
```
2022-11-25 23:54:43 +05:30
1. Test Lefthook is working by running the Lefthook `pre-push` Git hook:
2021-03-11 19:13:27 +05:30
```shell
2022-11-25 23:54:43 +05:30
bundle exec lefthook run pre-push
2021-03-11 19:13:27 +05:30
```
2022-11-25 23:54:43 +05:30
This should return the lefthook version and the list of executable commands with output.
2021-03-11 19:13:27 +05:30
### Lefthook configuration
2021-01-29 00:20:46 +05:30
2022-04-04 11:22:00 +05:30
Lefthook is configured with a combination of:
2021-01-29 00:20:46 +05:30
2022-04-04 11:22:00 +05:30
- Project configuration in [`lefthook.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lefthook.yml).
- Any [local configuration](https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md#local-config).
2021-01-29 00:20:46 +05:30
2021-03-11 19:13:27 +05:30
### Disable Lefthook temporarily
2021-01-29 00:20:46 +05:30
2021-03-11 19:13:27 +05:30
To disable Lefthook temporarily, you can set the `LEFTHOOK` environment variable to `0`. For instance:
2021-02-22 17:27:13 +05:30
2021-03-11 19:13:27 +05:30
```shell
LEFTHOOK=0 git push ...
2020-03-13 15:44:24 +05:30
```
2021-03-11 19:13:27 +05:30
### Run Lefthook hooks manually
To run the `pre-push` Git hook, run:
```shell
bundle exec lefthook run pre-push
```
2021-01-29 00:20:46 +05:30
2021-03-11 19:13:27 +05:30
For more information, check out [Lefthook documentation](https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md#run-githook-group-directly).
2020-03-13 15:44:24 +05:30
2021-03-11 19:13:27 +05:30
### Skip Lefthook checks per tag
2020-03-13 15:44:24 +05:30
2021-03-11 19:13:27 +05:30
To skip some checks based on tags when pushing, you can set the `LEFTHOOK_EXCLUDE` environment variable. For instance:
```shell
LEFTHOOK_EXCLUDE=frontend,documentation git push ...
```
2021-09-30 23:02:18 +05:30
As an alternative, you can create `lefthook-local.yml` with this structure:
```yaml
pre-push:
exclude_tags:
- frontend
- documentation
```
2021-03-11 19:13:27 +05:30
For more information, check out [Lefthook documentation](https://github.com/Arkweid/lefthook/blob/master/docs/full_guide.md#skip-some-tags-on-the-fly).
2020-03-13 15:44:24 +05:30
2021-09-30 23:02:18 +05:30
### Skip or enable a specific Lefthook check
To skip or enable a check based on its name when pushing, you can add `skip: true`
or `skip: false` to the `lefthook-local.yml` section for that hook. For instance,
you might want to enable the gettext check to detect issues with `locale/gitlab.pot`:
```yaml
pre-push:
commands:
gettext:
skip: false
```
For more information, check out [Lefthook documentation Skipping commands section](https://github.com/evilmartians/lefthook/blob/master/docs/full_guide.md#skipping-commands).
2020-03-13 15:44:24 +05:30
## Ruby, Rails, RSpec
Our codebase style is defined and enforced by [RuboCop](https://github.com/rubocop-hq/rubocop).
You can check for any offenses locally with `bundle exec rubocop --parallel`.
On the CI, this is automatically checked by the `static-analysis` jobs.
2021-06-08 01:23:25 +05:30
In addition, you can [integrate RuboCop](../developing_with_solargraph.md) into
supported IDEs using the [Solargraph](https://github.com/castwide/solargraph) gem.
2020-03-13 15:44:24 +05:30
For RuboCop rules that we have not taken a decision on yet, we follow the
[Ruby Style Guide](https://github.com/rubocop-hq/ruby-style-guide),
[Rails Style Guide](https://github.com/rubocop-hq/rails-style-guide), and
[RSpec Style Guide](https://github.com/rubocop-hq/rspec-style-guide) as general
guidelines to write idiomatic Ruby/Rails/RSpec, but reviewers/maintainers should
be tolerant and not too pedantic about style.
Similarly, some RuboCop rules are currently disabled, and for those,
reviewers/maintainers must not ask authors to use one style or the other, as both
are accepted. This isn't an ideal situation since this leaves space for
[bike-shedding](https://en.wiktionary.org/wiki/bikeshedding), and ideally we
should enable all RuboCop rules to avoid style-related
2021-10-27 15:23:28 +05:30
discussions/nitpicking/back-and-forth in reviews. There are some styles that
commonly come up in reviews that are not enforced, the
[GitLab Ruby style guide](../backend/ruby_style_guide.md) includes a non-exhaustive
list of these topics.
2020-03-13 15:44:24 +05:30
Additionally, we have a dedicated
2020-05-24 23:13:21 +05:30
[newlines style guide](../newlines_styleguide.md), as well as dedicated
2020-03-13 15:44:24 +05:30
[test-specific style guides and best practices](../testing_guide/index.md).
2020-07-28 23:09:34 +05:30
### Creating new RuboCop cops
Typically it is better for the linting rules to be enforced programmatically as it
reduces the aforementioned [bike-shedding](https://en.wiktionary.org/wiki/bikeshedding).
To that end, we encourage creation of new RuboCop rules in the codebase.
2022-10-11 01:57:18 +05:30
We maintain Cops across several Ruby code bases, and not all of them are
2021-09-30 23:02:18 +05:30
specific to the GitLab application.
2020-07-28 23:09:34 +05:30
When creating a new cop that could be applied to multiple applications, we encourage you
to add it to our [GitLab Styles](https://gitlab.com/gitlab-org/gitlab-styles) gem.
2021-09-30 23:02:18 +05:30
If the Cop targets rules that only apply to the main GitLab application,
it should be added to [GitLab](https://gitlab.com/gitlab-org/gitlab) instead.
2020-07-28 23:09:34 +05:30
2022-11-25 23:54:43 +05:30
### Cop grace period
A cop is in a "grace period" if it is enabled and has `Details: grace period` defined in its TODO YAML configuration.
On the default branch, all of the offenses from cops in the ["grace period"](../rake_tasks.md#run-rubocop-in-graceful-mode) will not fail the RuboCop CI job. The job will notify Slack in the `#f_rubocop` channel when offenses have been silenced in the scheduled pipeline. However, on merge request pipelines, the RuboCop job will fail.
A grace period can safely be lifted as soon as there are no warnings for 2 weeks in the `#f_rubocop` channel on Slack.
### Enabling a new cop
1. Enable the new cop in `.rubocop.yml` (if not already done via [`gitlab-styles`](https://gitlab.com/gitlab-org/ruby/gems/gitlab-styles)).
1. [Generate TODOs for the new cop](../rake_tasks.md#generate-initial-rubocop-todo-list).
1. [Set the new cop to "grace period"](#cop-grace-period).
1. Create an issue to fix TODOs and encourage Community contributions (via ~"good for new contributors" and/or ~"Seeking community contributions"). [See some examples](https://gitlab.com/gitlab-org/gitlab/-/issues/?sort=created_date&state=opened&label_name%5B%5D=good%20for%20new%20contributors&label_name%5B%5D=static%20code%20analysis&first_page_size=20).
1. Create an issue to remove "grace period" after 2 weeks silence in `#f_rubocop` Slack channel. ([See an example](https://gitlab.com/gitlab-org/gitlab/-/issues/374903).)
### Silenced offenses
When offenses are silenced for cops in ["grace period"](#cop-grace-period),
the `#f_rubocop` Slack channel receives a notification message every two hours.
To fix this issue:
1. Find cops with silenced offenses in the linked CI job.
1. [Generate TODOs](../rake_tasks.md#generate-initial-rubocop-todo-list) for these cops.
2022-10-11 01:57:18 +05:30
#### RuboCop node pattern
When creating [node patterns](https://docs.rubocop.org/rubocop-ast/node_pattern.html) to match
Ruby's AST, you can use [`scripts/rubocop-parse`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/scripts/rubocop-parse)
2022-11-25 23:54:43 +05:30
to display the AST of a Ruby expression, to help you create the matcher.
2022-10-11 01:57:18 +05:30
See also [!97024](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97024).
2021-02-22 17:27:13 +05:30
### Resolving RuboCop exceptions
When the number of RuboCop exceptions exceed the default [`exclude-limit` of 15](https://docs.rubocop.org/rubocop/1.2/usage/basic_usage.html#command-line-flags),
we may want to resolve exceptions over multiple commits. To minimize confusion,
we should track our progress through the exception list.
2022-05-07 20:08:51 +05:30
The preferred way to [generate the initial list or a list for specific RuboCop rules](../rake_tasks.md#generate-initial-rubocop-todo-list)
is to run the Rake task `rubocop:todo:generate`:
2021-02-22 17:27:13 +05:30
```shell
2022-05-07 20:08:51 +05:30
# Initial list
2021-11-11 11:23:49 +05:30
bundle exec rake rubocop:todo:generate
2022-05-07 20:08:51 +05:30
# List for specific RuboCop rules
bundle exec rake 'rubocop:todo:generate[Gitlab/NamespacedClass,Lint/Syntax]'
2021-02-22 17:27:13 +05:30
```
2022-05-07 20:08:51 +05:30
This Rake task creates or updates the exception list in `.rubocop_todo/`. For
example, the configuration for the RuboCop rule `Gitlab/NamespacedClass` is
located in `.rubocop_todo/gitlab/namespaced_class.yml`.
Make sure to commit any changes in `.rubocop_todo/` after running the Rake task.
2021-02-22 17:27:13 +05:30
2021-04-17 20:07:23 +05:30
### Reveal existing RuboCop exceptions
To reveal existing RuboCop exceptions in the code that have been excluded via `.rubocop_todo.yml` and
2022-01-26 12:08:38 +05:30
`.rubocop_todo/**/*.yml`, set the environment variable `REVEAL_RUBOCOP_TODO` to `1`.
2021-04-17 20:07:23 +05:30
This allows you to reveal existing RuboCop exceptions during your daily work cycle and fix them along the way.
NOTE:
2022-01-26 12:08:38 +05:30
Define permanent `Exclude`s in `.rubocop.yml` instead of `.rubocop_todo/**/*.yml`.
2021-04-17 20:07:23 +05:30
2020-03-13 15:44:24 +05:30
## Database migrations
See the dedicated [Database Migrations Style Guide](../migration_style_guide.md).
## JavaScript
See the dedicated [JS Style Guide](../fe_guide/style/javascript.md).
## SCSS
See the dedicated [SCSS Style Guide](../fe_guide/style/scss.md).
## Go
See the dedicated [Go standards and style guidelines](../go_guide/index.md).
## Shell commands (Ruby)
See the dedicated [Guidelines for shell commands in the GitLab codebase](../shell_commands.md).
## Shell scripting
See the dedicated [Shell scripting standards and style guidelines](../shell_scripting_guide/index.md).
## Markdown
2021-03-11 19:13:27 +05:30
<!-- vale gitlab.Spelling = NO -->
2020-07-28 23:09:34 +05:30
We're following [Ciro Santilli's Markdown Style Guide](https://cirosantilli.com/markdown-style-guide/).
2020-03-13 15:44:24 +05:30
2021-03-11 19:13:27 +05:30
<!-- vale gitlab.Spelling = YES -->
2020-03-13 15:44:24 +05:30
## Documentation
2021-01-29 00:20:46 +05:30
See the dedicated [Documentation Style Guide](../documentation/styleguide/index.md).
2020-03-13 15:44:24 +05:30
2022-10-11 01:57:18 +05:30
### Guidelines for good practices
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36576/) in GitLab 13.2 as GitLab Development documentation.
*Good practice* examples demonstrate encouraged ways of writing code while
comparing with examples of practices to avoid. These examples are labeled as
*Bad* or *Good*. In GitLab development guidelines, when presenting the cases,
it's recommended to follow a *first-bad-then-good* strategy. First demonstrate
the *Bad* practice (how things *could* be done, which is often still working
code), and then how things *should* be done better, using a *Good* example. This
is typically an improved example of the same code.
Consider the following guidelines when offering examples:
- First, offer the *Bad* example, and then the *Good* one.
- When only one bad case and one good case is given, use the same code block.
- When more than one bad case or one good case is offered, use separated code
blocks for each. With many examples being presented, a clear separation helps
the reader to go directly to the good part. Consider offering an explanation
(for example, a comment, or a link to a resource) on why something is bad
practice.
- Better and best cases can be considered part of the good cases' code block.
In the same code block, precede each with comments: `# Better` and `# Best`.
Although the bad-then-good approach is acceptable for the GitLab development
guidelines, do not use it for user documentation. For user documentation, use
*Do* and *Don't*. For examples, see the [Pajamas Design System](https://design.gitlab.com/content/punctuation/).
2020-03-13 15:44:24 +05:30
## Python
See the dedicated [Python Development Guidelines](../python_guide/index.md).
## Misc
Code should be written in [US English](https://en.wikipedia.org/wiki/American_English).