summaryrefslogtreecommitdiff
path: root/doc/development
diff options
context:
space:
mode:
Diffstat (limited to 'doc/development')
-rw-r--r--doc/development/README.md1
-rw-r--r--doc/development/fe_guide/style_guide_scss.md2
-rw-r--r--doc/development/gitaly.md23
-rw-r--r--doc/development/testing_guide/end_to_end_tests.md80
-rw-r--r--doc/development/testing_guide/index.md8
-rw-r--r--doc/development/testing_guide/testing_levels.md3
-rw-r--r--doc/development/utilities.md92
-rw-r--r--doc/development/what_requires_downtime.md57
-rw-r--r--doc/development/writing_documentation.md4
9 files changed, 267 insertions, 3 deletions
diff --git a/doc/development/README.md b/doc/development/README.md
index b624aa37c70..12cca9f84b7 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -27,6 +27,7 @@ comments: false
## Backend guides
+- [GitLab utilities](utilities.md)
- [API styleguide](api_styleguide.md) Use this styleguide if you are
contributing to the API.
- [Sidekiq guidelines](sidekiq_style_guide.md) for working with Sidekiq workers
diff --git a/doc/development/fe_guide/style_guide_scss.md b/doc/development/fe_guide/style_guide_scss.md
index 77b308c4a43..86a8b4135af 100644
--- a/doc/development/fe_guide/style_guide_scss.md
+++ b/doc/development/fe_guide/style_guide_scss.md
@@ -216,7 +216,7 @@ If you want a line or set of lines to be ignored by the linter, you can use
```scss
// This lint rule is disabled because the class name comes from a gem.
// scss-lint:disable SelectorFormat
-.ui_charcoal {
+.ui_indigo {
background-color: #333;
}
// scss-lint:enable SelectorFormat
diff --git a/doc/development/gitaly.md b/doc/development/gitaly.md
index ca2048c7019..26abf967dcf 100644
--- a/doc/development/gitaly.md
+++ b/doc/development/gitaly.md
@@ -97,6 +97,29 @@ describe 'Gitaly Request count tests' do
end
```
+## Running tests with a locally modified version of Gitaly
+
+Normally, gitlab-ce/ee tests use a local clone of Gitaly in `tmp/tests/gitaly`
+pinned at the version specified in GITALY_SERVER_VERSION. If you want
+to run tests locally against a modified version of Gitaly you can
+replace `tmp/tests/gitaly` with a symlink.
+
+```shell
+rm -rf tmp/tests/gitaly
+ln -s /path/to/gitaly tmp/tests/gitaly
+```
+
+Make sure you run `make` in your local Gitaly directory before running
+tests. Otherwise, Gitaly will fail to boot.
+
+If you make changes to your local Gitaly in between test runs you need
+to manually run `make` again.
+
+Note that CI tests will not use your locally modified version of
+Gitaly. To use a custom Gitaly version in CI you need to update
+GITALY_SERVER_VERSION. You can use the format `=revision` to use a
+non-tagged commit from https://gitlab.com/gitlab-org/gitaly in CI.
+
---
[Return to Development documentation](README.md)
diff --git a/doc/development/testing_guide/end_to_end_tests.md b/doc/development/testing_guide/end_to_end_tests.md
new file mode 100644
index 00000000000..abe5b06e0f0
--- /dev/null
+++ b/doc/development/testing_guide/end_to_end_tests.md
@@ -0,0 +1,80 @@
+# End-to-End Testing
+
+## What is End-to-End testing?
+
+End-to-End testing is a strategy used to check whether your application works
+as expected across entire software stack and architecture, including
+integration of all microservices and components that are supposed to work
+together.
+
+## How do we test GitLab?
+
+We use [Omnibus GitLab][omnibus-gitlab] to build GitLab packages and then we
+test these packages using [GitLab QA][gitlab-qa] project, which is entirely
+black-box, click-driven testing framework.
+
+### Testing nightly builds
+
+We run scheduled pipeline each night to test nightly builds created by Omnibus.
+You can find these nightly pipelines at [GitLab QA pipelines page][gitlab-qa-pipelines].
+
+### Testing code in merge requests
+
+It is possible to run end-to-end tests (eventually being run within a
+[GitLab QA pipeline][gitlab-qa-pipelines]) for a merge request by triggering
+the `package-qa` manual action, that should be present in a merge request
+widget.
+
+Mmanual action that starts end-to-end tests is also available in merge requests
+in Omnibus GitLab project.
+
+Below you can read more about how to use it and how does it work.
+
+#### How does it work?
+
+Currently, we are using _multi-project pipeline_-like approach to run QA
+pipelines.
+
+1. Developer triggers a manual action, that can be found in CE and EE merge
+requests. This starts a chain of pipelines in multiple projects.
+
+1. The script being executed triggers a pipeline in GitLab Omnibus and waits
+for the resulting status. We call this a _status attribution_.
+
+1. GitLab packages are being built in Omnibus pipeline. Packages are going to be
+pushed to Container Registry.
+
+1. When packages are ready, and available in the registry, a final step in the
+pipeline, that is now running in Omnibus, triggers a new pipeline in the GitLab
+QA project. It also waits for a resulting status.
+
+1. GitLab QA pulls images from the registry, spins-up containers and runs tests
+against a test environment that has been just orchestrated by the `gitlab-qa`
+tool.
+
+1. The result of the GitLab QA pipeline is being propagated upstream, through
+Omnibus, back to CE / EE merge request.
+
+#### How do I write tests?
+
+In order to write new tests, you first need to learn more about GitLab QA
+architecture. See the [documentation about it][gitlab-qa-architecture] in
+GitLab QA project.
+
+Once you decided where to put test environment orchestration scenarios and
+instance specs, take a look at the [relevant documentation][instance-qa-readme]
+and examples in [the `qa/` directory][instance-qa-examples].
+
+## Where can I ask for help?
+
+You can ask question in the `#qa` channel on Slack (GitLab internal) or you can
+find an issue you would like to work on in [the issue tracker][gitlab-qa-issues]
+and start a new discussion there.
+
+[omnibus-gitlab]: https://gitlab.com/gitlab-org/omnibus-gitlab
+[gitlab-qa]: https://gitlab.com/gitlab-org/gitlab-qa
+[gitlab-qa-pipelines]: https://gitlab.com/gitlab-org/gitlab-qa/pipelines
+[gitlab-qa-architecture]: https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/architecture.md
+[gitlab-qa-issues]: https://gitlab.com/gitlab-org/gitlab-qa/issues
+[instance-qa-readme]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/README.md
+[instance-qa-examples]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/qa
diff --git a/doc/development/testing_guide/index.md b/doc/development/testing_guide/index.md
index 65386f231a0..74d09eb91ff 100644
--- a/doc/development/testing_guide/index.md
+++ b/doc/development/testing_guide/index.md
@@ -65,6 +65,13 @@ Everything you should know about how to test Rake tasks.
---
+## [End-to-end tests](end_to_end_tests.md)
+
+Everything you should know about how to run end-to-end tests using
+[GitLab QA][gitlab-qa] testing framework.
+
+---
+
## Spinach (feature) tests
GitLab [moved from Cucumber to Spinach](https://github.com/gitlabhq/gitlabhq/pull/1426)
@@ -89,3 +96,4 @@ test should be re-implemented using RSpec instead.
[Capybara]: https://github.com/teamcapybara/capybara
[Karma]: http://karma-runner.github.io/
[Jasmine]: https://jasmine.github.io/
+[gitlab-qa]: https://gitlab.com/gitlab-org/gitlab-qa
diff --git a/doc/development/testing_guide/testing_levels.md b/doc/development/testing_guide/testing_levels.md
index 1cbd4350284..4adf0dc7c7a 100644
--- a/doc/development/testing_guide/testing_levels.md
+++ b/doc/development/testing_guide/testing_levels.md
@@ -121,6 +121,9 @@ running feature tests (i.e. using Capybara) against it.
The actual test scenarios and steps are [part of GitLab Rails] so that they're
always in-sync with the codebase.
+Read a separate document about [end-to-end tests](end_to_end_tests.md) to
+learn more.
+
[multiple pieces]: ../architecture.md#components
[GitLab Shell]: https://gitlab.com/gitlab-org/gitlab-shell
[GitLab Workhorse]: https://gitlab.com/gitlab-org/gitlab-workhorse
diff --git a/doc/development/utilities.md b/doc/development/utilities.md
new file mode 100644
index 00000000000..951c3ef85ce
--- /dev/null
+++ b/doc/development/utilities.md
@@ -0,0 +1,92 @@
+# GitLab utilities
+
+We developed a number of utilities to ease development.
+
+## [`MergeHash`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/utils/merge_hash.rb)
+
+* Deep merges an array of hashes:
+
+ ``` ruby
+ Gitlab::Utils::MergeHash.merge(
+ [{ hello: ["world"] },
+ { hello: "Everyone" },
+ { hello: { greetings: ['Bonjour', 'Hello', 'Hallo', 'Dzien dobry'] } },
+ "Goodbye", "Hallo"]
+ )
+ ```
+
+ Gives:
+
+ ``` ruby
+ [
+ {
+ hello:
+ [
+ "world",
+ "Everyone",
+ { greetings: ['Bonjour', 'Hello', 'Hallo', 'Dzien dobry'] }
+ ]
+ },
+ "Goodbye"
+ ]
+ ```
+
+* Extracts all keys and values from a hash into an array:
+
+ ``` ruby
+ Gitlab::Utils::MergeHash.crush(
+ { hello: "world", this: { crushes: ["an entire", "hash"] } }
+ )
+ ```
+
+ Gives:
+
+ ``` ruby
+ [:hello, "world", :this, :crushes, "an entire", "hash"]
+ ```
+
+## [`StrongMemoize`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/utils/strong_memoize.rb)
+
+* Memoize the value even if it is `nil` or `false`.
+
+ We often do `@value ||= compute`, however this doesn't work well if
+ `compute` might eventually give `nil` and we don't want to compute again.
+ Instead we could use `defined?` to check if the value is set or not.
+ However it's tedious to write such pattern, and `StrongMemoize` would
+ help us use such pattern.
+
+ Instead of writing patterns like this:
+
+ ``` ruby
+ class Find
+ def result
+ return @result if defined?(@result)
+
+ @result = search
+ end
+ end
+ ```
+
+ We could write it like:
+
+ ``` ruby
+ class Find
+ include Gitlab::Utils::StrongMemoize
+
+ def result
+ strong_memoize(:result) do
+ search
+ end
+ end
+ end
+ ```
+
+* Clear memoization
+
+ ``` ruby
+ class Find
+ include Gitlab::Utils::StrongMemoize
+ end
+
+ Find.new.clear_memoization(:result)
+ ```
diff --git a/doc/development/what_requires_downtime.md b/doc/development/what_requires_downtime.md
index 05e0a64af18..9d0c62ecc35 100644
--- a/doc/development/what_requires_downtime.md
+++ b/doc/development/what_requires_downtime.md
@@ -195,6 +195,63 @@ end
And that's it, we're done!
+## Changing Column Types For Large Tables
+
+While `change_column_type_concurrently` can be used for changing the type of a
+column without downtime it doesn't work very well for large tables. Because all
+of the work happens in sequence the migration can take a very long time to
+complete, preventing a deployment from proceeding.
+`change_column_type_concurrently` can also produce a lot of pressure on the
+database due to it rapidly updating many rows in sequence.
+
+To reduce database pressure you should instead use
+`change_column_type_using_background_migration` when migrating a column in a
+large table (e.g. `issues`). This method works similar to
+`change_column_type_concurrently` but uses background migration to spread the
+work / load over a longer time period, without slowing down deployments.
+
+Usage of this method is fairly simple:
+
+```ruby
+class ExampleMigration < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ class Issue < ActiveRecord::Base
+ self.table_name = 'issues'
+
+ include EachBatch
+
+ def self.to_migrate
+ where('closed_at IS NOT NULL')
+ end
+ end
+
+ def up
+ change_column_type_using_background_migration(
+ Issue.to_migrate,
+ :closed_at,
+ :datetime_with_timezone
+ )
+ end
+
+ def down
+ change_column_type_using_background_migration(
+ Issue.to_migrate,
+ :closed_at,
+ :datetime
+ )
+ end
+end
+```
+
+This would change the type of `issues.closed_at` to `timestamp with time zone`.
+
+Keep in mind that the relation passed to
+`change_column_type_using_background_migration` _must_ include `EachBatch`,
+otherwise it will raise a `TypeError`.
+
## Adding Indexes
Adding indexes is an expensive process that blocks INSERT and UPDATE queries for
diff --git a/doc/development/writing_documentation.md b/doc/development/writing_documentation.md
index 43a79ffcaa5..133ac0234cf 100644
--- a/doc/development/writing_documentation.md
+++ b/doc/development/writing_documentation.md
@@ -15,7 +15,7 @@ request introducing these changes must be accompanied by the documentation
(either updating existing ones or creating new ones). This is also valid when
changes are introduced to the UI.
-The one resposible for writing the first piece of documentation is the developer who
+The one responsible for writing the first piece of documentation is the developer who
wrote the code. It's the job of the Product Manager to ensure all features are
shipped with its docs, whether is a small or big change. At the pace GitLab evolves,
this is the only way to keep the docs up-to-date. If you have any questions about it,
@@ -31,7 +31,7 @@ Every major feature (regardless if present in GitLab Community or Enterprise edi
should present, at the beginning of the document, two main sections: **overview** and
**use cases**. Every GitLab EE-only feature should also contain these sections.
-**Overview**: at the name suggests, the goal here is to provide an overview of the feature.
+**Overview**: as the name suggests, the goal here is to provide an overview of the feature.
Describe what is it, what it does, why it is important/cool/nice-to-have,
what problem it solves, and what you can do with this feature that you couldn't
do before.